From 10ad54b8a9d757704b763827e3aa9338fb23b3b0 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 9 Sep 2016 16:12:47 -0700 Subject: [PATCH 001/271] Initial commit Add a bunch of builders and new tests. All tests currently passing. Get ready to publish. Almost ready to publish. Fix pubspec. --- pkgs/code_builder/.gitignore | 30 +++ pkgs/code_builder/.travis.yml | 7 + pkgs/code_builder/AUTHORS | 6 + pkgs/code_builder/CHANGELOG.md | 5 + pkgs/code_builder/CONTRIBUTING.md | 33 +++ pkgs/code_builder/LICENSE | 26 ++ pkgs/code_builder/README.md | 0 pkgs/code_builder/analysis_options.yaml | 41 +++ pkgs/code_builder/lib/code_builder.dart | 102 ++++++++ pkgs/code_builder/lib/dart/core.dart | 137 ++++++++++ .../lib/src/annotation_builder.dart | 98 +++++++ pkgs/code_builder/lib/src/class_builder.dart | 97 +++++++ .../lib/src/constructor_builder.dart | 60 +++++ .../lib/src/expression_builder.dart | 186 +++++++++++++ pkgs/code_builder/lib/src/field_builder.dart | 110 ++++++++ pkgs/code_builder/lib/src/file_builder.dart | 133 ++++++++++ pkgs/code_builder/lib/src/method_builder.dart | 174 +++++++++++++ .../lib/src/parameter_builder.dart | 130 ++++++++++ pkgs/code_builder/lib/src/pretty_printer.dart | 103 ++++++++ .../lib/src/statement_builder.dart | 10 + pkgs/code_builder/lib/src/type_builder.dart | 32 +++ .../lib/testing/equals_source.dart | 73 ++++++ pkgs/code_builder/pubspec.yaml | 17 ++ .../test/builders/class_builder_test.dart | 161 ++++++++++++ .../test/builders/field_builder_test.dart | 49 ++++ .../test/builders/file_builder_test.dart | 46 ++++ .../test/builders/method_builder_test.dart | 244 ++++++++++++++++++ pkgs/code_builder/test/integration_test.dart | 58 +++++ pkgs/code_builder/tool/travis.sh | 28 ++ 29 files changed, 2196 insertions(+) create mode 100644 pkgs/code_builder/.gitignore create mode 100644 pkgs/code_builder/.travis.yml create mode 100644 pkgs/code_builder/AUTHORS create mode 100644 pkgs/code_builder/CHANGELOG.md create mode 100644 pkgs/code_builder/CONTRIBUTING.md create mode 100644 pkgs/code_builder/LICENSE create mode 100644 pkgs/code_builder/README.md create mode 100644 pkgs/code_builder/analysis_options.yaml create mode 100644 pkgs/code_builder/lib/code_builder.dart create mode 100644 pkgs/code_builder/lib/dart/core.dart create mode 100644 pkgs/code_builder/lib/src/annotation_builder.dart create mode 100644 pkgs/code_builder/lib/src/class_builder.dart create mode 100644 pkgs/code_builder/lib/src/constructor_builder.dart create mode 100644 pkgs/code_builder/lib/src/expression_builder.dart create mode 100644 pkgs/code_builder/lib/src/field_builder.dart create mode 100644 pkgs/code_builder/lib/src/file_builder.dart create mode 100644 pkgs/code_builder/lib/src/method_builder.dart create mode 100644 pkgs/code_builder/lib/src/parameter_builder.dart create mode 100644 pkgs/code_builder/lib/src/pretty_printer.dart create mode 100644 pkgs/code_builder/lib/src/statement_builder.dart create mode 100644 pkgs/code_builder/lib/src/type_builder.dart create mode 100644 pkgs/code_builder/lib/testing/equals_source.dart create mode 100644 pkgs/code_builder/pubspec.yaml create mode 100644 pkgs/code_builder/test/builders/class_builder_test.dart create mode 100644 pkgs/code_builder/test/builders/field_builder_test.dart create mode 100644 pkgs/code_builder/test/builders/file_builder_test.dart create mode 100644 pkgs/code_builder/test/builders/method_builder_test.dart create mode 100644 pkgs/code_builder/test/integration_test.dart create mode 100755 pkgs/code_builder/tool/travis.sh diff --git a/pkgs/code_builder/.gitignore b/pkgs/code_builder/.gitignore new file mode 100644 index 000000000..8d4854698 --- /dev/null +++ b/pkgs/code_builder/.gitignore @@ -0,0 +1,30 @@ +# See https://www.dartlang.org/tools/private-files.html + +# Files and directories created by pub +.buildlog +.packages +.project +.pub +**/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 diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml new file mode 100644 index 000000000..5826f9bc1 --- /dev/null +++ b/pkgs/code_builder/.travis.yml @@ -0,0 +1,7 @@ +language: dart + +dart: + - dev + - stable + +script: ./tool/travis.sh diff --git a/pkgs/code_builder/AUTHORS b/pkgs/code_builder/AUTHORS new file mode 100644 index 000000000..609e0dce0 --- /dev/null +++ b/pkgs/code_builder/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. \ No newline at end of file diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md new file mode 100644 index 000000000..a11689988 --- /dev/null +++ b/pkgs/code_builder/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 0.1.0 + +- Initial version diff --git a/pkgs/code_builder/CONTRIBUTING.md b/pkgs/code_builder/CONTRIBUTING.md new file mode 100644 index 000000000..0bf17f075 --- /dev/null +++ b/pkgs/code_builder/CONTRIBUTING.md @@ -0,0 +1,33 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. + +### File headers +All files in the project must start with the following header. + + // 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. + +### The small print +Contributions made by corporations are covered by a different agreement than the +one above, the +[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). \ No newline at end of file diff --git a/pkgs/code_builder/LICENSE b/pkgs/code_builder/LICENSE new file mode 100644 index 000000000..4ded3fa11 --- /dev/null +++ b/pkgs/code_builder/LICENSE @@ -0,0 +1,26 @@ +Copyright 2016, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml new file mode 100644 index 000000000..f7145dbf2 --- /dev/null +++ b/pkgs/code_builder/analysis_options.yaml @@ -0,0 +1,41 @@ +analyzer: + strong-mode: true +linter: + rules: + - avoid_empty_else + - comment_references + - control_flow_in_finally + - empty_statements + - hash_and_equals + - iterable_contains_unrelated_type + - list_remove_unrelated_type + - test_types_in_equals + - throw_in_finally + - unrelated_type_equality_checks + - valid_regexps + - always_declare_return_types + - annotate_overrides + - avoid_as + - avoid_init_to_null + - avoid_return_types_on_setters + - await_only_futures + - camel_case_types + - constant_identifier_names + - empty_catches + - 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 diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart new file mode 100644 index 000000000..bcde81ff2 --- /dev/null +++ b/pkgs/code_builder/lib/code_builder.dart @@ -0,0 +1,102 @@ +// 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. + +/// 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:analyzer/src/dart/ast/token.dart'; +import 'package:analyzer/src/generated/java_core.dart'; +import 'package:dart_style/dart_style.dart'; +import 'package:meta/meta.dart'; + +part 'src/annotation_builder.dart'; +part 'src/class_builder.dart'; +part 'src/constructor_builder.dart'; +part 'src/expression_builder.dart'; +part 'src/field_builder.dart'; +part 'src/file_builder.dart'; +part 'src/method_builder.dart'; +part 'src/parameter_builder.dart'; +part 'src/pretty_printer.dart'; +part 'src/statement_builder.dart'; +part 'src/type_builder.dart'; + +/// Base class for building and emitting a Dart language [AstNode]. +abstract class CodeBuilder { + /// Returns a copy-safe [AstNode] representing the current builder state. + A toAst(); +} + +// Simplifies some of the builders by having a mutable node we clone from. +abstract class _AbstractCodeBuilder extends CodeBuilder { + final A _astNode; + + _AbstractCodeBuilder._(this._astNode); + + /// Returns a copy-safe [AstNode] representing the current builder state. + @override + A toAst() => _cloneAst/**/(_astNode); + + @override + String toString() => '$runtimeType: ${_astNode.toSource()}'; +} + +/// Marker interface for builders that need an import to work. +/// +/// **NOTE**: This currently (as of 0.2.0) has no effect. It is planned that +/// the [FileBuilder] will be able to act as a scope 'resolver' and subtly +/// rewrite the AST tree to use prefixing if required (or requested). +abstract class RequiresImport implements CodeBuilder { + /// Imports that are required for this AST to work. + List get requiredImports; + + /// Creates a copy-safe [AstNode] representing the current builder state. + /// + /// Uses [scope] to output an AST re-written to use appropriate prefixes. + A toScopedAst(FileBuilder scope) => throw new UnimplementedError(); +} + +// Creates a defensive copy of an AST node. +AstNode/*=E*/ _cloneAst/**/(AstNode/*=E*/ astNode) { + return new AstCloner().cloneNode/**/(astNode); +} + +final DartFormatter _dartfmt = new DartFormatter(); + +/// Returns [source] formatted by `dartfmt`. +@visibleForTesting +String dartfmt(String source) => _dartfmt.format(source); + +Literal _stringLit(String s) { + return new SimpleStringLiteral(new StringToken(TokenType.STRING, s, 0), s); +} + +Identifier _stringId(String s) { + return new SimpleIdentifier(new StringToken(TokenType.STRING, s, 0)); +} diff --git a/pkgs/code_builder/lib/dart/core.dart b/pkgs/code_builder/lib/dart/core.dart new file mode 100644 index 000000000..f8c4e2170 --- /dev/null +++ b/pkgs/code_builder/lib/dart/core.dart @@ -0,0 +1,137 @@ +// 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:core` library for use in code generation. +/// +/// This library is currently *experimental*, and is subject to change; it +/// currently is manually written but there might be a strong use case for this +/// to be automatically generated (at least partially) in the near future. +library code_builder.dart.core; + +import 'package:code_builder/code_builder.dart'; + +/// An alias for `new AnnotationBuilder('override')`. +const AnnotationBuilder atOverride = const AnnotationBuilder.reference( + 'override', + 'dart:core', +); + +/// An alias for `new TypeBuilder('bool')`. +const TypeBuilder typeBool = const TypeBuilder( + 'bool', + importFrom: 'dart:core', +); + +/// An alias for `new TypeBuilder('DateTime')`. +const TypeBuilder typeDateTime = const TypeBuilder( + 'DateTime', + importFrom: 'dart:core', +); + +/// An alias for `new TypeBuilder('double')`. +const TypeBuilder typeDouble = const TypeBuilder( + 'double', + importFrom: 'dart:core', +); + +/// An alias for `new TypeBuilder('Duration')`. +const TypeBuilder typeDuration = const TypeBuilder( + 'Duration', + importFrom: 'dart:core', +); + +/// An alias for `new TypeBuilder('Expando')`. +const TypeBuilder typeExpando = const TypeBuilder( + 'Expando', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Function')`. +const TypeBuilder typeFunction = const TypeBuilder( + 'Function', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('int')`. +const TypeBuilder typeInt = const TypeBuilder( + 'int', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Iterable')`. +const TypeBuilder typeIterable = const TypeBuilder( + 'Iterable', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('List')`. +const TypeBuilder typeList = const TypeBuilder( + 'List', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Map')`. +const TypeBuilder typeMap = const TypeBuilder( + 'Map', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Null')`. +const TypeBuilder typeNull = const TypeBuilder( + 'Null', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('num')`. +const TypeBuilder typeNum = const TypeBuilder( + 'num', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Object')`. +const TypeBuilder typeObject = const TypeBuilder( + 'Object', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Set')`. +const TypeBuilder typeSet = const TypeBuilder( + 'Set', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('String')`. +const TypeBuilder typeString = const TypeBuilder( + 'String', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Symbol')`. +const TypeBuilder typeSymbol = const TypeBuilder( + 'Symbol', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Type')`. +const TypeBuilder typeType = const TypeBuilder( + 'Type', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Uri')`. +const TypeBuilder typeUri = const TypeBuilder( + 'Uri', + importFrom: 'dart:core', +); + +/// Creates either a `@deprecated` or `@Deprecated('Message')` annotation. +AnnotationBuilder atDeprecated([String message]) { + if (message == null) { + return new AnnotationBuilder.reference('deprecated', 'dart:core'); + } + return new AnnotationBuilder.invoke( + 'Deprecated', + positional: [new LiteralString(message)], + ); +} diff --git a/pkgs/code_builder/lib/src/annotation_builder.dart b/pkgs/code_builder/lib/src/annotation_builder.dart new file mode 100644 index 000000000..885bc409e --- /dev/null +++ b/pkgs/code_builder/lib/src/annotation_builder.dart @@ -0,0 +1,98 @@ +// 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. + +part of code_builder; + +/// Builds a metadata [Annotation] to be added to other AST elements. +/// +/// An annotation may either be a reference to an existing `const` identifier +/// _or_ to an invocation of a `const` class constructor. +/// +/// To create a `@doNotUse` reference, use [AnnotationBuilder.reference]: +/// const doNotUse = #do_not_use; +/// +/// @doNotUse +/// void destroyTheWorld() { ... } +/// +/// To create a `@DoNotUse('Blows up')` use [AnnotationBuilder.invoke]. +abstract class AnnotationBuilder implements RequiresImport { + /// Create a new annotated `const` [constructor] invocation. + /// + /// May optionally specify an [importFrom] to auto-prefix the annotation _if_ + /// attached to a library where the import is not specified or is prefixed. + factory AnnotationBuilder.invoke( + String constructor, { + String importFrom, + Iterable> positional: const [], + Map> named: const {}, + }) { + return new _ConstructorAnnotationBuilder( + constructor, + new ExpressionBuilder.invoke( + null, + positional: positional, + named: named, + ), + importFrom, + ); + } + + /// Create a new annotated `const` [identifier]. + /// + /// May optionally specify an [importFrom] to auto-prefix the annotation _if_ + /// attached to a library where the import is not specified or is prefixed. + const factory AnnotationBuilder.reference(String identifier, + [String importFrom]) = _ReferenceAnnotationBuilder; +} + +class _ConstructorAnnotationBuilder extends RequiresImport + implements AnnotationBuilder { + final String _constructor; + final ExpressionBuilder _expression; + final String _importFrom; + + _ConstructorAnnotationBuilder(this._constructor, this._expression, + [this._importFrom]); + + @override + List get requiredImports => [_importFrom]; + + @override + Annotation toAst() { + var expressionAst = _expression.toAst(); + if (expressionAst is MethodInvocation) { + return new Annotation( + null, + _stringId(_constructor), + null, + null, + // TODO(matanl): InvocationExpression needs to be public API. + expressionAst.argumentList, + ); + } + throw new UnsupportedError('Expression must be InvocationExpression'); + } +} + +class _ReferenceAnnotationBuilder implements AnnotationBuilder { + final String _importFrom; + final String _reference; + + const _ReferenceAnnotationBuilder(this._reference, [this._importFrom]); + + @override + List get requiredImports => [_importFrom]; + + @override + Annotation toAst() => new Annotation( + null, + _stringId(_reference), + null, + null, + null, + ); + + @override + Annotation toScopedAst(_) => throw new UnimplementedError(); +} diff --git a/pkgs/code_builder/lib/src/class_builder.dart b/pkgs/code_builder/lib/src/class_builder.dart new file mode 100644 index 000000000..e9ca4170e --- /dev/null +++ b/pkgs/code_builder/lib/src/class_builder.dart @@ -0,0 +1,97 @@ +// 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. + +part of code_builder; + +/// Builds a [ClassDeclaration] AST. +class ClassBuilder extends _AbstractCodeBuilder { + static Token _abstract = new KeywordToken(Keyword.ABSTRACT, 0); + static Token _extends = new KeywordToken(Keyword.EXTENDS, 0); + static Token _implements = new KeywordToken(Keyword.IMPLEMENTS, 0); + static Token _with = new KeywordToken(Keyword.WITH, 0); + + /// Create a new builder for a `class` named [name]. + /// + /// Optionally, define another class to [extend] or classes to either + /// [implement] or [mixin]. You may also define a `class` as [abstract]. + factory ClassBuilder( + String name, { + bool abstract: false, + String extend, + Iterable implement: const [], + Iterable mixin: const [], + }) { + var astNode = _emptyClassDeclaration()..name = _stringId(name); + if (abstract) { + astNode.abstractKeyword = _abstract; + } + if (extend != null) { + astNode.extendsClause = new ExtendsClause( + _extends, + new TypeName( + _stringId(extend), + null, + )); + } + if (implement.isNotEmpty) { + astNode.implementsClause = new ImplementsClause( + _implements, + implement + .map/**/((i) => new TypeName(_stringId(i), null)) + .toList()); + } + if (mixin.isNotEmpty) { + astNode.withClause = new WithClause( + _with, + mixin + .map/**/((i) => new TypeName(_stringId(i), null)) + .toList()); + } + return new ClassBuilder._(astNode); + } + + ClassBuilder._(ClassDeclaration astNode) : super._(astNode); + + /// Adds an annotation [builder] as metadata. + void addAnnotation(AnnotationBuilder builder) { + _astNode.metadata.add(builder.toAst()); + } + + /// Adds a constructor [builder]. + void addConstructor(ConstructorBuilder builder) { + var astNode = builder.toAst(); + if (astNode.returnType == null) { + astNode.returnType = _astNode.name; + } + _astNode.members.add(astNode); + } + + /// Adds a field [builder] as a member on the class. + void addField(FieldBuilder builder, {bool static: false}) { + _astNode.members.add(builder.toFieldAst(static: static)); + } + + /// Adds a method [builder] as a member on the class. + void addMethod(MethodBuilder builder, {bool static: false}) { + _astNode.members.add(builder.toMethodAst( + static: static, + canBeAbstract: _astNode.abstractKeyword != null, + )); + } + + static ClassDeclaration _emptyClassDeclaration() => new ClassDeclaration( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + ); +} diff --git a/pkgs/code_builder/lib/src/constructor_builder.dart b/pkgs/code_builder/lib/src/constructor_builder.dart new file mode 100644 index 000000000..0839a05cb --- /dev/null +++ b/pkgs/code_builder/lib/src/constructor_builder.dart @@ -0,0 +1,60 @@ +// 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. + +part of code_builder; + +/// Builds a [ConstructorDeclaration] AST. +/// +/// Similar to [MethodBuilder] but adds constructor-only features. +/// +/// Use [ConstructorBuilder.initializeFields] to create something like: +/// class Foo { +/// final _one; +/// final _two; +/// +/// Foo(this._one, this._two); +/// } +class ConstructorBuilder extends _AbstractCodeBuilder { + static final Token _const = new KeywordToken(Keyword.CONST, 0); + static final Token _this = new KeywordToken(Keyword.THIS, 0); + + /// Create a simple [ConstructorBuilder] that initializes class fields. + /// + /// May optionally be [constant] compatible, or have a [name]. + factory ConstructorBuilder.initializeFields( + {bool constant: false, + String name, + Iterable positionalArguments: const [], + Iterable optionalArguments: const [], + Iterable namedArguments: const []}) { + var parameters = []; + for (var a in positionalArguments) { + parameters.add(new ParameterBuilder(a, field: true).toAst()); + } + for (var a in optionalArguments) { + parameters.add(new ParameterBuilder.optional(a, field: true).toAst()); + } + for (var a in namedArguments) { + parameters.add(new ParameterBuilder.named(a, field: true).toAst()); + } + var astNode = new ConstructorDeclaration( + null, + null, + null, + null, + constant ? _const : null, + null, + null, + name != null ? _stringId(name) : null, + MethodBuilder._emptyParameters()..parameters.addAll(parameters), + null, + null, + null, + new EmptyFunctionBody(MethodBuilder._semicolon), + ); + return new ConstructorBuilder._(astNode); + } + + ConstructorBuilder._(ConstructorDeclaration astNode) : super._(astNode); +} diff --git a/pkgs/code_builder/lib/src/expression_builder.dart b/pkgs/code_builder/lib/src/expression_builder.dart new file mode 100644 index 000000000..8147978c2 --- /dev/null +++ b/pkgs/code_builder/lib/src/expression_builder.dart @@ -0,0 +1,186 @@ +// 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. + +part of code_builder; + +// Shared functionality between ExpressionBuilder and _LiteralExpression. +final Token _closeP = new Token(TokenType.CLOSE_PAREN, 0); +final Token _openP = new Token(TokenType.OPEN_PAREN, 0); +final Token _semicolon = new Token(TokenType.SEMICOLON, 0); + +// Returns wrapped as a [ExpressionFunctionBody] AST. +ExpressionFunctionBody _asFunctionBody(CodeBuilder expression) { + return new ExpressionFunctionBody( + null, + null, + expression.toAst(), + _semicolon, + ); +} + +// Returns wrapped as a [FunctionExpression] AST. +FunctionExpression _asFunctionExpression(CodeBuilder expression) { + return new FunctionExpression( + null, + new FormalParameterList( + _openP, + const [], + null, + null, + _closeP, + ), + _asFunctionBody(expression), + ); +} + +/// Builds an [Expression] AST. +/// +/// For simple literal expressions see: +/// - [LiteralBool] and [literalTrue] [literalFalse] +/// - [LiteralInt] +/// - [LiteralString] +/// - [literalNull] +abstract class ExpressionBuilder implements CodeBuilder { + /// Invoke [name] (which should be available in the local scope). + /// + /// Optionally specify [positional] and [named] arguments. + factory ExpressionBuilder.invoke( + String name, { + Iterable> positional: const [], + Map> named: const {}, + }) { + return new _InvokeExpression( + name, + new List>.unmodifiable(positional), + new Map>.unmodifiable(named), + ); + } + + const ExpressionBuilder._(); + + /// Returns wrapped as a [ExpressionFunctionBody] AST. + ExpressionFunctionBody toFunctionBody() => _asFunctionBody(this); + + /// Returns wrapped as a [FunctionExpression] AST. + FunctionExpression toFunctionExpression() => _asFunctionExpression(this); +} + +// TODO(matanl): Make this part of the public API. See annotation_builder.dart. +class _InvokeExpression extends ExpressionBuilder + implements CodeBuilder { + static final Token _colon = new Token(TokenType.COLON, 0); + + final String _name; + final List> _positionalArguments; + final Map> _namedArguments; + + const _InvokeExpression( + this._name, + this._positionalArguments, + this._namedArguments, + ) + : super._(); + + ArgumentList _getArgumentList() { + return new ArgumentList( + new Token(TokenType.OPEN_CURLY_BRACKET, 0), + _positionalArguments.map/* p.toAst()).toList() + ..addAll(_namedArguments.keys + .map/**/((name) => new NamedExpression( + new Label( + _stringId(name), + _colon, + ), + _namedArguments[name].toAst(), + ))), + new Token(TokenType.CLOSE_CURLY_BRACKET, 0), + ); + } + + @override + InvocationExpression toAst() { + return new MethodInvocation( + null, + null, + _stringId(_name), + null, + _getArgumentList(), + ); + } +} + +abstract class _LiteralExpression + implements ExpressionBuilder, CodeBuilder { + const _LiteralExpression(); + + @override + ExpressionFunctionBody toFunctionBody() => _asFunctionBody(this); + + @override + FunctionExpression toFunctionExpression() => _asFunctionExpression(this); +} + +/// Represents an expression value of `true`. +const literalTrue = const LiteralBool(true); + +/// Represents an expression value of `false`. +const literalFalse = const LiteralBool(false); + +/// Creates a new literal `bool` value. +class LiteralBool extends _LiteralExpression { + static final BooleanLiteral _true = + new BooleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); + static final BooleanLiteral _false = + new BooleanLiteral(new KeywordToken(Keyword.FALSE, 0), false); + + final bool _value; + + /// Returns the passed value as a [BooleanLiteral]. + const LiteralBool(this._value); + + @override + BooleanLiteral toAst() => _value ? _true : _false; +} + +/// Represents an expression value of `null`. +const literalNull = const _LiteralNull(); + +class _LiteralNull extends _LiteralExpression { + static NullLiteral _null = new NullLiteral(new KeywordToken(Keyword.NULL, 0)); + + const _LiteralNull(); + + @override + NullLiteral toAst() => _null; +} + +/// Represents an expression value of a literal number. +class LiteralInt extends _LiteralExpression { + final int _value; + + /// Returns the passed value as a [IntegerLiteral]. + const LiteralInt(this._value); + + @override + IntegerLiteral toAst() => + new IntegerLiteral(new StringToken(TokenType.INT, '$_value', 0), _value); +} + +/// Represents an expression value of a literal `'string'`. +class LiteralString extends _LiteralExpression { + final String _value; + + /// Returns the passed value as a [StringLiteral]. + const LiteralString(this._value); + + @override + StringLiteral toAst() => new SimpleStringLiteral( + new StringToken( + TokenType.STRING, + "'$_value'", + 0, + ), + _value, + ); +} diff --git a/pkgs/code_builder/lib/src/field_builder.dart b/pkgs/code_builder/lib/src/field_builder.dart new file mode 100644 index 000000000..c6e9e2c24 --- /dev/null +++ b/pkgs/code_builder/lib/src/field_builder.dart @@ -0,0 +1,110 @@ +// 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. + +part of code_builder; + +/// Builds either a [FieldDeclaration] or [VariableDeclaration] AST. +/// +/// While the API is the same, you may specifically ask for either a field +/// AST (for class members) via [toFieldAst] or a variable declaration (used +/// both at the top-level and within methods) via [toVariablesAst]. +class FieldBuilder implements CodeBuilder { + static Token _equals = new Token(TokenType.EQ, 0); + static Token _semicolon = new Token(TokenType.SEMICOLON, 0); + static Token _static = new KeywordToken(Keyword.STATIC, 0); + static Token _final = new KeywordToken(Keyword.FINAL, 0); + static Token _const = new KeywordToken(Keyword.CONST, 0); + static Token _var = new KeywordToken(Keyword.VAR, 0); + + final bool _isConst; + final bool _isFinal; + final ExpressionBuilder _initialize; + final String _name; + final TypeBuilder _type; + + /// Create a new field builder. + /// + /// Optionally set a type and initializer. + FieldBuilder( + this._name, { + TypeBuilder type, + ExpressionBuilder initialize, + }) + : this._type = type, + this._initialize = initialize, + this._isFinal = false, + this._isConst = false; + + /// Create a new field builder that emits a `const` field. + /// + /// Optionally set a type and initializer. + FieldBuilder.isConst( + this._name, { + TypeBuilder type, + ExpressionBuilder initialize, + }) + : this._type = type, + this._initialize = initialize, + this._isFinal = false, + this._isConst = true; + + /// Create a new field builder that emits a `final` field. + /// + /// Optionally set a type and initializer. + FieldBuilder.isFinal( + this._name, { + TypeBuilder type, + ExpressionBuilder initialize, + }) + : this._type = type, + this._initialize = initialize, + this._isFinal = true, + this._isConst = false; + + Token _getVariableKeyword() { + if (_isFinal) { + return _final; + } + if (_isConst) { + return _const; + } + return _type == null ? _var : null; + } + + /// Returns a copy-safe [AstNode] representing the current builder state. + /// + /// **NOTE**: This method exists primarily for testing and compatibility with + /// the [CodeBuilder] ADT. When possible, invoke [toFieldAst] or + /// [toVariablesAst]. + @override + @visibleForTesting + Declaration toAst() => toFieldAst(); + + /// Returns a copy-safe [FieldDeclaration] AST representing current state. + FieldDeclaration toFieldAst({ + bool static: false, + }) => + new FieldDeclaration( + null, + null, + static ? _static : null, + toVariablesAst(), + null, + ); + + /// Returns a copy-safe [VariableDeclaration] AST representing current state. + VariableDeclarationList toVariablesAst() => new VariableDeclarationList( + null, + null, + _getVariableKeyword(), + _type?.toAst(), + [ + new VariableDeclaration( + _stringId(_name), + _initialize != null ? _equals : null, + _initialize?.toAst(), + ) + ], + ); +} diff --git a/pkgs/code_builder/lib/src/file_builder.dart b/pkgs/code_builder/lib/src/file_builder.dart new file mode 100644 index 000000000..bb2e99b50 --- /dev/null +++ b/pkgs/code_builder/lib/src/file_builder.dart @@ -0,0 +1,133 @@ +// 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. + +part of code_builder; + +/// Builds files of Dart source code. +/// +/// Files may either be a standalone library or `part of` another library. +class FileBuilder extends _AbstractCodeBuilder { + static Token _library = new KeywordToken(Keyword.LIBRARY, 0); + static Token _part = new KeywordToken(Keyword.PART, 0); + static Token _of = new StringToken(TokenType.KEYWORD, 'of', 0); + + /// Create a new standalone Dart library, optionally with a [name]. + factory FileBuilder([String name]) { + var astNode = _emptyCompilationUnit(); + if (name != null) { + astNode.directives.add(new LibraryDirective( + null, + null, + _library, + new LibraryIdentifier([_stringId(name)]), + null, + )); + } + return new FileBuilder._(astNode); + } + + /// Create a new `part of` the dart library with [name]. + factory FileBuilder.partOf(String name) { + var astNode = _emptyCompilationUnit(); + astNode.directives.add(new PartOfDirective( + null, + null, + _part, + _of, + new LibraryIdentifier([_stringId(name)]), + null, + )); + return new FileBuilder._(astNode); + } + + FileBuilder._(CompilationUnit astNode) : super._(astNode); + + /// Add a copy of [clazz] as a declaration in this file. + void addClass(ClassBuilder clazz) { + _astNode.declarations.add(clazz.toAst()); + } + + /// Adds an `import` or `export` [directive]. + void addDirective(CodeBuilder directive) { + if (isPartOf) { + throw const DartPartFileException._(); + } + _astNode.directives.add(directive.toAst()); + } + + static CompilationUnit _emptyCompilationUnit() => new CompilationUnit( + null, + null, + null, + null, + null, + ); + + static bool _isPartOf(Directive d) => d is PartOfDirective; + + /// Whether the file is `part of` another. + bool get isPartOf => _astNode.directives.contains(_isPartOf); +} + +/// An `export` directive in a [FileBuilder]. +class ExportBuilder extends _AbstractCodeBuilder { + /// Create a new `export` directive exporting [uri]. + factory ExportBuilder(String uri) { + var astNode = _createExportDirective()..uri = _stringLit("'$uri'"); + return new ExportBuilder._(astNode); + } + + ExportBuilder._(ExportDirective astNode) : super._(astNode); + + static ExportDirective _createExportDirective() => new ExportDirective( + null, + null, + null, + null, + null, + null, + null, + ); +} + +/// An `import` directive in a [FileBuilder]. +class ImportBuilder extends _AbstractCodeBuilder { + static Token _as = new KeywordToken(Keyword.AS, 0); + + /// Create a new `import` directive importing [uri]. + /// + /// Optionally prefix [as]. + factory ImportBuilder(String uri, {String as}) { + var astNode = _createImportDirective()..uri = _stringLit("'$uri'"); + if (as != null) { + astNode + ..asKeyword = _as + ..prefix = _stringId(as); + } + return new ImportBuilder._(astNode); + } + + ImportBuilder._(ImportDirective astNode) : super._(astNode); + + static ImportDirective _createImportDirective() => new ImportDirective( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + ); +} + +/// Thrown when an invalid operation is attempted on a [FileBuilder] instance. +class DartPartFileException implements Exception { + const DartPartFileException._(); + + @override + String toString() => 'Not a valid operation for a `part of` file.'; +} diff --git a/pkgs/code_builder/lib/src/method_builder.dart b/pkgs/code_builder/lib/src/method_builder.dart new file mode 100644 index 000000000..6a96e0c07 --- /dev/null +++ b/pkgs/code_builder/lib/src/method_builder.dart @@ -0,0 +1,174 @@ +// 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. + +part of code_builder; + +/// Builds either a [MethodDeclaration] or a [FunctionDeclaration]. +/// +/// While the API is the same, you may specifically ask for either a method +/// AST (for class members) via [toMethodAst] or a function AST (used both at +/// the top level and within other methods) via [toFunctionAst]. +/// +/// To return nothing (`void`), use [MethodBuilder.returnVoid]. +class MethodBuilder implements CodeBuilder { + static Token _abstract = new KeywordToken(Keyword.ABSTRACT, 0); + static Token _semicolon = new Token(TokenType.SEMICOLON, 0); + static Token _static = new KeywordToken(Keyword.STATIC, 0); + + // Void is a "type" that is only valid as a return type on a method. + static const TypeBuilder _typeVoid = const TypeBuilder('void'); + + final List _annotations = []; + final String _name; + final List _parameters = []; + final List _statements = []; + + ExpressionBuilder _returnExpression; + TypeBuilder _returnType; + + /// Create a new method builder, + /// + /// Optionally set a [returns] type. + factory MethodBuilder({String name, TypeBuilder returns}) { + return new MethodBuilder._(name, returns); + } + + /// Creates a `void`-returning MethodBuilder with [name]. + factory MethodBuilder.returnVoid([String name]) { + return new MethodBuilder._(name, _typeVoid); + } + + MethodBuilder._(this._name, this._returnType); + + /// Lazily adds [annotation]. + /// + /// When the method is emitted as an AST, [AnnotationBuilder.toAst] is used. + void addAnnotation(AnnotationBuilder annotation) { + _annotations.add(annotation); + } + + /// Lazily adds [parameter]. + /// + /// When the method is emitted as an AST, [ParameterBuilder.toAst] is used. + void addParameter(ParameterBuilder parameter) { + _parameters.add(parameter); + } + + static FunctionBody _emptyBlockBody() => new BlockFunctionBody( + null, + null, + new Block( + new Token(TokenType.OPEN_CURLY_BRACKET, 0), + null, + new Token(TokenType.CLOSE_CURLY_BRACKET, 0), + ), + ); + + static FunctionDeclaration _emptyFunction() => new FunctionDeclaration( + null, + null, + null, + null, + null, + null, + new FunctionExpression( + null, + _emptyParameters(), + _emptyBlockBody(), + ), + ); + + static MethodDeclaration _emptyMethod() => new MethodDeclaration( + null, + null, + null, + null, + null, + null, + null, + null, + null, + _emptyParameters(), + null, + ); + + static FormalParameterList _emptyParameters() => new FormalParameterList( + new Token(TokenType.OPEN_PAREN, 0), + [], + null, + null, + new Token(TokenType.CLOSE_PAREN, 0), + ); + + /// Lazily adds [statement]. + /// + /// When the method is emitted as an AST, [StatementBuilder.toAst] is used. + void addStatement(StatementBuilder statement) { + _statements.add(statement); + } + + /// Lazily sets [expression] as the lambda result of this method invocation. + /// + /// When the method is emitted as an AST, [ExpressionBuilder.toAst] is used. + void setExpression(ExpressionBuilder expression) { + _returnExpression = expression; + } + + /// Returns a copy-safe [AstNode] representing the current builder state. + /// + /// **NOTE**: This method exists primarily for testing and compatibility with + /// the [CodeBuilder] ADT. When possible, invoke [toFunctionAst] or + /// [toMethodAst]. + @override + @visibleForTesting + Declaration toAst() => toFunctionAst(); + + /// Returns a copy-safe [FunctionDeclaration] AST representing current state. + FunctionDeclaration toFunctionAst() { + var functionAst = _emptyFunction() + ..metadata.addAll(_annotations.map/**/((a) => a.toAst())) + ..name = _stringId(_name) + ..returnType = _returnType?.toAst(); + if (_returnExpression != null) { + functionAst.functionExpression = _returnExpression.toFunctionExpression(); + } + if (_parameters.isNotEmpty) { + functionAst.functionExpression.parameters = _emptyParameters() + ..parameters + .addAll(_parameters.map/**/((p) => p.toAst())); + } + return functionAst; + } + + /// Returns a copy-safe [FunctionDeclaration] AST representing current state. + MethodDeclaration toMethodAst({ + bool static: false, + bool canBeAbstract: false, + }) { + var methodAst = _emptyMethod() + ..metadata.addAll(_annotations.map/**/((a) => a.toAst())) + ..name = _stringId(_name) + ..returnType = _returnType?.toAst(); + FunctionBody methodBody = _returnExpression?.toFunctionBody(); + if (static) { + methodAst.modifierKeyword = _static; + if (methodBody == null) { + methodBody = _emptyBlockBody(); + } + } + if (methodBody == null) { + methodBody = + canBeAbstract ? new EmptyFunctionBody(_semicolon) : _emptyBlockBody(); + } + if (_parameters.isNotEmpty) { + methodAst.parameters.parameters + .addAll(_parameters.map/**/((p) => p.toAst())); + } + methodAst.body = methodBody; + return methodAst; + } + + @override + String toString() => 'MethodBuilder ${toAst().toSource()}'; +} diff --git a/pkgs/code_builder/lib/src/parameter_builder.dart b/pkgs/code_builder/lib/src/parameter_builder.dart new file mode 100644 index 000000000..bf710d176 --- /dev/null +++ b/pkgs/code_builder/lib/src/parameter_builder.dart @@ -0,0 +1,130 @@ +// 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. + +part of code_builder; + +/// Build a [FormalParameter] AST. +/// +/// A parameter is part of a built [MethodBuilder], and can refer to a +/// class-member (field) variable (see the `field` property in the +/// constructors). +class ParameterBuilder extends _AbstractCodeBuilder { + static final Token _this = new KeywordToken(Keyword.THIS, 0); + + /// Create a new _required_ parameter of [name]. + factory ParameterBuilder( + String name, { + bool field: false, + TypeBuilder type, + }) { + FormalParameter astNode; + if (field) { + astNode = new FieldFormalParameter( + null, + null, + null, + type?.toAst(), + _this, + null, + _stringId(name), + null, + null, + ); + } else { + astNode = new SimpleFormalParameter( + null, + null, + null, + type?.toAst(), + _stringId(name), + ); + } + return new ParameterBuilder._(astNode); + } + + /// Create a new _optional_ (but positional) parameter. + /// + /// See [ParameterBuilder.named] for an optional _named_ parameter. + factory ParameterBuilder.optional( + String name, { + bool field: false, + TypeBuilder type, + ExpressionBuilder defaultTo, + }) { + return new ParameterBuilder._optional( + name, + false, + field: field, + type: type, + defaultTo: defaultTo, + ); + } + + /// Create a new _optional_ _named_ parameter. + factory ParameterBuilder.named( + String name, { + bool field: false, + TypeBuilder type, + ExpressionBuilder defaultTo, + }) { + return new ParameterBuilder._optional( + name, + true, + field: field, + type: type, + defaultTo: defaultTo, + ); + } + + // Actual implementation of optional and named. + factory ParameterBuilder._optional( + String name, + bool named, { + bool field: false, + TypeBuilder type, + ExpressionBuilder defaultTo, + }) { + FormalParameter astNode; + if (field) { + astNode = new FieldFormalParameter( + null, + null, + null, + type?.toAst(), + _this, + null, + _stringId(name), + null, + null, + ); + } else { + astNode = new SimpleFormalParameter( + null, + null, + null, + type?.toAst(), + _stringId(name), + ); + } + Token defaultToEq; + if (defaultTo != null) { + defaultToEq = + named ? new Token(TokenType.COLON, 0) : new Token(TokenType.EQ, 0); + } + astNode = new DefaultFormalParameter( + astNode, + named ? ParameterKind.NAMED : ParameterKind.POSITIONAL, + defaultToEq, + defaultTo?.toAst(), + ); + return new ParameterBuilder._(astNode); + } + + ParameterBuilder._(FormalParameter astNode) : super._(astNode); + + /// Adds a metadata annotation from [builder]. + void addAnnotation(AnnotationBuilder builder) { + _astNode.metadata.add(builder.toAst()); + } +} diff --git a/pkgs/code_builder/lib/src/pretty_printer.dart b/pkgs/code_builder/lib/src/pretty_printer.dart new file mode 100644 index 000000000..ce8c148f8 --- /dev/null +++ b/pkgs/code_builder/lib/src/pretty_printer.dart @@ -0,0 +1,103 @@ +// 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. + +part of code_builder; + +/// Augments [AstNode.toSource] by adding some whitespace/line breaks. +/// +/// The final result is run through `dartfmt`. +/// +/// This is the _recommended_ output (but not required) when comparing ASTs +/// to expected golden files/text blobs. +String prettyToSource(AstNode astNode) { + var writer = new PrintStringWriter(); + var visitor = new _PrettyToSourceVisitor(writer); + astNode.accept(visitor); + return dartfmt(writer.toString()); +} + +// TODO(matanl): Remove copied-pasted methods when API becomes available. +// https://github.com/dart-lang/sdk/issues/27169 +class _PrettyToSourceVisitor extends ToSourceVisitor { + // Removed in a new version of the analyzer, but due to dartfmt it's not + // possible to refer to the newest analyzer and use dartfmt. + // https://github.com/dart-lang/sdk/issues/27301 + final PrintStringWriter _writer; + + _PrettyToSourceVisitor(PrintStringWriter writer) + : _writer = writer, + super(writer); + + @override + Object visitClassDeclaration(ClassDeclaration node) { + _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); + _visitTokenWithSuffix(node.abstractKeyword, " "); + _writer.print("class "); + _visitNode(node.name); + _visitNode(node.typeParameters); + _visitNodeWithPrefix(" ", node.extendsClause); + _visitNodeWithPrefix(" ", node.withClause); + _visitNodeWithPrefix(" ", node.implementsClause); + _writer.print(" {"); + _visitNodeListWithSeparator(node.members, "\n\n"); + _writer.print("}"); + return null; + } + + // Safely visit the given [node]. + void _visitNode(AstNode node) { + if (node != null) { + node.accept(this); + } + } + + // Write a list of [nodes], separated by the given [separator]. + void _visitNodeListWithSeparator(NodeList nodes, String separator) { + if (nodes != null) { + int size = nodes.length; + for (int i = 0; i < size; i++) { + if (i > 0) { + _writer.print(separator); + } + nodes[i].accept(this); + } + } + } + + // Write a list of [nodes], separated by the given [separator], followed by + // the given [suffix] if the list is not empty. + void _visitNodeListWithSeparatorAndSuffix( + NodeList nodes, String separator, String suffix) { + if (nodes != null) { + int size = nodes.length; + if (size > 0) { + for (int i = 0; i < size; i++) { + if (i > 0) { + _writer.print(separator); + } + nodes[i].accept(this); + } + _writer.print(suffix); + } + } + } + + // Safely visit the given [node], writing the [prefix] before the node if it + // is non-`null`. + void _visitNodeWithPrefix(String prefix, AstNode node) { + if (node != null) { + _writer.print(prefix); + node.accept(this); + } + } + + // Safely visit the given [token], writing the [suffix] after the token if it + // is non-`null`. + void _visitTokenWithSuffix(Token token, String suffix) { + if (token != null) { + _writer.print(token.lexeme); + _writer.print(suffix); + } + } +} diff --git a/pkgs/code_builder/lib/src/statement_builder.dart b/pkgs/code_builder/lib/src/statement_builder.dart new file mode 100644 index 000000000..fd5a794a1 --- /dev/null +++ b/pkgs/code_builder/lib/src/statement_builder.dart @@ -0,0 +1,10 @@ +// 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. + +part of code_builder; + +/// Builds a [Statement] AST. +abstract class StatementBuilder implements CodeBuilder { + // TODO(matanl): Implement (not required immediately as we have expressions). +} diff --git a/pkgs/code_builder/lib/src/type_builder.dart b/pkgs/code_builder/lib/src/type_builder.dart new file mode 100644 index 000000000..45aac3213 --- /dev/null +++ b/pkgs/code_builder/lib/src/type_builder.dart @@ -0,0 +1,32 @@ +// 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. + +part of code_builder; + +/// Build a [TypeName] AST. +class TypeBuilder implements RequiresImport { + final String _identifier; + final String _importFrom; + + /// Create a builder for emitting a [TypeName] AST. + /// + /// Optionally specify what must be imported for this type to resolve. + /// + /// __Example use__: + /// const TypeBuilder('String', importFrom: 'dart:core') + const TypeBuilder(this._identifier, {String importFrom}) + : _importFrom = importFrom; + + @override + List get requiredImports => [_importFrom]; + + @override + TypeName toAst() => new TypeName( + _stringId(_identifier), + null, + ); + + @override + TypeName toScopedAst(FileBuilder scope) => throw new UnimplementedError(); +} diff --git a/pkgs/code_builder/lib/testing/equals_source.dart b/pkgs/code_builder/lib/testing/equals_source.dart new file mode 100644 index 000000000..a706e7dcd --- /dev/null +++ b/pkgs/code_builder/lib/testing/equals_source.dart @@ -0,0 +1,73 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:matcher/matcher.dart'; + +/// Returns a [Matcher] that checks a [CodeBuilder] versus [source]. +/// +/// On failure, uses the default string matcher to show a detailed diff between +/// the expected and actual source code results. +/// +/// **NOTE**: By default it both runs `dartfmt` _and_ prints the source with +/// additional formatting over the default `Ast.toSource` implementation (i.e. +/// adds new lines between methods in classes, and more). +/// +/// If you have code that is not consider a valid compilation unit (like an +/// expression, you should flip [format] to `false`). +Matcher equalsSource(String source, {bool format: true}) { + return new _EqualsSource(format ? dartfmt(source) : source, format); +} + +// Delegates to the default matcher (which delegates further). +// +// Would be nice to just use more of package:matcher directly: +// https://github.com/dart-lang/matcher/issues/36 +class _EqualsSource extends Matcher { + final String _source; + final bool _isFormatted; + + _EqualsSource(this._source, this._isFormatted); + + @override + Description describe(Description description) { + return equals(_source).describe(description); + } + + @override + Description describeMismatch( + item, + Description mismatchDescription, + Map matchState, + bool verbose, + ) { + if (item is CodeBuilder) { + return equals(_source).describeMismatch( + _formatAst(item), + mismatchDescription, + matchState, + verbose, + ); + } else { + return mismatchDescription.add('$item is not a CodeBuilder'); + } + } + + String _formatAst(CodeBuilder builder) { + var ast = builder.toAst(); + if (_isFormatted) { + return prettyToSource(ast); + } else { + return ast.toSource(); + } + } + + @override + bool matches(item, _) { + if (item is CodeBuilder) { + return _formatAst(item) == _source; + } + return false; + } +} diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml new file mode 100644 index 000000000..73a0602cb --- /dev/null +++ b/pkgs/code_builder/pubspec.yaml @@ -0,0 +1,17 @@ +name: code_builder +version: 0.1.0 +description: A fluent API for generating Dart code +author: Dart Team +homepage: https://github.com/dart-lang/code_builder + +environment: + sdk: '>=1.9.1 <2.0.0' + +dependencies: + analyzer: ">=0.27.1 <0.29.0" + dart_style: ^0.2.9+1 + matcher: ^0.12.0+2 + meta: ^1.0.2 + +dev_dependencies: + test: ^0.12.0 diff --git a/pkgs/code_builder/test/builders/class_builder_test.dart b/pkgs/code_builder/test/builders/class_builder_test.dart new file mode 100644 index 000000000..ac4cf9168 --- /dev/null +++ b/pkgs/code_builder/test/builders/class_builder_test.dart @@ -0,0 +1,161 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing/equals_source.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit an empty class', () { + expect(new ClassBuilder('Animal'), equalsSource('class Animal {}')); + }); + + test('should emit an abstract class', () { + expect( + new ClassBuilder('Animal', abstract: true), + equalsSource('abstract class Animal {}'), + ); + }); + + test('should emit a class extending another class', () { + expect( + new ClassBuilder('Animal', extend: 'Organism'), + equalsSource('class Animal extends Organism {}'), + ); + }); + + test('should emit a class implementing another class', () { + expect( + new ClassBuilder('Animal', implement: ['Delicious']), + equalsSource('class Animal implements Delicious {}'), + ); + }); + + test('should emit a class extending and mixing in another class', () { + expect( + new ClassBuilder('Animal', extend: 'Organism', mixin: ['Breathing']), + equalsSource('class Animal extends Organism with Breathing {}'), + ); + }); + + test('should emit a class with a method', () { + expect( + new ClassBuilder('Animal') + ..addMethod(new MethodBuilder( + name: 'toString', + returns: typeString, + )..setExpression(const LiteralString('Delicious'))), + equalsSource(r''' + class Animal { + String toString() => 'Delicious'; + } + '''), + ); + }); + + test('should emit an abstract class with an abstract method', () { + expect( + new ClassBuilder('Animal', abstract: true) + ..addMethod( + new MethodBuilder.returnVoid('eat'), + ), + equalsSource(r''' + abstract class Animal { + void eat(); + } + '''), + ); + }); + + test('should emit a class with a static method', () { + expect( + new ClassBuilder('Animal') + ..addMethod( + new MethodBuilder( + name: 'create', + returns: new TypeBuilder('Animal'), + )..setExpression(literalNull), + static: true, + ), + equalsSource(r''' + class Animal { + static Animal create() => null; + } + '''), + ); + }); + + test('should emit a class with a metadata annotation', () { + expect( + new ClassBuilder('Animal')..addAnnotation(atDeprecated()), + equalsSource(r''' + @deprecated + class Animal {} + '''), + ); + }); + + test('should emit a class with an invoking metadata annotation', () { + expect( + new ClassBuilder('Animal') + ..addAnnotation(atDeprecated('We ate them all')), + equalsSource(r''' + @Deprecated('We ate them all') + class Animal {} + '''), + ); + }); + + group('constructors', () { + ClassBuilder clazz; + + setUp(() { + clazz = new ClassBuilder('Animal'); + }); + + test('default constructor', () { + clazz.addConstructor(new ConstructorBuilder.initializeFields()); + expect( + clazz, + equalsSource( + r''' + class Animal { + Animal(); + } + ''', + )); + }); + + test('default const constructor', () { + clazz.addConstructor( + new ConstructorBuilder.initializeFields(constant: true)); + expect( + clazz, + equalsSource( + r''' + class Animal { + const Animal(); + } + ''', + )); + }); + + test('initializing fields', () { + clazz.addConstructor(new ConstructorBuilder.initializeFields( + positionalArguments: ['a'], + optionalArguments: ['b'], + )); + expect( + clazz, + equalsSource( + r''' + class Animal { + Animal(this.a, [this.b]); + } + ''', + )); + }); + }); +} diff --git a/pkgs/code_builder/test/builders/field_builder_test.dart b/pkgs/code_builder/test/builders/field_builder_test.dart new file mode 100644 index 000000000..95954b4c2 --- /dev/null +++ b/pkgs/code_builder/test/builders/field_builder_test.dart @@ -0,0 +1,49 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing/equals_source.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit an unitialized simple variable', () { + expect( + new FieldBuilder('name'), + equalsSource(r'var name;'), + ); + }); + + test('should emit a typed variable', () { + expect( + new FieldBuilder('name', type: typeString), + equalsSource(r'String name;'), + ); + }); + + test('should emit an initialized variable', () { + expect( + new FieldBuilder( + 'name', + type: typeString, + initialize: const LiteralString('Jill User'), + ), + equalsSource(r"String name = 'Jill User';"), + ); + }); + + test('should emit a final variable', () { + expect( + new FieldBuilder.isFinal('name'), + equalsSource(r'final name;'), + ); + }); + + test('should emit a const variable', () { + expect( + new FieldBuilder.isConst('name'), + equalsSource(r'const name;'), + ); + }); +} diff --git a/pkgs/code_builder/test/builders/file_builder_test.dart b/pkgs/code_builder/test/builders/file_builder_test.dart new file mode 100644 index 000000000..14fae003b --- /dev/null +++ b/pkgs/code_builder/test/builders/file_builder_test.dart @@ -0,0 +1,46 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/testing/equals_source.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit a blank file', () { + expect(new FileBuilder(), equalsSource('')); + }); + + test('should emit a file with a library directive', () { + expect( + new FileBuilder('code_builder'), equalsSource('library code_builder;')); + }); + + test('should emit a file with a part of directive', () { + expect( + new FileBuilder.partOf('code_builder'), + equalsSource('part of code_builder;'), + ); + }); + + test('should emit an import directive', () { + expect( + new ImportBuilder('package:foo/foo.dart'), + equalsSource("import 'package:foo/foo.dart';"), + ); + }); + + test('should emit an import directive and a prefix', () { + expect( + new ImportBuilder('package:foo/foo.dart', as: 'foo'), + equalsSource("import 'package:foo/foo.dart' as foo;"), + ); + }); + + test('should emit an export directive', () { + expect( + new ExportBuilder('package:foo/foo.dart'), + equalsSource("export 'package:foo/foo.dart';"), + ); + }); +} diff --git a/pkgs/code_builder/test/builders/method_builder_test.dart b/pkgs/code_builder/test/builders/method_builder_test.dart new file mode 100644 index 000000000..bcca43668 --- /dev/null +++ b/pkgs/code_builder/test/builders/method_builder_test.dart @@ -0,0 +1,244 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing/equals_source.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit a simple "void" method', () { + expect( + new MethodBuilder.returnVoid('main'), + equalsSource('void main() {}'), + ); + }); + + test('should emit a method returning a String', () { + expect( + new MethodBuilder(name: 'toString', returns: typeString), + equalsSource('String toString() {}'), + ); + }); + + test('should emit a method annotated', () { + expect( + new MethodBuilder(name: 'oldMethod')..addAnnotation(atDeprecated()), + equalsSource( + r''' + @deprecated + oldMethod() {} + ''', + )); + }); + + group('with an expression', () { + test('should return true', () { + expect( + new MethodBuilder(name: 'isSupported', returns: typeBool) + ..setExpression(literalTrue), + equalsSource( + r''' + bool isSupported() => true; + ''', + ), + ); + }); + + test('should return false', () { + expect( + new MethodBuilder(name: 'isSupported', returns: typeBool) + ..setExpression(literalFalse), + equalsSource( + r''' + bool isSupported() => false; + ''', + ), + ); + }); + + test('should return null', () { + expect( + new MethodBuilder(name: 'isSupported')..setExpression(literalNull), + equalsSource( + r''' + isSupported() => null; + ''', + ), + ); + }); + + test('should return "Hello World"', () { + expect( + new MethodBuilder(name: 'sayHello', returns: typeString) + ..setExpression( + const LiteralString('Hello World'), + ), + equalsSource( + r''' + String sayHello() => 'Hello World'; + ''', + ), + ); + }); + + group('with parameters:', () { + MethodBuilder method; + + setUp(() { + method = new MethodBuilder.returnVoid('main'); + }); + + test('single required parameter', () { + method.addParameter(new ParameterBuilder('name', type: typeString)); + expect( + method, + equalsSource( + r''' + void main(String name) {} + ''', + ), + ); + }); + + test('two required parameters', () { + method + ..addParameter(new ParameterBuilder('a', type: typeInt)) + ..addParameter(new ParameterBuilder('b', type: typeInt)); + expect( + method, + equalsSource( + r''' + void main(int a, int b) {} + ''', + ), + ); + }); + + test('one optional parameter', () { + method.addParameter(new ParameterBuilder.optional( + 'name', + type: typeString, + )); + expect( + method, + equalsSource( + r''' + void main([String name]) {} + ''', + ), + ); + }); + + test('one optional parameter with a default value', () { + method.addParameter(new ParameterBuilder.optional( + 'enabled', + type: typeBool, + defaultTo: literalTrue, + )); + expect( + method, + equalsSource( + r''' + void main([bool enabled = true]) {} + ''', + ), + ); + }); + + test('one optional named parameter with a default value', () { + method.addParameter(new ParameterBuilder.named( + 'enabled', + type: typeBool, + defaultTo: literalTrue, + )); + expect( + method, + equalsSource( + r''' + void main({bool enabled: true}) {} + ''', + ), + ); + }); + + test('one optional named parameter with an annotation', () { + method.addParameter(new ParameterBuilder.named( + 'enabled', + type: typeBool, + defaultTo: literalTrue, + )..addAnnotation(atDeprecated())); + expect( + method, + equalsSource( + r''' + void main({@deprecated bool enabled: true}) {} + ''', + ), + ); + }); + }); + + group('invoking method', () { + MethodBuilder method; + + setUp(() { + method = new MethodBuilder(name: 'forward', returns: typeInt); + }); + + test('should call another method with one argument', () { + method.setExpression(new ExpressionBuilder.invoke( + 'forwardImpl', + positional: [const LiteralInt(666)], + )); + expect( + method, + equalsSource(r''' + int forward() => forwardImpl(666); + '''), + ); + }); + + test('should call another method with two arguments', () { + method.setExpression(new ExpressionBuilder.invoke( + 'sum', + positional: [const LiteralInt(1), const LiteralInt(2)], + )); + expect( + method, + equalsSource(r''' + int forward() => sum(1, 2); + '''), + ); + }); + + test('should call another method with a named arguments', () { + method.setExpression(new ExpressionBuilder.invoke( + 'forwardImpl', + named: {'value': const LiteralInt(666)}, + )); + expect( + method, + equalsSource(r''' + int forward() => forwardImpl(value: 666); + '''), + ); + }); + + test('should call another method with many arguments', () { + method.setExpression(new ExpressionBuilder.invoke( + 'forwardImpl', + positional: const [const LiteralInt(3), const LiteralInt(4)], + named: {'a': const LiteralInt(1), 'b': const LiteralInt(2)}, + )); + expect( + method, + equalsSource(r''' + int forward() => forwardImpl(3, 4, a: 1, b: 2); + '''), + ); + }); + }); + }); +} diff --git a/pkgs/code_builder/test/integration_test.dart b/pkgs/code_builder/test/integration_test.dart new file mode 100644 index 000000000..2d5b9a70f --- /dev/null +++ b/pkgs/code_builder/test/integration_test.dart @@ -0,0 +1,58 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing/equals_source.dart'; +import 'package:test/test.dart'; + +// Closely mirrors the API you would need to do dependency injection :) +void main() { + test('Emits a complex generated file', () { + var clazz = new ClassBuilder(r'Injector', implement: ['App']) + ..addField(new FieldBuilder.isFinal( + '_module', + type: const TypeBuilder('Module'), + )) + ..addConstructor(new ConstructorBuilder.initializeFields( + positionalArguments: ['_module'], + )) + ..addMethod( + new MethodBuilder( + name: 'getThing', + returns: const TypeBuilder('Thing'), + ) + ..addAnnotation(atOverride) + ..setExpression(new ExpressionBuilder.invoke( + 'new Thing', + positional: [ + new ExpressionBuilder.invoke('_module.getDep1'), + new ExpressionBuilder.invoke('_module.getDep2'), + ], + )), + ); + var lib = new FileBuilder() + ..addDirective( + new ImportBuilder('app.dart'), + ) + ..addClass(clazz); + expect( + lib, + equalsSource( + r''' + import 'app.dart'; + + class Injector implements App { + final Module _module; + + Injector(this._module); + + @override + Thing getThing() => new Thing(_module.getDep1(), _module.getDep2()); + } + ''', + ), + ); + }); +} diff --git a/pkgs/code_builder/tool/travis.sh b/pkgs/code_builder/tool/travis.sh new file mode 100755 index 000000000..cab493d2b --- /dev/null +++ b/pkgs/code_builder/tool/travis.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# 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. + +# Fast fail the script on failures. +set -e + +# Verify that the libraries are error free. +dartanalyzer --fatal-warnings \ + lib/code_builder.dart \ + lib/dart/core.dart \ + lib/testing/equals_source.dart + +# Run the tests. +pub run test + +# Install dart_coveralls; gather and send coverage data. +if [ "$COVERALLS_TOKEN" ] && [ "$TRAVIS_DART_VERSION" = "stable" ]; then + dart tool/create_test_all.dart + pub global activate dart_coveralls + pub global run dart_coveralls report \ + --retry 2 \ + --exclude-test-files \ + tool/test_all.dart + rm tool/test_all.dart +fi From 2fc53713c556d2069b8153b3bc933dcdff65283f Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 9 Sep 2016 16:12:47 -0700 Subject: [PATCH 002/271] Initial commit Add a bunch of builders and new tests. All tests currently passing. Get ready to publish. Almost ready to publish. Fix pubspec. . --- pkgs/code_builder/.gitignore | 30 +++ pkgs/code_builder/.travis.yml | 7 + pkgs/code_builder/AUTHORS | 6 + pkgs/code_builder/CHANGELOG.md | 5 + pkgs/code_builder/CONTRIBUTING.md | 33 +++ pkgs/code_builder/LICENSE | 26 ++ pkgs/code_builder/README.md | 32 +++ pkgs/code_builder/analysis_options.yaml | 41 +++ pkgs/code_builder/lib/code_builder.dart | 102 ++++++++ pkgs/code_builder/lib/dart/core.dart | 137 ++++++++++ .../lib/src/annotation_builder.dart | 98 +++++++ pkgs/code_builder/lib/src/class_builder.dart | 97 +++++++ .../lib/src/constructor_builder.dart | 60 +++++ .../lib/src/expression_builder.dart | 186 +++++++++++++ pkgs/code_builder/lib/src/field_builder.dart | 110 ++++++++ pkgs/code_builder/lib/src/file_builder.dart | 133 ++++++++++ pkgs/code_builder/lib/src/method_builder.dart | 174 +++++++++++++ .../lib/src/parameter_builder.dart | 130 ++++++++++ pkgs/code_builder/lib/src/pretty_printer.dart | 103 ++++++++ .../lib/src/statement_builder.dart | 10 + pkgs/code_builder/lib/src/type_builder.dart | 32 +++ .../lib/testing/equals_source.dart | 73 ++++++ pkgs/code_builder/pubspec.yaml | 17 ++ .../test/builders/class_builder_test.dart | 161 ++++++++++++ .../test/builders/field_builder_test.dart | 49 ++++ .../test/builders/file_builder_test.dart | 46 ++++ .../test/builders/method_builder_test.dart | 244 ++++++++++++++++++ pkgs/code_builder/test/integration_test.dart | 58 +++++ pkgs/code_builder/tool/travis.sh | 28 ++ 29 files changed, 2228 insertions(+) create mode 100644 pkgs/code_builder/.gitignore create mode 100644 pkgs/code_builder/.travis.yml create mode 100644 pkgs/code_builder/AUTHORS create mode 100644 pkgs/code_builder/CHANGELOG.md create mode 100644 pkgs/code_builder/CONTRIBUTING.md create mode 100644 pkgs/code_builder/LICENSE create mode 100644 pkgs/code_builder/README.md create mode 100644 pkgs/code_builder/analysis_options.yaml create mode 100644 pkgs/code_builder/lib/code_builder.dart create mode 100644 pkgs/code_builder/lib/dart/core.dart create mode 100644 pkgs/code_builder/lib/src/annotation_builder.dart create mode 100644 pkgs/code_builder/lib/src/class_builder.dart create mode 100644 pkgs/code_builder/lib/src/constructor_builder.dart create mode 100644 pkgs/code_builder/lib/src/expression_builder.dart create mode 100644 pkgs/code_builder/lib/src/field_builder.dart create mode 100644 pkgs/code_builder/lib/src/file_builder.dart create mode 100644 pkgs/code_builder/lib/src/method_builder.dart create mode 100644 pkgs/code_builder/lib/src/parameter_builder.dart create mode 100644 pkgs/code_builder/lib/src/pretty_printer.dart create mode 100644 pkgs/code_builder/lib/src/statement_builder.dart create mode 100644 pkgs/code_builder/lib/src/type_builder.dart create mode 100644 pkgs/code_builder/lib/testing/equals_source.dart create mode 100644 pkgs/code_builder/pubspec.yaml create mode 100644 pkgs/code_builder/test/builders/class_builder_test.dart create mode 100644 pkgs/code_builder/test/builders/field_builder_test.dart create mode 100644 pkgs/code_builder/test/builders/file_builder_test.dart create mode 100644 pkgs/code_builder/test/builders/method_builder_test.dart create mode 100644 pkgs/code_builder/test/integration_test.dart create mode 100755 pkgs/code_builder/tool/travis.sh diff --git a/pkgs/code_builder/.gitignore b/pkgs/code_builder/.gitignore new file mode 100644 index 000000000..8d4854698 --- /dev/null +++ b/pkgs/code_builder/.gitignore @@ -0,0 +1,30 @@ +# See https://www.dartlang.org/tools/private-files.html + +# Files and directories created by pub +.buildlog +.packages +.project +.pub +**/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 diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml new file mode 100644 index 000000000..5826f9bc1 --- /dev/null +++ b/pkgs/code_builder/.travis.yml @@ -0,0 +1,7 @@ +language: dart + +dart: + - dev + - stable + +script: ./tool/travis.sh diff --git a/pkgs/code_builder/AUTHORS b/pkgs/code_builder/AUTHORS new file mode 100644 index 000000000..609e0dce0 --- /dev/null +++ b/pkgs/code_builder/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. \ No newline at end of file diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md new file mode 100644 index 000000000..a11689988 --- /dev/null +++ b/pkgs/code_builder/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 0.1.0 + +- Initial version diff --git a/pkgs/code_builder/CONTRIBUTING.md b/pkgs/code_builder/CONTRIBUTING.md new file mode 100644 index 000000000..0bf17f075 --- /dev/null +++ b/pkgs/code_builder/CONTRIBUTING.md @@ -0,0 +1,33 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. + +### File headers +All files in the project must start with the following header. + + // 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. + +### The small print +Contributions made by corporations are covered by a different agreement than the +one above, the +[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). \ No newline at end of file diff --git a/pkgs/code_builder/LICENSE b/pkgs/code_builder/LICENSE new file mode 100644 index 000000000..4ded3fa11 --- /dev/null +++ b/pkgs/code_builder/LICENSE @@ -0,0 +1,26 @@ +Copyright 2016, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md new file mode 100644 index 000000000..36d7d2779 --- /dev/null +++ b/pkgs/code_builder/README.md @@ -0,0 +1,32 @@ +# code_builder + +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](analyzer) package to create real Dart +language ASTs, which, while not guaranteed to be correct, always follows +the analyzer's own understood format. + +[analyzer]: https://pub.dartlang.org/packages/analyzer + +Code builder also adds a more narrow and user-friendly API. For example +creating a class with a method is an easy affair: + +```dart +new ClassBuilder('Animal', extends: 'Organism') + ..addMethod(new MethodBuilder.returnVoid('eat') + ..setExpression(new ExpressionBuilder.invoke('print', + positional: [new LiteralString('Yum!')]))); +``` + +Outputs: +```dart +class Animal extends Organism { + void eat() => print('Yum!'); +} +``` + +This package is in development and APIs are subject to frequent change. diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml new file mode 100644 index 000000000..f7145dbf2 --- /dev/null +++ b/pkgs/code_builder/analysis_options.yaml @@ -0,0 +1,41 @@ +analyzer: + strong-mode: true +linter: + rules: + - avoid_empty_else + - comment_references + - control_flow_in_finally + - empty_statements + - hash_and_equals + - iterable_contains_unrelated_type + - list_remove_unrelated_type + - test_types_in_equals + - throw_in_finally + - unrelated_type_equality_checks + - valid_regexps + - always_declare_return_types + - annotate_overrides + - avoid_as + - avoid_init_to_null + - avoid_return_types_on_setters + - await_only_futures + - camel_case_types + - constant_identifier_names + - empty_catches + - 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 diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart new file mode 100644 index 000000000..bcde81ff2 --- /dev/null +++ b/pkgs/code_builder/lib/code_builder.dart @@ -0,0 +1,102 @@ +// 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. + +/// 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:analyzer/src/dart/ast/token.dart'; +import 'package:analyzer/src/generated/java_core.dart'; +import 'package:dart_style/dart_style.dart'; +import 'package:meta/meta.dart'; + +part 'src/annotation_builder.dart'; +part 'src/class_builder.dart'; +part 'src/constructor_builder.dart'; +part 'src/expression_builder.dart'; +part 'src/field_builder.dart'; +part 'src/file_builder.dart'; +part 'src/method_builder.dart'; +part 'src/parameter_builder.dart'; +part 'src/pretty_printer.dart'; +part 'src/statement_builder.dart'; +part 'src/type_builder.dart'; + +/// Base class for building and emitting a Dart language [AstNode]. +abstract class CodeBuilder { + /// Returns a copy-safe [AstNode] representing the current builder state. + A toAst(); +} + +// Simplifies some of the builders by having a mutable node we clone from. +abstract class _AbstractCodeBuilder extends CodeBuilder { + final A _astNode; + + _AbstractCodeBuilder._(this._astNode); + + /// Returns a copy-safe [AstNode] representing the current builder state. + @override + A toAst() => _cloneAst/**/(_astNode); + + @override + String toString() => '$runtimeType: ${_astNode.toSource()}'; +} + +/// Marker interface for builders that need an import to work. +/// +/// **NOTE**: This currently (as of 0.2.0) has no effect. It is planned that +/// the [FileBuilder] will be able to act as a scope 'resolver' and subtly +/// rewrite the AST tree to use prefixing if required (or requested). +abstract class RequiresImport implements CodeBuilder { + /// Imports that are required for this AST to work. + List get requiredImports; + + /// Creates a copy-safe [AstNode] representing the current builder state. + /// + /// Uses [scope] to output an AST re-written to use appropriate prefixes. + A toScopedAst(FileBuilder scope) => throw new UnimplementedError(); +} + +// Creates a defensive copy of an AST node. +AstNode/*=E*/ _cloneAst/**/(AstNode/*=E*/ astNode) { + return new AstCloner().cloneNode/**/(astNode); +} + +final DartFormatter _dartfmt = new DartFormatter(); + +/// Returns [source] formatted by `dartfmt`. +@visibleForTesting +String dartfmt(String source) => _dartfmt.format(source); + +Literal _stringLit(String s) { + return new SimpleStringLiteral(new StringToken(TokenType.STRING, s, 0), s); +} + +Identifier _stringId(String s) { + return new SimpleIdentifier(new StringToken(TokenType.STRING, s, 0)); +} diff --git a/pkgs/code_builder/lib/dart/core.dart b/pkgs/code_builder/lib/dart/core.dart new file mode 100644 index 000000000..f8c4e2170 --- /dev/null +++ b/pkgs/code_builder/lib/dart/core.dart @@ -0,0 +1,137 @@ +// 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:core` library for use in code generation. +/// +/// This library is currently *experimental*, and is subject to change; it +/// currently is manually written but there might be a strong use case for this +/// to be automatically generated (at least partially) in the near future. +library code_builder.dart.core; + +import 'package:code_builder/code_builder.dart'; + +/// An alias for `new AnnotationBuilder('override')`. +const AnnotationBuilder atOverride = const AnnotationBuilder.reference( + 'override', + 'dart:core', +); + +/// An alias for `new TypeBuilder('bool')`. +const TypeBuilder typeBool = const TypeBuilder( + 'bool', + importFrom: 'dart:core', +); + +/// An alias for `new TypeBuilder('DateTime')`. +const TypeBuilder typeDateTime = const TypeBuilder( + 'DateTime', + importFrom: 'dart:core', +); + +/// An alias for `new TypeBuilder('double')`. +const TypeBuilder typeDouble = const TypeBuilder( + 'double', + importFrom: 'dart:core', +); + +/// An alias for `new TypeBuilder('Duration')`. +const TypeBuilder typeDuration = const TypeBuilder( + 'Duration', + importFrom: 'dart:core', +); + +/// An alias for `new TypeBuilder('Expando')`. +const TypeBuilder typeExpando = const TypeBuilder( + 'Expando', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Function')`. +const TypeBuilder typeFunction = const TypeBuilder( + 'Function', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('int')`. +const TypeBuilder typeInt = const TypeBuilder( + 'int', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Iterable')`. +const TypeBuilder typeIterable = const TypeBuilder( + 'Iterable', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('List')`. +const TypeBuilder typeList = const TypeBuilder( + 'List', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Map')`. +const TypeBuilder typeMap = const TypeBuilder( + 'Map', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Null')`. +const TypeBuilder typeNull = const TypeBuilder( + 'Null', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('num')`. +const TypeBuilder typeNum = const TypeBuilder( + 'num', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Object')`. +const TypeBuilder typeObject = const TypeBuilder( + 'Object', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Set')`. +const TypeBuilder typeSet = const TypeBuilder( + 'Set', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('String')`. +const TypeBuilder typeString = const TypeBuilder( + 'String', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Symbol')`. +const TypeBuilder typeSymbol = const TypeBuilder( + 'Symbol', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Type')`. +const TypeBuilder typeType = const TypeBuilder( + 'Type', + importFrom: 'dart:core', +); + +/// An alias for `const TypeBuilder('Uri')`. +const TypeBuilder typeUri = const TypeBuilder( + 'Uri', + importFrom: 'dart:core', +); + +/// Creates either a `@deprecated` or `@Deprecated('Message')` annotation. +AnnotationBuilder atDeprecated([String message]) { + if (message == null) { + return new AnnotationBuilder.reference('deprecated', 'dart:core'); + } + return new AnnotationBuilder.invoke( + 'Deprecated', + positional: [new LiteralString(message)], + ); +} diff --git a/pkgs/code_builder/lib/src/annotation_builder.dart b/pkgs/code_builder/lib/src/annotation_builder.dart new file mode 100644 index 000000000..885bc409e --- /dev/null +++ b/pkgs/code_builder/lib/src/annotation_builder.dart @@ -0,0 +1,98 @@ +// 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. + +part of code_builder; + +/// Builds a metadata [Annotation] to be added to other AST elements. +/// +/// An annotation may either be a reference to an existing `const` identifier +/// _or_ to an invocation of a `const` class constructor. +/// +/// To create a `@doNotUse` reference, use [AnnotationBuilder.reference]: +/// const doNotUse = #do_not_use; +/// +/// @doNotUse +/// void destroyTheWorld() { ... } +/// +/// To create a `@DoNotUse('Blows up')` use [AnnotationBuilder.invoke]. +abstract class AnnotationBuilder implements RequiresImport { + /// Create a new annotated `const` [constructor] invocation. + /// + /// May optionally specify an [importFrom] to auto-prefix the annotation _if_ + /// attached to a library where the import is not specified or is prefixed. + factory AnnotationBuilder.invoke( + String constructor, { + String importFrom, + Iterable> positional: const [], + Map> named: const {}, + }) { + return new _ConstructorAnnotationBuilder( + constructor, + new ExpressionBuilder.invoke( + null, + positional: positional, + named: named, + ), + importFrom, + ); + } + + /// Create a new annotated `const` [identifier]. + /// + /// May optionally specify an [importFrom] to auto-prefix the annotation _if_ + /// attached to a library where the import is not specified or is prefixed. + const factory AnnotationBuilder.reference(String identifier, + [String importFrom]) = _ReferenceAnnotationBuilder; +} + +class _ConstructorAnnotationBuilder extends RequiresImport + implements AnnotationBuilder { + final String _constructor; + final ExpressionBuilder _expression; + final String _importFrom; + + _ConstructorAnnotationBuilder(this._constructor, this._expression, + [this._importFrom]); + + @override + List get requiredImports => [_importFrom]; + + @override + Annotation toAst() { + var expressionAst = _expression.toAst(); + if (expressionAst is MethodInvocation) { + return new Annotation( + null, + _stringId(_constructor), + null, + null, + // TODO(matanl): InvocationExpression needs to be public API. + expressionAst.argumentList, + ); + } + throw new UnsupportedError('Expression must be InvocationExpression'); + } +} + +class _ReferenceAnnotationBuilder implements AnnotationBuilder { + final String _importFrom; + final String _reference; + + const _ReferenceAnnotationBuilder(this._reference, [this._importFrom]); + + @override + List get requiredImports => [_importFrom]; + + @override + Annotation toAst() => new Annotation( + null, + _stringId(_reference), + null, + null, + null, + ); + + @override + Annotation toScopedAst(_) => throw new UnimplementedError(); +} diff --git a/pkgs/code_builder/lib/src/class_builder.dart b/pkgs/code_builder/lib/src/class_builder.dart new file mode 100644 index 000000000..e9ca4170e --- /dev/null +++ b/pkgs/code_builder/lib/src/class_builder.dart @@ -0,0 +1,97 @@ +// 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. + +part of code_builder; + +/// Builds a [ClassDeclaration] AST. +class ClassBuilder extends _AbstractCodeBuilder { + static Token _abstract = new KeywordToken(Keyword.ABSTRACT, 0); + static Token _extends = new KeywordToken(Keyword.EXTENDS, 0); + static Token _implements = new KeywordToken(Keyword.IMPLEMENTS, 0); + static Token _with = new KeywordToken(Keyword.WITH, 0); + + /// Create a new builder for a `class` named [name]. + /// + /// Optionally, define another class to [extend] or classes to either + /// [implement] or [mixin]. You may also define a `class` as [abstract]. + factory ClassBuilder( + String name, { + bool abstract: false, + String extend, + Iterable implement: const [], + Iterable mixin: const [], + }) { + var astNode = _emptyClassDeclaration()..name = _stringId(name); + if (abstract) { + astNode.abstractKeyword = _abstract; + } + if (extend != null) { + astNode.extendsClause = new ExtendsClause( + _extends, + new TypeName( + _stringId(extend), + null, + )); + } + if (implement.isNotEmpty) { + astNode.implementsClause = new ImplementsClause( + _implements, + implement + .map/**/((i) => new TypeName(_stringId(i), null)) + .toList()); + } + if (mixin.isNotEmpty) { + astNode.withClause = new WithClause( + _with, + mixin + .map/**/((i) => new TypeName(_stringId(i), null)) + .toList()); + } + return new ClassBuilder._(astNode); + } + + ClassBuilder._(ClassDeclaration astNode) : super._(astNode); + + /// Adds an annotation [builder] as metadata. + void addAnnotation(AnnotationBuilder builder) { + _astNode.metadata.add(builder.toAst()); + } + + /// Adds a constructor [builder]. + void addConstructor(ConstructorBuilder builder) { + var astNode = builder.toAst(); + if (astNode.returnType == null) { + astNode.returnType = _astNode.name; + } + _astNode.members.add(astNode); + } + + /// Adds a field [builder] as a member on the class. + void addField(FieldBuilder builder, {bool static: false}) { + _astNode.members.add(builder.toFieldAst(static: static)); + } + + /// Adds a method [builder] as a member on the class. + void addMethod(MethodBuilder builder, {bool static: false}) { + _astNode.members.add(builder.toMethodAst( + static: static, + canBeAbstract: _astNode.abstractKeyword != null, + )); + } + + static ClassDeclaration _emptyClassDeclaration() => new ClassDeclaration( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + ); +} diff --git a/pkgs/code_builder/lib/src/constructor_builder.dart b/pkgs/code_builder/lib/src/constructor_builder.dart new file mode 100644 index 000000000..0839a05cb --- /dev/null +++ b/pkgs/code_builder/lib/src/constructor_builder.dart @@ -0,0 +1,60 @@ +// 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. + +part of code_builder; + +/// Builds a [ConstructorDeclaration] AST. +/// +/// Similar to [MethodBuilder] but adds constructor-only features. +/// +/// Use [ConstructorBuilder.initializeFields] to create something like: +/// class Foo { +/// final _one; +/// final _two; +/// +/// Foo(this._one, this._two); +/// } +class ConstructorBuilder extends _AbstractCodeBuilder { + static final Token _const = new KeywordToken(Keyword.CONST, 0); + static final Token _this = new KeywordToken(Keyword.THIS, 0); + + /// Create a simple [ConstructorBuilder] that initializes class fields. + /// + /// May optionally be [constant] compatible, or have a [name]. + factory ConstructorBuilder.initializeFields( + {bool constant: false, + String name, + Iterable positionalArguments: const [], + Iterable optionalArguments: const [], + Iterable namedArguments: const []}) { + var parameters = []; + for (var a in positionalArguments) { + parameters.add(new ParameterBuilder(a, field: true).toAst()); + } + for (var a in optionalArguments) { + parameters.add(new ParameterBuilder.optional(a, field: true).toAst()); + } + for (var a in namedArguments) { + parameters.add(new ParameterBuilder.named(a, field: true).toAst()); + } + var astNode = new ConstructorDeclaration( + null, + null, + null, + null, + constant ? _const : null, + null, + null, + name != null ? _stringId(name) : null, + MethodBuilder._emptyParameters()..parameters.addAll(parameters), + null, + null, + null, + new EmptyFunctionBody(MethodBuilder._semicolon), + ); + return new ConstructorBuilder._(astNode); + } + + ConstructorBuilder._(ConstructorDeclaration astNode) : super._(astNode); +} diff --git a/pkgs/code_builder/lib/src/expression_builder.dart b/pkgs/code_builder/lib/src/expression_builder.dart new file mode 100644 index 000000000..8147978c2 --- /dev/null +++ b/pkgs/code_builder/lib/src/expression_builder.dart @@ -0,0 +1,186 @@ +// 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. + +part of code_builder; + +// Shared functionality between ExpressionBuilder and _LiteralExpression. +final Token _closeP = new Token(TokenType.CLOSE_PAREN, 0); +final Token _openP = new Token(TokenType.OPEN_PAREN, 0); +final Token _semicolon = new Token(TokenType.SEMICOLON, 0); + +// Returns wrapped as a [ExpressionFunctionBody] AST. +ExpressionFunctionBody _asFunctionBody(CodeBuilder expression) { + return new ExpressionFunctionBody( + null, + null, + expression.toAst(), + _semicolon, + ); +} + +// Returns wrapped as a [FunctionExpression] AST. +FunctionExpression _asFunctionExpression(CodeBuilder expression) { + return new FunctionExpression( + null, + new FormalParameterList( + _openP, + const [], + null, + null, + _closeP, + ), + _asFunctionBody(expression), + ); +} + +/// Builds an [Expression] AST. +/// +/// For simple literal expressions see: +/// - [LiteralBool] and [literalTrue] [literalFalse] +/// - [LiteralInt] +/// - [LiteralString] +/// - [literalNull] +abstract class ExpressionBuilder implements CodeBuilder { + /// Invoke [name] (which should be available in the local scope). + /// + /// Optionally specify [positional] and [named] arguments. + factory ExpressionBuilder.invoke( + String name, { + Iterable> positional: const [], + Map> named: const {}, + }) { + return new _InvokeExpression( + name, + new List>.unmodifiable(positional), + new Map>.unmodifiable(named), + ); + } + + const ExpressionBuilder._(); + + /// Returns wrapped as a [ExpressionFunctionBody] AST. + ExpressionFunctionBody toFunctionBody() => _asFunctionBody(this); + + /// Returns wrapped as a [FunctionExpression] AST. + FunctionExpression toFunctionExpression() => _asFunctionExpression(this); +} + +// TODO(matanl): Make this part of the public API. See annotation_builder.dart. +class _InvokeExpression extends ExpressionBuilder + implements CodeBuilder { + static final Token _colon = new Token(TokenType.COLON, 0); + + final String _name; + final List> _positionalArguments; + final Map> _namedArguments; + + const _InvokeExpression( + this._name, + this._positionalArguments, + this._namedArguments, + ) + : super._(); + + ArgumentList _getArgumentList() { + return new ArgumentList( + new Token(TokenType.OPEN_CURLY_BRACKET, 0), + _positionalArguments.map/* p.toAst()).toList() + ..addAll(_namedArguments.keys + .map/**/((name) => new NamedExpression( + new Label( + _stringId(name), + _colon, + ), + _namedArguments[name].toAst(), + ))), + new Token(TokenType.CLOSE_CURLY_BRACKET, 0), + ); + } + + @override + InvocationExpression toAst() { + return new MethodInvocation( + null, + null, + _stringId(_name), + null, + _getArgumentList(), + ); + } +} + +abstract class _LiteralExpression + implements ExpressionBuilder, CodeBuilder { + const _LiteralExpression(); + + @override + ExpressionFunctionBody toFunctionBody() => _asFunctionBody(this); + + @override + FunctionExpression toFunctionExpression() => _asFunctionExpression(this); +} + +/// Represents an expression value of `true`. +const literalTrue = const LiteralBool(true); + +/// Represents an expression value of `false`. +const literalFalse = const LiteralBool(false); + +/// Creates a new literal `bool` value. +class LiteralBool extends _LiteralExpression { + static final BooleanLiteral _true = + new BooleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); + static final BooleanLiteral _false = + new BooleanLiteral(new KeywordToken(Keyword.FALSE, 0), false); + + final bool _value; + + /// Returns the passed value as a [BooleanLiteral]. + const LiteralBool(this._value); + + @override + BooleanLiteral toAst() => _value ? _true : _false; +} + +/// Represents an expression value of `null`. +const literalNull = const _LiteralNull(); + +class _LiteralNull extends _LiteralExpression { + static NullLiteral _null = new NullLiteral(new KeywordToken(Keyword.NULL, 0)); + + const _LiteralNull(); + + @override + NullLiteral toAst() => _null; +} + +/// Represents an expression value of a literal number. +class LiteralInt extends _LiteralExpression { + final int _value; + + /// Returns the passed value as a [IntegerLiteral]. + const LiteralInt(this._value); + + @override + IntegerLiteral toAst() => + new IntegerLiteral(new StringToken(TokenType.INT, '$_value', 0), _value); +} + +/// Represents an expression value of a literal `'string'`. +class LiteralString extends _LiteralExpression { + final String _value; + + /// Returns the passed value as a [StringLiteral]. + const LiteralString(this._value); + + @override + StringLiteral toAst() => new SimpleStringLiteral( + new StringToken( + TokenType.STRING, + "'$_value'", + 0, + ), + _value, + ); +} diff --git a/pkgs/code_builder/lib/src/field_builder.dart b/pkgs/code_builder/lib/src/field_builder.dart new file mode 100644 index 000000000..c6e9e2c24 --- /dev/null +++ b/pkgs/code_builder/lib/src/field_builder.dart @@ -0,0 +1,110 @@ +// 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. + +part of code_builder; + +/// Builds either a [FieldDeclaration] or [VariableDeclaration] AST. +/// +/// While the API is the same, you may specifically ask for either a field +/// AST (for class members) via [toFieldAst] or a variable declaration (used +/// both at the top-level and within methods) via [toVariablesAst]. +class FieldBuilder implements CodeBuilder { + static Token _equals = new Token(TokenType.EQ, 0); + static Token _semicolon = new Token(TokenType.SEMICOLON, 0); + static Token _static = new KeywordToken(Keyword.STATIC, 0); + static Token _final = new KeywordToken(Keyword.FINAL, 0); + static Token _const = new KeywordToken(Keyword.CONST, 0); + static Token _var = new KeywordToken(Keyword.VAR, 0); + + final bool _isConst; + final bool _isFinal; + final ExpressionBuilder _initialize; + final String _name; + final TypeBuilder _type; + + /// Create a new field builder. + /// + /// Optionally set a type and initializer. + FieldBuilder( + this._name, { + TypeBuilder type, + ExpressionBuilder initialize, + }) + : this._type = type, + this._initialize = initialize, + this._isFinal = false, + this._isConst = false; + + /// Create a new field builder that emits a `const` field. + /// + /// Optionally set a type and initializer. + FieldBuilder.isConst( + this._name, { + TypeBuilder type, + ExpressionBuilder initialize, + }) + : this._type = type, + this._initialize = initialize, + this._isFinal = false, + this._isConst = true; + + /// Create a new field builder that emits a `final` field. + /// + /// Optionally set a type and initializer. + FieldBuilder.isFinal( + this._name, { + TypeBuilder type, + ExpressionBuilder initialize, + }) + : this._type = type, + this._initialize = initialize, + this._isFinal = true, + this._isConst = false; + + Token _getVariableKeyword() { + if (_isFinal) { + return _final; + } + if (_isConst) { + return _const; + } + return _type == null ? _var : null; + } + + /// Returns a copy-safe [AstNode] representing the current builder state. + /// + /// **NOTE**: This method exists primarily for testing and compatibility with + /// the [CodeBuilder] ADT. When possible, invoke [toFieldAst] or + /// [toVariablesAst]. + @override + @visibleForTesting + Declaration toAst() => toFieldAst(); + + /// Returns a copy-safe [FieldDeclaration] AST representing current state. + FieldDeclaration toFieldAst({ + bool static: false, + }) => + new FieldDeclaration( + null, + null, + static ? _static : null, + toVariablesAst(), + null, + ); + + /// Returns a copy-safe [VariableDeclaration] AST representing current state. + VariableDeclarationList toVariablesAst() => new VariableDeclarationList( + null, + null, + _getVariableKeyword(), + _type?.toAst(), + [ + new VariableDeclaration( + _stringId(_name), + _initialize != null ? _equals : null, + _initialize?.toAst(), + ) + ], + ); +} diff --git a/pkgs/code_builder/lib/src/file_builder.dart b/pkgs/code_builder/lib/src/file_builder.dart new file mode 100644 index 000000000..bb2e99b50 --- /dev/null +++ b/pkgs/code_builder/lib/src/file_builder.dart @@ -0,0 +1,133 @@ +// 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. + +part of code_builder; + +/// Builds files of Dart source code. +/// +/// Files may either be a standalone library or `part of` another library. +class FileBuilder extends _AbstractCodeBuilder { + static Token _library = new KeywordToken(Keyword.LIBRARY, 0); + static Token _part = new KeywordToken(Keyword.PART, 0); + static Token _of = new StringToken(TokenType.KEYWORD, 'of', 0); + + /// Create a new standalone Dart library, optionally with a [name]. + factory FileBuilder([String name]) { + var astNode = _emptyCompilationUnit(); + if (name != null) { + astNode.directives.add(new LibraryDirective( + null, + null, + _library, + new LibraryIdentifier([_stringId(name)]), + null, + )); + } + return new FileBuilder._(astNode); + } + + /// Create a new `part of` the dart library with [name]. + factory FileBuilder.partOf(String name) { + var astNode = _emptyCompilationUnit(); + astNode.directives.add(new PartOfDirective( + null, + null, + _part, + _of, + new LibraryIdentifier([_stringId(name)]), + null, + )); + return new FileBuilder._(astNode); + } + + FileBuilder._(CompilationUnit astNode) : super._(astNode); + + /// Add a copy of [clazz] as a declaration in this file. + void addClass(ClassBuilder clazz) { + _astNode.declarations.add(clazz.toAst()); + } + + /// Adds an `import` or `export` [directive]. + void addDirective(CodeBuilder directive) { + if (isPartOf) { + throw const DartPartFileException._(); + } + _astNode.directives.add(directive.toAst()); + } + + static CompilationUnit _emptyCompilationUnit() => new CompilationUnit( + null, + null, + null, + null, + null, + ); + + static bool _isPartOf(Directive d) => d is PartOfDirective; + + /// Whether the file is `part of` another. + bool get isPartOf => _astNode.directives.contains(_isPartOf); +} + +/// An `export` directive in a [FileBuilder]. +class ExportBuilder extends _AbstractCodeBuilder { + /// Create a new `export` directive exporting [uri]. + factory ExportBuilder(String uri) { + var astNode = _createExportDirective()..uri = _stringLit("'$uri'"); + return new ExportBuilder._(astNode); + } + + ExportBuilder._(ExportDirective astNode) : super._(astNode); + + static ExportDirective _createExportDirective() => new ExportDirective( + null, + null, + null, + null, + null, + null, + null, + ); +} + +/// An `import` directive in a [FileBuilder]. +class ImportBuilder extends _AbstractCodeBuilder { + static Token _as = new KeywordToken(Keyword.AS, 0); + + /// Create a new `import` directive importing [uri]. + /// + /// Optionally prefix [as]. + factory ImportBuilder(String uri, {String as}) { + var astNode = _createImportDirective()..uri = _stringLit("'$uri'"); + if (as != null) { + astNode + ..asKeyword = _as + ..prefix = _stringId(as); + } + return new ImportBuilder._(astNode); + } + + ImportBuilder._(ImportDirective astNode) : super._(astNode); + + static ImportDirective _createImportDirective() => new ImportDirective( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + ); +} + +/// Thrown when an invalid operation is attempted on a [FileBuilder] instance. +class DartPartFileException implements Exception { + const DartPartFileException._(); + + @override + String toString() => 'Not a valid operation for a `part of` file.'; +} diff --git a/pkgs/code_builder/lib/src/method_builder.dart b/pkgs/code_builder/lib/src/method_builder.dart new file mode 100644 index 000000000..6a96e0c07 --- /dev/null +++ b/pkgs/code_builder/lib/src/method_builder.dart @@ -0,0 +1,174 @@ +// 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. + +part of code_builder; + +/// Builds either a [MethodDeclaration] or a [FunctionDeclaration]. +/// +/// While the API is the same, you may specifically ask for either a method +/// AST (for class members) via [toMethodAst] or a function AST (used both at +/// the top level and within other methods) via [toFunctionAst]. +/// +/// To return nothing (`void`), use [MethodBuilder.returnVoid]. +class MethodBuilder implements CodeBuilder { + static Token _abstract = new KeywordToken(Keyword.ABSTRACT, 0); + static Token _semicolon = new Token(TokenType.SEMICOLON, 0); + static Token _static = new KeywordToken(Keyword.STATIC, 0); + + // Void is a "type" that is only valid as a return type on a method. + static const TypeBuilder _typeVoid = const TypeBuilder('void'); + + final List _annotations = []; + final String _name; + final List _parameters = []; + final List _statements = []; + + ExpressionBuilder _returnExpression; + TypeBuilder _returnType; + + /// Create a new method builder, + /// + /// Optionally set a [returns] type. + factory MethodBuilder({String name, TypeBuilder returns}) { + return new MethodBuilder._(name, returns); + } + + /// Creates a `void`-returning MethodBuilder with [name]. + factory MethodBuilder.returnVoid([String name]) { + return new MethodBuilder._(name, _typeVoid); + } + + MethodBuilder._(this._name, this._returnType); + + /// Lazily adds [annotation]. + /// + /// When the method is emitted as an AST, [AnnotationBuilder.toAst] is used. + void addAnnotation(AnnotationBuilder annotation) { + _annotations.add(annotation); + } + + /// Lazily adds [parameter]. + /// + /// When the method is emitted as an AST, [ParameterBuilder.toAst] is used. + void addParameter(ParameterBuilder parameter) { + _parameters.add(parameter); + } + + static FunctionBody _emptyBlockBody() => new BlockFunctionBody( + null, + null, + new Block( + new Token(TokenType.OPEN_CURLY_BRACKET, 0), + null, + new Token(TokenType.CLOSE_CURLY_BRACKET, 0), + ), + ); + + static FunctionDeclaration _emptyFunction() => new FunctionDeclaration( + null, + null, + null, + null, + null, + null, + new FunctionExpression( + null, + _emptyParameters(), + _emptyBlockBody(), + ), + ); + + static MethodDeclaration _emptyMethod() => new MethodDeclaration( + null, + null, + null, + null, + null, + null, + null, + null, + null, + _emptyParameters(), + null, + ); + + static FormalParameterList _emptyParameters() => new FormalParameterList( + new Token(TokenType.OPEN_PAREN, 0), + [], + null, + null, + new Token(TokenType.CLOSE_PAREN, 0), + ); + + /// Lazily adds [statement]. + /// + /// When the method is emitted as an AST, [StatementBuilder.toAst] is used. + void addStatement(StatementBuilder statement) { + _statements.add(statement); + } + + /// Lazily sets [expression] as the lambda result of this method invocation. + /// + /// When the method is emitted as an AST, [ExpressionBuilder.toAst] is used. + void setExpression(ExpressionBuilder expression) { + _returnExpression = expression; + } + + /// Returns a copy-safe [AstNode] representing the current builder state. + /// + /// **NOTE**: This method exists primarily for testing and compatibility with + /// the [CodeBuilder] ADT. When possible, invoke [toFunctionAst] or + /// [toMethodAst]. + @override + @visibleForTesting + Declaration toAst() => toFunctionAst(); + + /// Returns a copy-safe [FunctionDeclaration] AST representing current state. + FunctionDeclaration toFunctionAst() { + var functionAst = _emptyFunction() + ..metadata.addAll(_annotations.map/**/((a) => a.toAst())) + ..name = _stringId(_name) + ..returnType = _returnType?.toAst(); + if (_returnExpression != null) { + functionAst.functionExpression = _returnExpression.toFunctionExpression(); + } + if (_parameters.isNotEmpty) { + functionAst.functionExpression.parameters = _emptyParameters() + ..parameters + .addAll(_parameters.map/**/((p) => p.toAst())); + } + return functionAst; + } + + /// Returns a copy-safe [FunctionDeclaration] AST representing current state. + MethodDeclaration toMethodAst({ + bool static: false, + bool canBeAbstract: false, + }) { + var methodAst = _emptyMethod() + ..metadata.addAll(_annotations.map/**/((a) => a.toAst())) + ..name = _stringId(_name) + ..returnType = _returnType?.toAst(); + FunctionBody methodBody = _returnExpression?.toFunctionBody(); + if (static) { + methodAst.modifierKeyword = _static; + if (methodBody == null) { + methodBody = _emptyBlockBody(); + } + } + if (methodBody == null) { + methodBody = + canBeAbstract ? new EmptyFunctionBody(_semicolon) : _emptyBlockBody(); + } + if (_parameters.isNotEmpty) { + methodAst.parameters.parameters + .addAll(_parameters.map/**/((p) => p.toAst())); + } + methodAst.body = methodBody; + return methodAst; + } + + @override + String toString() => 'MethodBuilder ${toAst().toSource()}'; +} diff --git a/pkgs/code_builder/lib/src/parameter_builder.dart b/pkgs/code_builder/lib/src/parameter_builder.dart new file mode 100644 index 000000000..bf710d176 --- /dev/null +++ b/pkgs/code_builder/lib/src/parameter_builder.dart @@ -0,0 +1,130 @@ +// 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. + +part of code_builder; + +/// Build a [FormalParameter] AST. +/// +/// A parameter is part of a built [MethodBuilder], and can refer to a +/// class-member (field) variable (see the `field` property in the +/// constructors). +class ParameterBuilder extends _AbstractCodeBuilder { + static final Token _this = new KeywordToken(Keyword.THIS, 0); + + /// Create a new _required_ parameter of [name]. + factory ParameterBuilder( + String name, { + bool field: false, + TypeBuilder type, + }) { + FormalParameter astNode; + if (field) { + astNode = new FieldFormalParameter( + null, + null, + null, + type?.toAst(), + _this, + null, + _stringId(name), + null, + null, + ); + } else { + astNode = new SimpleFormalParameter( + null, + null, + null, + type?.toAst(), + _stringId(name), + ); + } + return new ParameterBuilder._(astNode); + } + + /// Create a new _optional_ (but positional) parameter. + /// + /// See [ParameterBuilder.named] for an optional _named_ parameter. + factory ParameterBuilder.optional( + String name, { + bool field: false, + TypeBuilder type, + ExpressionBuilder defaultTo, + }) { + return new ParameterBuilder._optional( + name, + false, + field: field, + type: type, + defaultTo: defaultTo, + ); + } + + /// Create a new _optional_ _named_ parameter. + factory ParameterBuilder.named( + String name, { + bool field: false, + TypeBuilder type, + ExpressionBuilder defaultTo, + }) { + return new ParameterBuilder._optional( + name, + true, + field: field, + type: type, + defaultTo: defaultTo, + ); + } + + // Actual implementation of optional and named. + factory ParameterBuilder._optional( + String name, + bool named, { + bool field: false, + TypeBuilder type, + ExpressionBuilder defaultTo, + }) { + FormalParameter astNode; + if (field) { + astNode = new FieldFormalParameter( + null, + null, + null, + type?.toAst(), + _this, + null, + _stringId(name), + null, + null, + ); + } else { + astNode = new SimpleFormalParameter( + null, + null, + null, + type?.toAst(), + _stringId(name), + ); + } + Token defaultToEq; + if (defaultTo != null) { + defaultToEq = + named ? new Token(TokenType.COLON, 0) : new Token(TokenType.EQ, 0); + } + astNode = new DefaultFormalParameter( + astNode, + named ? ParameterKind.NAMED : ParameterKind.POSITIONAL, + defaultToEq, + defaultTo?.toAst(), + ); + return new ParameterBuilder._(astNode); + } + + ParameterBuilder._(FormalParameter astNode) : super._(astNode); + + /// Adds a metadata annotation from [builder]. + void addAnnotation(AnnotationBuilder builder) { + _astNode.metadata.add(builder.toAst()); + } +} diff --git a/pkgs/code_builder/lib/src/pretty_printer.dart b/pkgs/code_builder/lib/src/pretty_printer.dart new file mode 100644 index 000000000..ce8c148f8 --- /dev/null +++ b/pkgs/code_builder/lib/src/pretty_printer.dart @@ -0,0 +1,103 @@ +// 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. + +part of code_builder; + +/// Augments [AstNode.toSource] by adding some whitespace/line breaks. +/// +/// The final result is run through `dartfmt`. +/// +/// This is the _recommended_ output (but not required) when comparing ASTs +/// to expected golden files/text blobs. +String prettyToSource(AstNode astNode) { + var writer = new PrintStringWriter(); + var visitor = new _PrettyToSourceVisitor(writer); + astNode.accept(visitor); + return dartfmt(writer.toString()); +} + +// TODO(matanl): Remove copied-pasted methods when API becomes available. +// https://github.com/dart-lang/sdk/issues/27169 +class _PrettyToSourceVisitor extends ToSourceVisitor { + // Removed in a new version of the analyzer, but due to dartfmt it's not + // possible to refer to the newest analyzer and use dartfmt. + // https://github.com/dart-lang/sdk/issues/27301 + final PrintStringWriter _writer; + + _PrettyToSourceVisitor(PrintStringWriter writer) + : _writer = writer, + super(writer); + + @override + Object visitClassDeclaration(ClassDeclaration node) { + _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); + _visitTokenWithSuffix(node.abstractKeyword, " "); + _writer.print("class "); + _visitNode(node.name); + _visitNode(node.typeParameters); + _visitNodeWithPrefix(" ", node.extendsClause); + _visitNodeWithPrefix(" ", node.withClause); + _visitNodeWithPrefix(" ", node.implementsClause); + _writer.print(" {"); + _visitNodeListWithSeparator(node.members, "\n\n"); + _writer.print("}"); + return null; + } + + // Safely visit the given [node]. + void _visitNode(AstNode node) { + if (node != null) { + node.accept(this); + } + } + + // Write a list of [nodes], separated by the given [separator]. + void _visitNodeListWithSeparator(NodeList nodes, String separator) { + if (nodes != null) { + int size = nodes.length; + for (int i = 0; i < size; i++) { + if (i > 0) { + _writer.print(separator); + } + nodes[i].accept(this); + } + } + } + + // Write a list of [nodes], separated by the given [separator], followed by + // the given [suffix] if the list is not empty. + void _visitNodeListWithSeparatorAndSuffix( + NodeList nodes, String separator, String suffix) { + if (nodes != null) { + int size = nodes.length; + if (size > 0) { + for (int i = 0; i < size; i++) { + if (i > 0) { + _writer.print(separator); + } + nodes[i].accept(this); + } + _writer.print(suffix); + } + } + } + + // Safely visit the given [node], writing the [prefix] before the node if it + // is non-`null`. + void _visitNodeWithPrefix(String prefix, AstNode node) { + if (node != null) { + _writer.print(prefix); + node.accept(this); + } + } + + // Safely visit the given [token], writing the [suffix] after the token if it + // is non-`null`. + void _visitTokenWithSuffix(Token token, String suffix) { + if (token != null) { + _writer.print(token.lexeme); + _writer.print(suffix); + } + } +} diff --git a/pkgs/code_builder/lib/src/statement_builder.dart b/pkgs/code_builder/lib/src/statement_builder.dart new file mode 100644 index 000000000..fd5a794a1 --- /dev/null +++ b/pkgs/code_builder/lib/src/statement_builder.dart @@ -0,0 +1,10 @@ +// 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. + +part of code_builder; + +/// Builds a [Statement] AST. +abstract class StatementBuilder implements CodeBuilder { + // TODO(matanl): Implement (not required immediately as we have expressions). +} diff --git a/pkgs/code_builder/lib/src/type_builder.dart b/pkgs/code_builder/lib/src/type_builder.dart new file mode 100644 index 000000000..45aac3213 --- /dev/null +++ b/pkgs/code_builder/lib/src/type_builder.dart @@ -0,0 +1,32 @@ +// 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. + +part of code_builder; + +/// Build a [TypeName] AST. +class TypeBuilder implements RequiresImport { + final String _identifier; + final String _importFrom; + + /// Create a builder for emitting a [TypeName] AST. + /// + /// Optionally specify what must be imported for this type to resolve. + /// + /// __Example use__: + /// const TypeBuilder('String', importFrom: 'dart:core') + const TypeBuilder(this._identifier, {String importFrom}) + : _importFrom = importFrom; + + @override + List get requiredImports => [_importFrom]; + + @override + TypeName toAst() => new TypeName( + _stringId(_identifier), + null, + ); + + @override + TypeName toScopedAst(FileBuilder scope) => throw new UnimplementedError(); +} diff --git a/pkgs/code_builder/lib/testing/equals_source.dart b/pkgs/code_builder/lib/testing/equals_source.dart new file mode 100644 index 000000000..a706e7dcd --- /dev/null +++ b/pkgs/code_builder/lib/testing/equals_source.dart @@ -0,0 +1,73 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:matcher/matcher.dart'; + +/// Returns a [Matcher] that checks a [CodeBuilder] versus [source]. +/// +/// On failure, uses the default string matcher to show a detailed diff between +/// the expected and actual source code results. +/// +/// **NOTE**: By default it both runs `dartfmt` _and_ prints the source with +/// additional formatting over the default `Ast.toSource` implementation (i.e. +/// adds new lines between methods in classes, and more). +/// +/// If you have code that is not consider a valid compilation unit (like an +/// expression, you should flip [format] to `false`). +Matcher equalsSource(String source, {bool format: true}) { + return new _EqualsSource(format ? dartfmt(source) : source, format); +} + +// Delegates to the default matcher (which delegates further). +// +// Would be nice to just use more of package:matcher directly: +// https://github.com/dart-lang/matcher/issues/36 +class _EqualsSource extends Matcher { + final String _source; + final bool _isFormatted; + + _EqualsSource(this._source, this._isFormatted); + + @override + Description describe(Description description) { + return equals(_source).describe(description); + } + + @override + Description describeMismatch( + item, + Description mismatchDescription, + Map matchState, + bool verbose, + ) { + if (item is CodeBuilder) { + return equals(_source).describeMismatch( + _formatAst(item), + mismatchDescription, + matchState, + verbose, + ); + } else { + return mismatchDescription.add('$item is not a CodeBuilder'); + } + } + + String _formatAst(CodeBuilder builder) { + var ast = builder.toAst(); + if (_isFormatted) { + return prettyToSource(ast); + } else { + return ast.toSource(); + } + } + + @override + bool matches(item, _) { + if (item is CodeBuilder) { + return _formatAst(item) == _source; + } + return false; + } +} diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml new file mode 100644 index 000000000..73a0602cb --- /dev/null +++ b/pkgs/code_builder/pubspec.yaml @@ -0,0 +1,17 @@ +name: code_builder +version: 0.1.0 +description: A fluent API for generating Dart code +author: Dart Team +homepage: https://github.com/dart-lang/code_builder + +environment: + sdk: '>=1.9.1 <2.0.0' + +dependencies: + analyzer: ">=0.27.1 <0.29.0" + dart_style: ^0.2.9+1 + matcher: ^0.12.0+2 + meta: ^1.0.2 + +dev_dependencies: + test: ^0.12.0 diff --git a/pkgs/code_builder/test/builders/class_builder_test.dart b/pkgs/code_builder/test/builders/class_builder_test.dart new file mode 100644 index 000000000..ac4cf9168 --- /dev/null +++ b/pkgs/code_builder/test/builders/class_builder_test.dart @@ -0,0 +1,161 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing/equals_source.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit an empty class', () { + expect(new ClassBuilder('Animal'), equalsSource('class Animal {}')); + }); + + test('should emit an abstract class', () { + expect( + new ClassBuilder('Animal', abstract: true), + equalsSource('abstract class Animal {}'), + ); + }); + + test('should emit a class extending another class', () { + expect( + new ClassBuilder('Animal', extend: 'Organism'), + equalsSource('class Animal extends Organism {}'), + ); + }); + + test('should emit a class implementing another class', () { + expect( + new ClassBuilder('Animal', implement: ['Delicious']), + equalsSource('class Animal implements Delicious {}'), + ); + }); + + test('should emit a class extending and mixing in another class', () { + expect( + new ClassBuilder('Animal', extend: 'Organism', mixin: ['Breathing']), + equalsSource('class Animal extends Organism with Breathing {}'), + ); + }); + + test('should emit a class with a method', () { + expect( + new ClassBuilder('Animal') + ..addMethod(new MethodBuilder( + name: 'toString', + returns: typeString, + )..setExpression(const LiteralString('Delicious'))), + equalsSource(r''' + class Animal { + String toString() => 'Delicious'; + } + '''), + ); + }); + + test('should emit an abstract class with an abstract method', () { + expect( + new ClassBuilder('Animal', abstract: true) + ..addMethod( + new MethodBuilder.returnVoid('eat'), + ), + equalsSource(r''' + abstract class Animal { + void eat(); + } + '''), + ); + }); + + test('should emit a class with a static method', () { + expect( + new ClassBuilder('Animal') + ..addMethod( + new MethodBuilder( + name: 'create', + returns: new TypeBuilder('Animal'), + )..setExpression(literalNull), + static: true, + ), + equalsSource(r''' + class Animal { + static Animal create() => null; + } + '''), + ); + }); + + test('should emit a class with a metadata annotation', () { + expect( + new ClassBuilder('Animal')..addAnnotation(atDeprecated()), + equalsSource(r''' + @deprecated + class Animal {} + '''), + ); + }); + + test('should emit a class with an invoking metadata annotation', () { + expect( + new ClassBuilder('Animal') + ..addAnnotation(atDeprecated('We ate them all')), + equalsSource(r''' + @Deprecated('We ate them all') + class Animal {} + '''), + ); + }); + + group('constructors', () { + ClassBuilder clazz; + + setUp(() { + clazz = new ClassBuilder('Animal'); + }); + + test('default constructor', () { + clazz.addConstructor(new ConstructorBuilder.initializeFields()); + expect( + clazz, + equalsSource( + r''' + class Animal { + Animal(); + } + ''', + )); + }); + + test('default const constructor', () { + clazz.addConstructor( + new ConstructorBuilder.initializeFields(constant: true)); + expect( + clazz, + equalsSource( + r''' + class Animal { + const Animal(); + } + ''', + )); + }); + + test('initializing fields', () { + clazz.addConstructor(new ConstructorBuilder.initializeFields( + positionalArguments: ['a'], + optionalArguments: ['b'], + )); + expect( + clazz, + equalsSource( + r''' + class Animal { + Animal(this.a, [this.b]); + } + ''', + )); + }); + }); +} diff --git a/pkgs/code_builder/test/builders/field_builder_test.dart b/pkgs/code_builder/test/builders/field_builder_test.dart new file mode 100644 index 000000000..95954b4c2 --- /dev/null +++ b/pkgs/code_builder/test/builders/field_builder_test.dart @@ -0,0 +1,49 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing/equals_source.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit an unitialized simple variable', () { + expect( + new FieldBuilder('name'), + equalsSource(r'var name;'), + ); + }); + + test('should emit a typed variable', () { + expect( + new FieldBuilder('name', type: typeString), + equalsSource(r'String name;'), + ); + }); + + test('should emit an initialized variable', () { + expect( + new FieldBuilder( + 'name', + type: typeString, + initialize: const LiteralString('Jill User'), + ), + equalsSource(r"String name = 'Jill User';"), + ); + }); + + test('should emit a final variable', () { + expect( + new FieldBuilder.isFinal('name'), + equalsSource(r'final name;'), + ); + }); + + test('should emit a const variable', () { + expect( + new FieldBuilder.isConst('name'), + equalsSource(r'const name;'), + ); + }); +} diff --git a/pkgs/code_builder/test/builders/file_builder_test.dart b/pkgs/code_builder/test/builders/file_builder_test.dart new file mode 100644 index 000000000..14fae003b --- /dev/null +++ b/pkgs/code_builder/test/builders/file_builder_test.dart @@ -0,0 +1,46 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/testing/equals_source.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit a blank file', () { + expect(new FileBuilder(), equalsSource('')); + }); + + test('should emit a file with a library directive', () { + expect( + new FileBuilder('code_builder'), equalsSource('library code_builder;')); + }); + + test('should emit a file with a part of directive', () { + expect( + new FileBuilder.partOf('code_builder'), + equalsSource('part of code_builder;'), + ); + }); + + test('should emit an import directive', () { + expect( + new ImportBuilder('package:foo/foo.dart'), + equalsSource("import 'package:foo/foo.dart';"), + ); + }); + + test('should emit an import directive and a prefix', () { + expect( + new ImportBuilder('package:foo/foo.dart', as: 'foo'), + equalsSource("import 'package:foo/foo.dart' as foo;"), + ); + }); + + test('should emit an export directive', () { + expect( + new ExportBuilder('package:foo/foo.dart'), + equalsSource("export 'package:foo/foo.dart';"), + ); + }); +} diff --git a/pkgs/code_builder/test/builders/method_builder_test.dart b/pkgs/code_builder/test/builders/method_builder_test.dart new file mode 100644 index 000000000..bcca43668 --- /dev/null +++ b/pkgs/code_builder/test/builders/method_builder_test.dart @@ -0,0 +1,244 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing/equals_source.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit a simple "void" method', () { + expect( + new MethodBuilder.returnVoid('main'), + equalsSource('void main() {}'), + ); + }); + + test('should emit a method returning a String', () { + expect( + new MethodBuilder(name: 'toString', returns: typeString), + equalsSource('String toString() {}'), + ); + }); + + test('should emit a method annotated', () { + expect( + new MethodBuilder(name: 'oldMethod')..addAnnotation(atDeprecated()), + equalsSource( + r''' + @deprecated + oldMethod() {} + ''', + )); + }); + + group('with an expression', () { + test('should return true', () { + expect( + new MethodBuilder(name: 'isSupported', returns: typeBool) + ..setExpression(literalTrue), + equalsSource( + r''' + bool isSupported() => true; + ''', + ), + ); + }); + + test('should return false', () { + expect( + new MethodBuilder(name: 'isSupported', returns: typeBool) + ..setExpression(literalFalse), + equalsSource( + r''' + bool isSupported() => false; + ''', + ), + ); + }); + + test('should return null', () { + expect( + new MethodBuilder(name: 'isSupported')..setExpression(literalNull), + equalsSource( + r''' + isSupported() => null; + ''', + ), + ); + }); + + test('should return "Hello World"', () { + expect( + new MethodBuilder(name: 'sayHello', returns: typeString) + ..setExpression( + const LiteralString('Hello World'), + ), + equalsSource( + r''' + String sayHello() => 'Hello World'; + ''', + ), + ); + }); + + group('with parameters:', () { + MethodBuilder method; + + setUp(() { + method = new MethodBuilder.returnVoid('main'); + }); + + test('single required parameter', () { + method.addParameter(new ParameterBuilder('name', type: typeString)); + expect( + method, + equalsSource( + r''' + void main(String name) {} + ''', + ), + ); + }); + + test('two required parameters', () { + method + ..addParameter(new ParameterBuilder('a', type: typeInt)) + ..addParameter(new ParameterBuilder('b', type: typeInt)); + expect( + method, + equalsSource( + r''' + void main(int a, int b) {} + ''', + ), + ); + }); + + test('one optional parameter', () { + method.addParameter(new ParameterBuilder.optional( + 'name', + type: typeString, + )); + expect( + method, + equalsSource( + r''' + void main([String name]) {} + ''', + ), + ); + }); + + test('one optional parameter with a default value', () { + method.addParameter(new ParameterBuilder.optional( + 'enabled', + type: typeBool, + defaultTo: literalTrue, + )); + expect( + method, + equalsSource( + r''' + void main([bool enabled = true]) {} + ''', + ), + ); + }); + + test('one optional named parameter with a default value', () { + method.addParameter(new ParameterBuilder.named( + 'enabled', + type: typeBool, + defaultTo: literalTrue, + )); + expect( + method, + equalsSource( + r''' + void main({bool enabled: true}) {} + ''', + ), + ); + }); + + test('one optional named parameter with an annotation', () { + method.addParameter(new ParameterBuilder.named( + 'enabled', + type: typeBool, + defaultTo: literalTrue, + )..addAnnotation(atDeprecated())); + expect( + method, + equalsSource( + r''' + void main({@deprecated bool enabled: true}) {} + ''', + ), + ); + }); + }); + + group('invoking method', () { + MethodBuilder method; + + setUp(() { + method = new MethodBuilder(name: 'forward', returns: typeInt); + }); + + test('should call another method with one argument', () { + method.setExpression(new ExpressionBuilder.invoke( + 'forwardImpl', + positional: [const LiteralInt(666)], + )); + expect( + method, + equalsSource(r''' + int forward() => forwardImpl(666); + '''), + ); + }); + + test('should call another method with two arguments', () { + method.setExpression(new ExpressionBuilder.invoke( + 'sum', + positional: [const LiteralInt(1), const LiteralInt(2)], + )); + expect( + method, + equalsSource(r''' + int forward() => sum(1, 2); + '''), + ); + }); + + test('should call another method with a named arguments', () { + method.setExpression(new ExpressionBuilder.invoke( + 'forwardImpl', + named: {'value': const LiteralInt(666)}, + )); + expect( + method, + equalsSource(r''' + int forward() => forwardImpl(value: 666); + '''), + ); + }); + + test('should call another method with many arguments', () { + method.setExpression(new ExpressionBuilder.invoke( + 'forwardImpl', + positional: const [const LiteralInt(3), const LiteralInt(4)], + named: {'a': const LiteralInt(1), 'b': const LiteralInt(2)}, + )); + expect( + method, + equalsSource(r''' + int forward() => forwardImpl(3, 4, a: 1, b: 2); + '''), + ); + }); + }); + }); +} diff --git a/pkgs/code_builder/test/integration_test.dart b/pkgs/code_builder/test/integration_test.dart new file mode 100644 index 000000000..2d5b9a70f --- /dev/null +++ b/pkgs/code_builder/test/integration_test.dart @@ -0,0 +1,58 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing/equals_source.dart'; +import 'package:test/test.dart'; + +// Closely mirrors the API you would need to do dependency injection :) +void main() { + test('Emits a complex generated file', () { + var clazz = new ClassBuilder(r'Injector', implement: ['App']) + ..addField(new FieldBuilder.isFinal( + '_module', + type: const TypeBuilder('Module'), + )) + ..addConstructor(new ConstructorBuilder.initializeFields( + positionalArguments: ['_module'], + )) + ..addMethod( + new MethodBuilder( + name: 'getThing', + returns: const TypeBuilder('Thing'), + ) + ..addAnnotation(atOverride) + ..setExpression(new ExpressionBuilder.invoke( + 'new Thing', + positional: [ + new ExpressionBuilder.invoke('_module.getDep1'), + new ExpressionBuilder.invoke('_module.getDep2'), + ], + )), + ); + var lib = new FileBuilder() + ..addDirective( + new ImportBuilder('app.dart'), + ) + ..addClass(clazz); + expect( + lib, + equalsSource( + r''' + import 'app.dart'; + + class Injector implements App { + final Module _module; + + Injector(this._module); + + @override + Thing getThing() => new Thing(_module.getDep1(), _module.getDep2()); + } + ''', + ), + ); + }); +} diff --git a/pkgs/code_builder/tool/travis.sh b/pkgs/code_builder/tool/travis.sh new file mode 100755 index 000000000..cab493d2b --- /dev/null +++ b/pkgs/code_builder/tool/travis.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# 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. + +# Fast fail the script on failures. +set -e + +# Verify that the libraries are error free. +dartanalyzer --fatal-warnings \ + lib/code_builder.dart \ + lib/dart/core.dart \ + lib/testing/equals_source.dart + +# Run the tests. +pub run test + +# Install dart_coveralls; gather and send coverage data. +if [ "$COVERALLS_TOKEN" ] && [ "$TRAVIS_DART_VERSION" = "stable" ]; then + dart tool/create_test_all.dart + pub global activate dart_coveralls + pub global run dart_coveralls report \ + --retry 2 \ + --exclude-test-files \ + tool/test_all.dart + rm tool/test_all.dart +fi From ca138b345d2850d7d23932902b9ae1efa99ba605 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 13 Sep 2016 10:34:41 -0700 Subject: [PATCH 003/271] Support analyzer 0.29.0-alpha.0 --- pkgs/code_builder/lib/src/pretty_printer.dart | 34 +++++++++---------- pkgs/code_builder/pubspec.yaml | 12 +++++-- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/pkgs/code_builder/lib/src/pretty_printer.dart b/pkgs/code_builder/lib/src/pretty_printer.dart index ce8c148f8..31bbc16ae 100644 --- a/pkgs/code_builder/lib/src/pretty_printer.dart +++ b/pkgs/code_builder/lib/src/pretty_printer.dart @@ -11,37 +11,35 @@ part of code_builder; /// This is the _recommended_ output (but not required) when comparing ASTs /// to expected golden files/text blobs. String prettyToSource(AstNode astNode) { - var writer = new PrintStringWriter(); - var visitor = new _PrettyToSourceVisitor(writer); + var buffer = new StringBuffer(); + var visitor = new _PrettyToSourceVisitor(buffer); astNode.accept(visitor); - return dartfmt(writer.toString()); + return dartfmt(buffer.toString()); } // TODO(matanl): Remove copied-pasted methods when API becomes available. // https://github.com/dart-lang/sdk/issues/27169 class _PrettyToSourceVisitor extends ToSourceVisitor { - // Removed in a new version of the analyzer, but due to dartfmt it's not - // possible to refer to the newest analyzer and use dartfmt. // https://github.com/dart-lang/sdk/issues/27301 - final PrintStringWriter _writer; + final StringBuffer _buffer; - _PrettyToSourceVisitor(PrintStringWriter writer) - : _writer = writer, - super(writer); + _PrettyToSourceVisitor(StringBuffer buffer) + : _buffer = buffer, + super(buffer); @override Object visitClassDeclaration(ClassDeclaration node) { _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); _visitTokenWithSuffix(node.abstractKeyword, " "); - _writer.print("class "); + _buffer.write("class "); _visitNode(node.name); _visitNode(node.typeParameters); _visitNodeWithPrefix(" ", node.extendsClause); _visitNodeWithPrefix(" ", node.withClause); _visitNodeWithPrefix(" ", node.implementsClause); - _writer.print(" {"); + _buffer.write(" {"); _visitNodeListWithSeparator(node.members, "\n\n"); - _writer.print("}"); + _buffer.write("}"); return null; } @@ -58,7 +56,7 @@ class _PrettyToSourceVisitor extends ToSourceVisitor { int size = nodes.length; for (int i = 0; i < size; i++) { if (i > 0) { - _writer.print(separator); + _buffer.write(separator); } nodes[i].accept(this); } @@ -74,11 +72,11 @@ class _PrettyToSourceVisitor extends ToSourceVisitor { if (size > 0) { for (int i = 0; i < size; i++) { if (i > 0) { - _writer.print(separator); + _buffer.write(separator); } nodes[i].accept(this); } - _writer.print(suffix); + _buffer.write(suffix); } } } @@ -87,7 +85,7 @@ class _PrettyToSourceVisitor extends ToSourceVisitor { // is non-`null`. void _visitNodeWithPrefix(String prefix, AstNode node) { if (node != null) { - _writer.print(prefix); + _buffer.write(prefix); node.accept(this); } } @@ -96,8 +94,8 @@ class _PrettyToSourceVisitor extends ToSourceVisitor { // is non-`null`. void _visitTokenWithSuffix(Token token, String suffix) { if (token != null) { - _writer.print(token.lexeme); - _writer.print(suffix); + _buffer.write(token.lexeme); + _buffer.write(suffix); } } } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 73a0602cb..98f8a6093 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 0.1.0 +version: 0.1.0-dev description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -8,10 +8,16 @@ environment: sdk: '>=1.9.1 <2.0.0' dependencies: - analyzer: ">=0.27.1 <0.29.0" - dart_style: ^0.2.9+1 + analyzer: + dart_style: matcher: ^0.12.0+2 meta: ^1.0.2 dev_dependencies: test: ^0.12.0 + +dependency_overrides: + # As of 9-13-2016, this is the internal SHA. This means we can't publish to + # pub, but at least can develop with code that will work out of the box on + # the internal repo. + analyzer: 0.29.0-alpha.0 From 16aaba88580d5c4bd0d14e9f0cb249305ecd97d6 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 13 Sep 2016 20:56:18 -0700 Subject: [PATCH 004/271] Add Expression#toStatement, and tests. (dart-lang/code_builder#4) * Add Expression#toStatement, and tests. * Add example, fix doc comment. --- .../lib/src/expression_builder.dart | 191 ++++++++++++------ pkgs/code_builder/lib/src/method_builder.dart | 111 +++++----- .../lib/src/statement_builder.dart | 14 +- .../test/builders/method_builder_test.dart | 33 +++ 4 files changed, 229 insertions(+), 120 deletions(-) diff --git a/pkgs/code_builder/lib/src/expression_builder.dart b/pkgs/code_builder/lib/src/expression_builder.dart index 8147978c2..365dc6559 100644 --- a/pkgs/code_builder/lib/src/expression_builder.dart +++ b/pkgs/code_builder/lib/src/expression_builder.dart @@ -5,11 +5,24 @@ part of code_builder; // Shared functionality between ExpressionBuilder and _LiteralExpression. +/// Represents an expression value of `false`. +const literalFalse = const LiteralBool(false); + +/// Represents an expression value of `null`. +const literalNull = const _LiteralNull(); + +/// Represents an expression value of `true`. +const literalTrue = const LiteralBool(true); + +// Returns wrapped as a [ExpressionFunctionBody] AST. final Token _closeP = new Token(TokenType.CLOSE_PAREN, 0); + +// Returns wrapped as a [FunctionExpression] AST. final Token _openP = new Token(TokenType.OPEN_PAREN, 0); + final Token _semicolon = new Token(TokenType.SEMICOLON, 0); -// Returns wrapped as a [ExpressionFunctionBody] AST. +// TODO(matanl): Make this part of the public API. See annotation_builder.dart. ExpressionFunctionBody _asFunctionBody(CodeBuilder expression) { return new ExpressionFunctionBody( null, @@ -19,7 +32,6 @@ ExpressionFunctionBody _asFunctionBody(CodeBuilder expression) { ); } -// Returns wrapped as a [FunctionExpression] AST. FunctionExpression _asFunctionExpression(CodeBuilder expression) { return new FunctionExpression( null, @@ -34,6 +46,20 @@ FunctionExpression _asFunctionExpression(CodeBuilder expression) { ); } +ExpressionBuilder _invokeSelfImpl( + ExpressionBuilder self, + String name, { + Iterable> positional: const [], + Map> named: const {}, +}) { + return new _InvokeExpression.target( + name, + self, + positional, + named, + ); +} + /// Builds an [Expression] AST. /// /// For simple literal expressions see: @@ -59,18 +85,77 @@ abstract class ExpressionBuilder implements CodeBuilder { const ExpressionBuilder._(); + /// Return a new [ExpressionBuilder] invoking the result of this expression. + ExpressionBuilder invokeSelf( + String name, { + Iterable> positional: const [], + Map> named: const {}, + }); // TODO(matanl): Rename to invoke when factory is removed. + /// Returns wrapped as a [ExpressionFunctionBody] AST. ExpressionFunctionBody toFunctionBody() => _asFunctionBody(this); /// Returns wrapped as a [FunctionExpression] AST. FunctionExpression toFunctionExpression() => _asFunctionExpression(this); + + /// Converts to a [StatementBuilder]. + /// + /// __Example use__: + /// literalNull.toStatement(); // ==> null; + StatementBuilder toStatement(); +} + +/// Creates a new literal `bool` value. +class LiteralBool extends _LiteralExpression { + static final BooleanLiteral _true = + new BooleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); + static final BooleanLiteral _false = + new BooleanLiteral(new KeywordToken(Keyword.FALSE, 0), false); + + final bool _value; + + /// Returns the passed value as a [BooleanLiteral]. + const LiteralBool(this._value); + + @override + BooleanLiteral toAst() => _value ? _true : _false; +} + +/// Represents an expression value of a literal number. +class LiteralInt extends _LiteralExpression { + final int _value; + + /// Returns the passed value as a [IntegerLiteral]. + const LiteralInt(this._value); + + @override + IntegerLiteral toAst() => + new IntegerLiteral(new StringToken(TokenType.INT, '$_value', 0), _value); +} + +/// Represents an expression value of a literal `'string'`. +class LiteralString extends _LiteralExpression { + final String _value; + + /// Returns the passed value as a [StringLiteral]. + const LiteralString(this._value); + + @override + StringLiteral toAst() => new SimpleStringLiteral( + new StringToken( + TokenType.STRING, + "'$_value'", + 0, + ), + _value, + ); } -// TODO(matanl): Make this part of the public API. See annotation_builder.dart. class _InvokeExpression extends ExpressionBuilder implements CodeBuilder { static final Token _colon = new Token(TokenType.COLON, 0); + final ExpressionBuilder _target; final String _name; final List> _positionalArguments; final Map> _namedArguments; @@ -80,8 +165,35 @@ class _InvokeExpression extends ExpressionBuilder this._positionalArguments, this._namedArguments, ) + : _target = null, + super._(); + + const _InvokeExpression.target( + this._name, this._target, this._positionalArguments, this._namedArguments) : super._(); + @override + ExpressionBuilder invokeSelf( + String name, { + Iterable> positional: const [], + Map> named: const {}, + }) => + _invokeSelfImpl(this, name, positional: positional, named: named); + + @override + InvocationExpression toAst() { + return new MethodInvocation( + _target?.toAst(), + _target != null ? new Token(TokenType.PERIOD, 0) : null, + _stringId(_name), + null, + _getArgumentList(), + ); + } + + @override + StatementBuilder toStatement() => new StatementBuilder.fromExpression(this); + ArgumentList _getArgumentList() { return new ArgumentList( new Token(TokenType.OPEN_CURLY_BRACKET, 0), @@ -97,55 +209,30 @@ class _InvokeExpression extends ExpressionBuilder new Token(TokenType.CLOSE_CURLY_BRACKET, 0), ); } - - @override - InvocationExpression toAst() { - return new MethodInvocation( - null, - null, - _stringId(_name), - null, - _getArgumentList(), - ); - } } abstract class _LiteralExpression implements ExpressionBuilder, CodeBuilder { const _LiteralExpression(); + @override + ExpressionBuilder invokeSelf( + String name, { + Iterable> positional: const [], + Map> named: const {}, + }) => + _invokeSelfImpl(this, name, positional: positional, named: named); + @override ExpressionFunctionBody toFunctionBody() => _asFunctionBody(this); @override FunctionExpression toFunctionExpression() => _asFunctionExpression(this); -} - -/// Represents an expression value of `true`. -const literalTrue = const LiteralBool(true); - -/// Represents an expression value of `false`. -const literalFalse = const LiteralBool(false); - -/// Creates a new literal `bool` value. -class LiteralBool extends _LiteralExpression { - static final BooleanLiteral _true = - new BooleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); - static final BooleanLiteral _false = - new BooleanLiteral(new KeywordToken(Keyword.FALSE, 0), false); - - final bool _value; - - /// Returns the passed value as a [BooleanLiteral]. - const LiteralBool(this._value); @override - BooleanLiteral toAst() => _value ? _true : _false; + StatementBuilder toStatement() => new StatementBuilder.fromExpression(this); } -/// Represents an expression value of `null`. -const literalNull = const _LiteralNull(); - class _LiteralNull extends _LiteralExpression { static NullLiteral _null = new NullLiteral(new KeywordToken(Keyword.NULL, 0)); @@ -154,33 +241,3 @@ class _LiteralNull extends _LiteralExpression { @override NullLiteral toAst() => _null; } - -/// Represents an expression value of a literal number. -class LiteralInt extends _LiteralExpression { - final int _value; - - /// Returns the passed value as a [IntegerLiteral]. - const LiteralInt(this._value); - - @override - IntegerLiteral toAst() => - new IntegerLiteral(new StringToken(TokenType.INT, '$_value', 0), _value); -} - -/// Represents an expression value of a literal `'string'`. -class LiteralString extends _LiteralExpression { - final String _value; - - /// Returns the passed value as a [StringLiteral]. - const LiteralString(this._value); - - @override - StringLiteral toAst() => new SimpleStringLiteral( - new StringToken( - TokenType.STRING, - "'$_value'", - 0, - ), - _value, - ); -} diff --git a/pkgs/code_builder/lib/src/method_builder.dart b/pkgs/code_builder/lib/src/method_builder.dart index 6a96e0c07..a501df704 100644 --- a/pkgs/code_builder/lib/src/method_builder.dart +++ b/pkgs/code_builder/lib/src/method_builder.dart @@ -55,52 +55,6 @@ class MethodBuilder implements CodeBuilder { _parameters.add(parameter); } - static FunctionBody _emptyBlockBody() => new BlockFunctionBody( - null, - null, - new Block( - new Token(TokenType.OPEN_CURLY_BRACKET, 0), - null, - new Token(TokenType.CLOSE_CURLY_BRACKET, 0), - ), - ); - - static FunctionDeclaration _emptyFunction() => new FunctionDeclaration( - null, - null, - null, - null, - null, - null, - new FunctionExpression( - null, - _emptyParameters(), - _emptyBlockBody(), - ), - ); - - static MethodDeclaration _emptyMethod() => new MethodDeclaration( - null, - null, - null, - null, - null, - null, - null, - null, - null, - _emptyParameters(), - null, - ); - - static FormalParameterList _emptyParameters() => new FormalParameterList( - new Token(TokenType.OPEN_PAREN, 0), - [], - null, - null, - new Token(TokenType.CLOSE_PAREN, 0), - ); - /// Lazily adds [statement]. /// /// When the method is emitted as an AST, [StatementBuilder.toAst] is used. @@ -132,11 +86,16 @@ class MethodBuilder implements CodeBuilder { ..returnType = _returnType?.toAst(); if (_returnExpression != null) { functionAst.functionExpression = _returnExpression.toFunctionExpression(); + } else { + functionAst.functionExpression = new FunctionExpression( + null, + _emptyParameters(), + _blockBody(_statements.map/**/((s) => s.toAst())), + ); } if (_parameters.isNotEmpty) { - functionAst.functionExpression.parameters = _emptyParameters() - ..parameters - .addAll(_parameters.map/**/((p) => p.toAst())); + functionAst.functionExpression.parameters.parameters + .addAll(_parameters.map/**/((p) => p.toAst())); } return functionAst; } @@ -154,12 +113,13 @@ class MethodBuilder implements CodeBuilder { if (static) { methodAst.modifierKeyword = _static; if (methodBody == null) { - methodBody = _emptyBlockBody(); + methodBody = _blockBody(); } } if (methodBody == null) { - methodBody = - canBeAbstract ? new EmptyFunctionBody(_semicolon) : _emptyBlockBody(); + methodBody = canBeAbstract + ? new EmptyFunctionBody(_semicolon) + : _blockBody(_statements.map/**/((s) => s.toAst())); } if (_parameters.isNotEmpty) { methodAst.parameters.parameters @@ -171,4 +131,51 @@ class MethodBuilder implements CodeBuilder { @override String toString() => 'MethodBuilder ${toAst().toSource()}'; + + static FunctionBody _blockBody([Iterable statements]) => + new BlockFunctionBody( + null, + null, + new Block( + new Token(TokenType.OPEN_CURLY_BRACKET, 0), + statements?.toList(), + new Token(TokenType.CLOSE_CURLY_BRACKET, 0), + ), + ); + + static FunctionDeclaration _emptyFunction() => new FunctionDeclaration( + null, + null, + null, + null, + null, + null, + new FunctionExpression( + null, + _emptyParameters(), + _blockBody(), + ), + ); + + static MethodDeclaration _emptyMethod() => new MethodDeclaration( + null, + null, + null, + null, + null, + null, + null, + null, + null, + _emptyParameters(), + null, + ); + + static FormalParameterList _emptyParameters() => new FormalParameterList( + new Token(TokenType.OPEN_PAREN, 0), + [], + null, + null, + new Token(TokenType.CLOSE_PAREN, 0), + ); } diff --git a/pkgs/code_builder/lib/src/statement_builder.dart b/pkgs/code_builder/lib/src/statement_builder.dart index fd5a794a1..e7d0db959 100644 --- a/pkgs/code_builder/lib/src/statement_builder.dart +++ b/pkgs/code_builder/lib/src/statement_builder.dart @@ -6,5 +6,17 @@ part of code_builder; /// Builds a [Statement] AST. abstract class StatementBuilder implements CodeBuilder { - // TODO(matanl): Implement (not required immediately as we have expressions). + /// Returns a new [StatementBuilder] from the result of [ExpressionBuilder]. + factory StatementBuilder.fromExpression(ExpressionBuilder builder) { + return new _ExpressionStatementBuilder(new ExpressionStatement( + builder.toAst(), + _semicolon, + )); + } +} + +class _ExpressionStatementBuilder + extends _AbstractCodeBuilder + implements StatementBuilder { + _ExpressionStatementBuilder(ExpressionStatement astNode) : super._(astNode); } diff --git a/pkgs/code_builder/test/builders/method_builder_test.dart b/pkgs/code_builder/test/builders/method_builder_test.dart index bcca43668..28bb930a6 100644 --- a/pkgs/code_builder/test/builders/method_builder_test.dart +++ b/pkgs/code_builder/test/builders/method_builder_test.dart @@ -83,6 +83,39 @@ void main() { ); }); + group('with statements', () { + test('should work with an expression', () { + expect( + new MethodBuilder.returnVoid('main') + ..addStatement(const LiteralString('Hello World').toStatement()), + equalsSource(r''' + void main() { + 'Hello World'; + } + '''), + ); + }); + + test('should work invoking an expression', () { + expect( + new MethodBuilder.returnVoid('main') + ..addStatement( + new ExpressionBuilder.invoke('print', positional: [ + const LiteralString('Hello World').invokeSelf( + 'substring', + positional: [const LiteralInt(1)], + ) + ]).toStatement(), + ), + equalsSource(r''' + void main() { + print('Hello World'.substring(1)); + } + '''), + ); + }); + }); + group('with parameters:', () { MethodBuilder method; From 22390415d530ee174999f8235b077a66ec31bf25 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 13 Sep 2016 20:56:56 -0700 Subject: [PATCH 005/271] Split FileBuilder into LibraryBuilder and PartBuilder (dart-lang/code_builder#3) * Remove unused dependency. * Split FileBuilder into Library/PartBuilder. * Move FileBuilder#addDirectove to LibraryBuilder. --- pkgs/code_builder/lib/code_builder.dart | 1 - pkgs/code_builder/lib/src/file_builder.dart | 137 +++++++++--------- pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/file_builder_test.dart | 6 +- pkgs/code_builder/test/integration_test.dart | 4 +- 5 files changed, 71 insertions(+), 79 deletions(-) diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index bcde81ff2..b3766031c 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -31,7 +31,6 @@ library code_builder; import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/src/dart/ast/token.dart'; -import 'package:analyzer/src/generated/java_core.dart'; import 'package:dart_style/dart_style.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/lib/src/file_builder.dart b/pkgs/code_builder/lib/src/file_builder.dart index bb2e99b50..0d3bd822b 100644 --- a/pkgs/code_builder/lib/src/file_builder.dart +++ b/pkgs/code_builder/lib/src/file_builder.dart @@ -4,73 +4,74 @@ part of code_builder; +CompilationUnit _emptyCompilationUnit() => new CompilationUnit( + null, + null, + null, + null, + null, + ); + /// Builds files of Dart source code. /// -/// Files may either be a standalone library or `part of` another library. -class FileBuilder extends _AbstractCodeBuilder { - static Token _library = new KeywordToken(Keyword.LIBRARY, 0); - static Token _part = new KeywordToken(Keyword.PART, 0); - static Token _of = new StringToken(TokenType.KEYWORD, 'of', 0); +/// See [LibraryBuilder] and [PartBuilder] for concrete implementations. +abstract class FileBuilder extends _AbstractCodeBuilder { + FileBuilder._(CompilationUnit astNode) : super._(astNode); + + /// Adds [declaration]'s resulting AST to the source. + void addDeclaration(CodeBuilder declaration) { + _astNode.declarations.add(declaration.toAst()); + } +} + +/// Builds a standalone Dart library [CompilationUnit] AST. +class LibraryBuilder extends FileBuilder { + static final Token _library = new KeywordToken(Keyword.LIBRARY, 0); /// Create a new standalone Dart library, optionally with a [name]. - factory FileBuilder([String name]) { + factory LibraryBuilder([String name]) { var astNode = _emptyCompilationUnit(); if (name != null) { astNode.directives.add(new LibraryDirective( - null, - null, - _library, - new LibraryIdentifier([_stringId(name)]), - null, - )); + null, + null, + _library, + new LibraryIdentifier([_stringId(name)]), + null,)); } - return new FileBuilder._(astNode); + return new LibraryBuilder._(astNode); } - /// Create a new `part of` the dart library with [name]. - factory FileBuilder.partOf(String name) { - var astNode = _emptyCompilationUnit(); - astNode.directives.add(new PartOfDirective( - null, - null, - _part, - _of, - new LibraryIdentifier([_stringId(name)]), - null, - )); - return new FileBuilder._(astNode); - } - - FileBuilder._(CompilationUnit astNode) : super._(astNode); + LibraryBuilder._(CompilationUnit astNode) : super._(astNode); - /// Add a copy of [clazz] as a declaration in this file. - void addClass(ClassBuilder clazz) { - _astNode.declarations.add(clazz.toAst()); - } - - /// Adds an `import` or `export` [directive]. + /// Adds [directive]'s resulting AST to the source. void addDirective(CodeBuilder directive) { - if (isPartOf) { - throw const DartPartFileException._(); - } _astNode.directives.add(directive.toAst()); } +} - static CompilationUnit _emptyCompilationUnit() => new CompilationUnit( - null, - null, +/// Builds a `part of` [CompilationUnit] AST for an existing Dart library. +class PartBuilder extends FileBuilder { + static final Token _part = new KeywordToken(Keyword.PART, 0); + static final Token _of = new StringToken(TokenType.KEYWORD, 'of', 0); + + /// Create a new `part of` source file. + factory PartBuilder(String name) { + var astNode = _emptyCompilationUnit(); + astNode.directives.add(new PartOfDirective( null, null, + _part, + _of, + new LibraryIdentifier([_stringId(name)]), null, - ); - - static bool _isPartOf(Directive d) => d is PartOfDirective; + )); + return new PartBuilder._(astNode); + } - /// Whether the file is `part of` another. - bool get isPartOf => _astNode.directives.contains(_isPartOf); + PartBuilder._(CompilationUnit astNode) : super._(astNode); } - -/// An `export` directive in a [FileBuilder]. +/// An `export` directive in a [LibraryBuilder]. class ExportBuilder extends _AbstractCodeBuilder { /// Create a new `export` directive exporting [uri]. factory ExportBuilder(String uri) { @@ -81,13 +82,13 @@ class ExportBuilder extends _AbstractCodeBuilder { ExportBuilder._(ExportDirective astNode) : super._(astNode); static ExportDirective _createExportDirective() => new ExportDirective( - null, - null, - null, - null, - null, - null, - null, + null, + null, + null, + null, + null, + null, + null, ); } @@ -111,23 +112,15 @@ class ImportBuilder extends _AbstractCodeBuilder { ImportBuilder._(ImportDirective astNode) : super._(astNode); static ImportDirective _createImportDirective() => new ImportDirective( - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, ); } - -/// Thrown when an invalid operation is attempted on a [FileBuilder] instance. -class DartPartFileException implements Exception { - const DartPartFileException._(); - - @override - String toString() => 'Not a valid operation for a `part of` file.'; -} diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 98f8a6093..77cd407aa 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 0.1.0-dev +version: 0.1.0-dev+1 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/file_builder_test.dart b/pkgs/code_builder/test/builders/file_builder_test.dart index 14fae003b..98e21360f 100644 --- a/pkgs/code_builder/test/builders/file_builder_test.dart +++ b/pkgs/code_builder/test/builders/file_builder_test.dart @@ -8,17 +8,17 @@ import 'package:test/test.dart'; void main() { test('should emit a blank file', () { - expect(new FileBuilder(), equalsSource('')); + expect(new LibraryBuilder(), equalsSource('')); }); test('should emit a file with a library directive', () { expect( - new FileBuilder('code_builder'), equalsSource('library code_builder;')); + new LibraryBuilder('code_builder'), equalsSource('library code_builder;')); }); test('should emit a file with a part of directive', () { expect( - new FileBuilder.partOf('code_builder'), + new PartBuilder('code_builder'), equalsSource('part of code_builder;'), ); }); diff --git a/pkgs/code_builder/test/integration_test.dart b/pkgs/code_builder/test/integration_test.dart index 2d5b9a70f..8510c7b84 100644 --- a/pkgs/code_builder/test/integration_test.dart +++ b/pkgs/code_builder/test/integration_test.dart @@ -32,11 +32,11 @@ void main() { ], )), ); - var lib = new FileBuilder() + var lib = new LibraryBuilder() ..addDirective( new ImportBuilder('app.dart'), ) - ..addClass(clazz); + ..addDeclaration(clazz); expect( lib, equalsSource( From 0906fbc2ddadc584785da60e33752aed2c7b8ace Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 14 Sep 2016 23:44:10 -0700 Subject: [PATCH 006/271] Add travis, coveralls. (dart-lang/code_builder#7) --- pkgs/code_builder/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 36d7d2779..d9659906d 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -1,5 +1,8 @@ # 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) + Code builder is a fluent Dart API for generating valid Dart source code. Generally speaking, code generation usually is done through a series of From 960b90784a141f2bf9e23763b9ace9af117cd119 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 15 Sep 2016 11:56:49 -0700 Subject: [PATCH 007/271] Move builders to src/builders --- pkgs/code_builder/lib/code_builder.dart | 22 ++++++++++--------- .../{ => builders}/annotation_builder.dart | 0 .../lib/src/{ => builders}/class_builder.dart | 0 .../{ => builders}/constructor_builder.dart | 0 .../{ => builders}/expression_builder.dart | 0 .../lib/src/{ => builders}/field_builder.dart | 0 .../lib/src/{ => builders}/file_builder.dart | 7 ++++++ .../src/{ => builders}/method_builder.dart | 0 .../src/{ => builders}/parameter_builder.dart | 0 .../src/{ => builders}/statement_builder.dart | 0 .../lib/src/{ => builders}/type_builder.dart | 0 11 files changed, 19 insertions(+), 10 deletions(-) rename pkgs/code_builder/lib/src/{ => builders}/annotation_builder.dart (100%) rename pkgs/code_builder/lib/src/{ => builders}/class_builder.dart (100%) rename pkgs/code_builder/lib/src/{ => builders}/constructor_builder.dart (100%) rename pkgs/code_builder/lib/src/{ => builders}/expression_builder.dart (100%) rename pkgs/code_builder/lib/src/{ => builders}/field_builder.dart (100%) rename pkgs/code_builder/lib/src/{ => builders}/file_builder.dart (90%) rename pkgs/code_builder/lib/src/{ => builders}/method_builder.dart (100%) rename pkgs/code_builder/lib/src/{ => builders}/parameter_builder.dart (100%) rename pkgs/code_builder/lib/src/{ => builders}/statement_builder.dart (100%) rename pkgs/code_builder/lib/src/{ => builders}/type_builder.dart (100%) diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index b3766031c..784b48d40 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -34,17 +34,19 @@ import 'package:analyzer/src/dart/ast/token.dart'; import 'package:dart_style/dart_style.dart'; import 'package:meta/meta.dart'; -part 'src/annotation_builder.dart'; -part 'src/class_builder.dart'; -part 'src/constructor_builder.dart'; -part 'src/expression_builder.dart'; -part 'src/field_builder.dart'; -part 'src/file_builder.dart'; -part 'src/method_builder.dart'; -part 'src/parameter_builder.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/statement_builder.dart'; -part 'src/type_builder.dart'; +part 'src/scope_controller.dart'; /// Base class for building and emitting a Dart language [AstNode]. abstract class CodeBuilder { diff --git a/pkgs/code_builder/lib/src/annotation_builder.dart b/pkgs/code_builder/lib/src/builders/annotation_builder.dart similarity index 100% rename from pkgs/code_builder/lib/src/annotation_builder.dart rename to pkgs/code_builder/lib/src/builders/annotation_builder.dart diff --git a/pkgs/code_builder/lib/src/class_builder.dart b/pkgs/code_builder/lib/src/builders/class_builder.dart similarity index 100% rename from pkgs/code_builder/lib/src/class_builder.dart rename to pkgs/code_builder/lib/src/builders/class_builder.dart diff --git a/pkgs/code_builder/lib/src/constructor_builder.dart b/pkgs/code_builder/lib/src/builders/constructor_builder.dart similarity index 100% rename from pkgs/code_builder/lib/src/constructor_builder.dart rename to pkgs/code_builder/lib/src/builders/constructor_builder.dart diff --git a/pkgs/code_builder/lib/src/expression_builder.dart b/pkgs/code_builder/lib/src/builders/expression_builder.dart similarity index 100% rename from pkgs/code_builder/lib/src/expression_builder.dart rename to pkgs/code_builder/lib/src/builders/expression_builder.dart diff --git a/pkgs/code_builder/lib/src/field_builder.dart b/pkgs/code_builder/lib/src/builders/field_builder.dart similarity index 100% rename from pkgs/code_builder/lib/src/field_builder.dart rename to pkgs/code_builder/lib/src/builders/field_builder.dart diff --git a/pkgs/code_builder/lib/src/file_builder.dart b/pkgs/code_builder/lib/src/builders/file_builder.dart similarity index 90% rename from pkgs/code_builder/lib/src/file_builder.dart rename to pkgs/code_builder/lib/src/builders/file_builder.dart index 0d3bd822b..733f71601 100644 --- a/pkgs/code_builder/lib/src/file_builder.dart +++ b/pkgs/code_builder/lib/src/builders/file_builder.dart @@ -42,6 +42,13 @@ class LibraryBuilder extends FileBuilder { return new LibraryBuilder._(astNode); } + /// Create a new standalone Dart library, optionally with a [name]. + /// + /// As references are added in the library that implements [RequiresImport] + /// they are re-written to avoid collisions and the imports are automatically + /// included at the top with optional prefixes. + factory LibraryBuilder.autoScope({String name}) => new LibraryBuilder(name); + LibraryBuilder._(CompilationUnit astNode) : super._(astNode); /// Adds [directive]'s resulting AST to the source. diff --git a/pkgs/code_builder/lib/src/method_builder.dart b/pkgs/code_builder/lib/src/builders/method_builder.dart similarity index 100% rename from pkgs/code_builder/lib/src/method_builder.dart rename to pkgs/code_builder/lib/src/builders/method_builder.dart diff --git a/pkgs/code_builder/lib/src/parameter_builder.dart b/pkgs/code_builder/lib/src/builders/parameter_builder.dart similarity index 100% rename from pkgs/code_builder/lib/src/parameter_builder.dart rename to pkgs/code_builder/lib/src/builders/parameter_builder.dart diff --git a/pkgs/code_builder/lib/src/statement_builder.dart b/pkgs/code_builder/lib/src/builders/statement_builder.dart similarity index 100% rename from pkgs/code_builder/lib/src/statement_builder.dart rename to pkgs/code_builder/lib/src/builders/statement_builder.dart diff --git a/pkgs/code_builder/lib/src/type_builder.dart b/pkgs/code_builder/lib/src/builders/type_builder.dart similarity index 100% rename from pkgs/code_builder/lib/src/type_builder.dart rename to pkgs/code_builder/lib/src/builders/type_builder.dart From 7d3e5046dff2e5b798a445efb099b8a5b6576063 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 15 Sep 2016 13:34:01 -0700 Subject: [PATCH 008/271] Remove import from bad merge. --- pkgs/code_builder/lib/code_builder.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 784b48d40..23e4d1201 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -46,7 +46,6 @@ part 'src/builders/statement_builder.dart'; part 'src/builders/type_builder.dart'; part 'src/pretty_printer.dart'; -part 'src/scope_controller.dart'; /// Base class for building and emitting a Dart language [AstNode]. abstract class CodeBuilder { From baae61356dc2cb3309b7f0a8ac8fc51516df913c Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 15 Sep 2016 17:15:45 -0700 Subject: [PATCH 009/271] Add a simple identifier Scope class and a test. (dart-lang/code_builder#9) * Add a simple identifier Scope class and a test. * Address comments. --- pkgs/code_builder/lib/code_builder.dart | 1 + pkgs/code_builder/lib/src/scope.dart | 65 +++++++++++++++++++++++++ pkgs/code_builder/test/scope_test.dart | 55 +++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 pkgs/code_builder/lib/src/scope.dart create mode 100644 pkgs/code_builder/test/scope_test.dart diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 23e4d1201..a5b4265ed 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -46,6 +46,7 @@ part 'src/builders/statement_builder.dart'; part 'src/builders/type_builder.dart'; part 'src/pretty_printer.dart'; +part 'src/scope.dart'; /// Base class for building and emitting a Dart language [AstNode]. abstract class CodeBuilder { diff --git a/pkgs/code_builder/lib/src/scope.dart b/pkgs/code_builder/lib/src/scope.dart new file mode 100644 index 000000000..92ead6c15 --- /dev/null +++ b/pkgs/code_builder/lib/src/scope.dart @@ -0,0 +1,65 @@ +part of code_builder; + +/// Determines an [Identifier] deppending on where it appears. +/// +/// __Example use__: +/// void useContext(Scope scope) { +/// // Prints Identifier "i1.Foo" +/// print(scope.getIdentifier('Foo', 'package:foo/foo.dart'); +/// +/// // Prints Identifier "i1.Bar" +/// print(scope.getIdentifier('Bar', 'package:foo/foo.dart'); +/// +/// // Prints Identifier "i2.Baz" +/// print(scope.getIdentifier('Baz', 'package:bar/bar.dart'); +/// } +abstract class Scope { + /// Create a default scope context. + /// + /// Actual implementation is _not_ guaranteed, only that all import prefixes + /// will be unique in a given scope (actual implementation may be naive). + factory Scope() = _IncrementingScope; + + /// Create a context that does _not_ apply any scoping. + factory Scope.identity() = _IdentityScope; + + /// Given a [symbol] and its known [importUri], return an [Identifier]. + Identifier getIdentifier(String symbol, String importUri); + + /// Returns a list of all imports needed to resolve identifiers. + Iterable getImports(); +} + +class _IdentityScope implements Scope { + final Set _imports = new Set(); + + @override + Identifier getIdentifier(String symbol, String import) { + _imports.add(import); + return _stringId(symbol); + } + + @override + Iterable getImports() { + return _imports.map/* new ImportBuilder(i)); + } +} + +class _IncrementingScope implements Scope { + final Map _imports = {}; + + int _counter = 0; + + @override + Identifier getIdentifier(String symbol, String import) { + var newId = _imports.putIfAbsent(import, () => ++_counter); + return new PrefixedIdentifier(_stringId('_i$newId'), + new Token(TokenType.PERIOD, 0), _stringId(symbol)); + } + + @override + Iterable getImports() { + return _imports.keys.map/* new ImportBuilder(i, as: '_i${_imports[i]}')); + } +} diff --git a/pkgs/code_builder/test/scope_test.dart b/pkgs/code_builder/test/scope_test.dart new file mode 100644 index 000000000..db32ead56 --- /dev/null +++ b/pkgs/code_builder/test/scope_test.dart @@ -0,0 +1,55 @@ +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:test/test.dart'; + +void main() { + group('Identity scope', () { + Scope scope; + + setUp(() => scope = new Scope.identity()); + + test('should just output non-prefixed and de-duplicate imports', () { + var identifiers = [ + scope.getIdentifier('Foo', 'package:foo/foo.dart'), + scope.getIdentifier('Bar', 'package:foo/foo.dart'), + scope.getIdentifier('Baz', 'package:baz/baz.dart'), + ].map/**/((i) => i.toSource()); + + expect(identifiers, [ + 'Foo', + 'Bar', + 'Baz', + ],); + + expect(scope.getImports().map/**/((i) => i.toAst().toSource()), [ + r"import 'package:foo/foo.dart';", + r"import 'package:baz/baz.dart';", + ],); + }); + }); + + group('Incrementing scope', () { + Scope scope; + + setUp(() => scope = new Scope()); + + test('should out prefixed with a counter', () { + var identifiers = [ + scope.getIdentifier('Foo', 'package:foo/foo.dart'), + scope.getIdentifier('Bar', 'package:foo/foo.dart'), + scope.getIdentifier('Baz', 'package:baz/baz.dart'), + ].map/**/((i) => i.toSource()); + + expect(identifiers, [ + '_i1.Foo', + '_i1.Bar', + '_i2.Baz', + ],); + + expect(scope.getImports().map/**/((i) => i.toAst().toSource()), [ + r"import 'package:foo/foo.dart' as _i1;", + r"import 'package:baz/baz.dart' as _i2;", + ],); + }); + }); +} From 58e39e4267ed8bbb6413df75ba33643491c89f1e Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 15 Sep 2016 19:45:49 -0700 Subject: [PATCH 010/271] Add support for library scoping (dart-lang/code_builder#10) * Add a simple identifier Scope class and a test. * Address comments. * Add some support for scoping (methods, types, parameters) * Add some support to LibraryBuilder and a test. * Pubspec +1 --- pkgs/code_builder/lib/code_builder.dart | 8 +- .../lib/src/builders/annotation_builder.dart | 4 +- .../lib/src/builders/file_builder.dart | 37 ++++- .../lib/src/builders/method_builder.dart | 25 ++- .../lib/src/builders/parameter_builder.dart | 155 +++++++++++------- .../lib/src/builders/type_builder.dart | 11 +- pkgs/code_builder/lib/src/scope.dart | 19 ++- .../lib/testing/equals_source.dart | 54 +++++- pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/method_builder_test.dart | 31 ++++ pkgs/code_builder/test/integration_test.dart | 36 ++++ pkgs/code_builder/test/scope_test.dart | 24 ++- 12 files changed, 310 insertions(+), 96 deletions(-) diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index a5b4265ed..fc800e7d4 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -73,14 +73,14 @@ abstract class _AbstractCodeBuilder extends CodeBuilder { /// **NOTE**: This currently (as of 0.2.0) has no effect. It is planned that /// the [FileBuilder] will be able to act as a scope 'resolver' and subtly /// rewrite the AST tree to use prefixing if required (or requested). -abstract class RequiresImport implements CodeBuilder { - /// Imports that are required for this AST to work. - List get requiredImports; +abstract class ScopeAware implements CodeBuilder { + @override + A toAst() => toScopedAst(const Scope.identity()); /// Creates a copy-safe [AstNode] representing the current builder state. /// /// Uses [scope] to output an AST re-written to use appropriate prefixes. - A toScopedAst(FileBuilder scope) => throw new UnimplementedError(); + A toScopedAst(Scope scope) => throw new UnimplementedError(); } // Creates a defensive copy of an AST node. diff --git a/pkgs/code_builder/lib/src/builders/annotation_builder.dart b/pkgs/code_builder/lib/src/builders/annotation_builder.dart index 885bc409e..a209a4644 100644 --- a/pkgs/code_builder/lib/src/builders/annotation_builder.dart +++ b/pkgs/code_builder/lib/src/builders/annotation_builder.dart @@ -16,7 +16,7 @@ part of code_builder; /// void destroyTheWorld() { ... } /// /// To create a `@DoNotUse('Blows up')` use [AnnotationBuilder.invoke]. -abstract class AnnotationBuilder implements RequiresImport { +abstract class AnnotationBuilder implements ScopeAware { /// Create a new annotated `const` [constructor] invocation. /// /// May optionally specify an [importFrom] to auto-prefix the annotation _if_ @@ -46,7 +46,7 @@ abstract class AnnotationBuilder implements RequiresImport { [String importFrom]) = _ReferenceAnnotationBuilder; } -class _ConstructorAnnotationBuilder extends RequiresImport +class _ConstructorAnnotationBuilder extends ScopeAware implements AnnotationBuilder { final String _constructor; final ExpressionBuilder _expression; diff --git a/pkgs/code_builder/lib/src/builders/file_builder.dart b/pkgs/code_builder/lib/src/builders/file_builder.dart index 733f71601..d6fdcc76b 100644 --- a/pkgs/code_builder/lib/src/builders/file_builder.dart +++ b/pkgs/code_builder/lib/src/builders/file_builder.dart @@ -28,6 +28,8 @@ abstract class FileBuilder extends _AbstractCodeBuilder { class LibraryBuilder extends FileBuilder { static final Token _library = new KeywordToken(Keyword.LIBRARY, 0); + final Scope _scope; + /// Create a new standalone Dart library, optionally with a [name]. factory LibraryBuilder([String name]) { var astNode = _emptyCompilationUnit(); @@ -39,22 +41,49 @@ class LibraryBuilder extends FileBuilder { new LibraryIdentifier([_stringId(name)]), null,)); } - return new LibraryBuilder._(astNode); + return new LibraryBuilder._(astNode, new Scope.dedupe()); } /// Create a new standalone Dart library, optionally with a [name]. /// - /// As references are added in the library that implements [RequiresImport] + /// As references are added in the library that implements [ScopeAware] /// they are re-written to avoid collisions and the imports are automatically /// included at the top with optional prefixes. - factory LibraryBuilder.autoScope({String name}) => new LibraryBuilder(name); + factory LibraryBuilder.scope({String name, Scope scope}) { + var astNode = _emptyCompilationUnit(); + if (name != null) { + astNode.directives.add(new LibraryDirective( + null, + null, + _library, + new LibraryIdentifier([_stringId(name)]), + null,)); + } + return new LibraryBuilder._(astNode, scope ?? new Scope()); + } - LibraryBuilder._(CompilationUnit astNode) : super._(astNode); + LibraryBuilder._(CompilationUnit astNode, this._scope) : super._(astNode); + + @override + void addDeclaration(CodeBuilder declaration) { + if (declaration is ScopeAware) { + _astNode.declarations.add(declaration.toScopedAst(_scope)); + } else { + super.addDeclaration(declaration); + } + } /// Adds [directive]'s resulting AST to the source. void addDirective(CodeBuilder directive) { _astNode.directives.add(directive.toAst()); } + + @override + CompilationUnit toAst() { + var originalAst = super.toAst(); + originalAst.directives..addAll(_scope.getImports().map((i) => i.toAst())); + return originalAst; + } } /// Builds a `part of` [CompilationUnit] AST for an existing Dart library. diff --git a/pkgs/code_builder/lib/src/builders/method_builder.dart b/pkgs/code_builder/lib/src/builders/method_builder.dart index a501df704..f43b756ba 100644 --- a/pkgs/code_builder/lib/src/builders/method_builder.dart +++ b/pkgs/code_builder/lib/src/builders/method_builder.dart @@ -11,7 +11,9 @@ part of code_builder; /// the top level and within other methods) via [toFunctionAst]. /// /// To return nothing (`void`), use [MethodBuilder.returnVoid]. -class MethodBuilder implements CodeBuilder { +class MethodBuilder implements + CodeBuilder, + ScopeAware { static Token _abstract = new KeywordToken(Keyword.ABSTRACT, 0); static Token _semicolon = new Token(TokenType.SEMICOLON, 0); static Token _static = new KeywordToken(Keyword.STATIC, 0); @@ -41,6 +43,9 @@ class MethodBuilder implements CodeBuilder { MethodBuilder._(this._name, this._returnType); + @override + List get requiredImports => null; + /// Lazily adds [annotation]. /// /// When the method is emitted as an AST, [AnnotationBuilder.toAst] is used. @@ -76,14 +81,14 @@ class MethodBuilder implements CodeBuilder { /// [toMethodAst]. @override @visibleForTesting - Declaration toAst() => toFunctionAst(); + Declaration toAst() => toScopedAst(const Scope.identity()); /// Returns a copy-safe [FunctionDeclaration] AST representing current state. - FunctionDeclaration toFunctionAst() { + FunctionDeclaration toFunctionAst({Scope scope: const Scope.identity()}) { var functionAst = _emptyFunction() ..metadata.addAll(_annotations.map/**/((a) => a.toAst())) ..name = _stringId(_name) - ..returnType = _returnType?.toAst(); + ..returnType = _returnType?.toScopedAst(scope); if (_returnExpression != null) { functionAst.functionExpression = _returnExpression.toFunctionExpression(); } else { @@ -95,7 +100,7 @@ class MethodBuilder implements CodeBuilder { } if (_parameters.isNotEmpty) { functionAst.functionExpression.parameters.parameters - .addAll(_parameters.map/**/((p) => p.toAst())); + .addAll(_parameters.map/**/((p) => p.toScopedAst(scope))); } return functionAst; } @@ -104,11 +109,12 @@ class MethodBuilder implements CodeBuilder { MethodDeclaration toMethodAst({ bool static: false, bool canBeAbstract: false, + Scope scope: const Scope.identity(), }) { var methodAst = _emptyMethod() ..metadata.addAll(_annotations.map/**/((a) => a.toAst())) ..name = _stringId(_name) - ..returnType = _returnType?.toAst(); + ..returnType = _returnType?.toScopedAst(scope); FunctionBody methodBody = _returnExpression?.toFunctionBody(); if (static) { methodAst.modifierKeyword = _static; @@ -123,12 +129,15 @@ class MethodBuilder implements CodeBuilder { } if (_parameters.isNotEmpty) { methodAst.parameters.parameters - .addAll(_parameters.map/**/((p) => p.toAst())); + .addAll(_parameters.map/**/((p) => p.toScopedAst(scope))); } methodAst.body = methodBody; return methodAst; } + @override + Declaration toScopedAst(Scope scope) => toFunctionAst(scope: scope); + @override String toString() => 'MethodBuilder ${toAst().toSource()}'; @@ -156,7 +165,7 @@ class MethodBuilder implements CodeBuilder { _blockBody(), ), ); - + // TODO: implement requiredImports static MethodDeclaration _emptyMethod() => new MethodDeclaration( null, null, diff --git a/pkgs/code_builder/lib/src/builders/parameter_builder.dart b/pkgs/code_builder/lib/src/builders/parameter_builder.dart index bf710d176..16466f656 100644 --- a/pkgs/code_builder/lib/src/builders/parameter_builder.dart +++ b/pkgs/code_builder/lib/src/builders/parameter_builder.dart @@ -9,44 +9,36 @@ part of code_builder; /// A parameter is part of a built [MethodBuilder], and can refer to a /// class-member (field) variable (see the `field` property in the /// constructors). -class ParameterBuilder extends _AbstractCodeBuilder { +class ParameterBuilder extends ScopeAware { static final Token _this = new KeywordToken(Keyword.THIS, 0); + final String _name; + final bool _isField; + final bool _isOptional; + final bool _isNamed; + final TypeBuilder _type; + final ExpressionBuilder _defaultTo; + + final List _annotations = []; + /// Create a new _required_ parameter of [name]. factory ParameterBuilder( String name, { bool field: false, TypeBuilder type, }) { - FormalParameter astNode; - if (field) { - astNode = new FieldFormalParameter( - null, - null, - null, - type?.toAst(), - _this, - null, - _stringId(name), - null, - null, - ); - } else { - astNode = new SimpleFormalParameter( - null, - null, - null, - type?.toAst(), - _stringId(name), - ); - } - return new ParameterBuilder._(astNode); + return new ParameterBuilder._( + name, + field, + false, + false, + type, + null, + ); } - /// Create a new _optional_ (but positional) parameter. - /// - /// See [ParameterBuilder.named] for an optional _named_ parameter. - factory ParameterBuilder.optional( + /// Create a new _optional_ _named_ parameter. + factory ParameterBuilder.named( String name, { bool field: false, TypeBuilder type, @@ -54,15 +46,17 @@ class ParameterBuilder extends _AbstractCodeBuilder { }) { return new ParameterBuilder._optional( name, - false, + true, field: field, type: type, defaultTo: defaultTo, ); } - /// Create a new _optional_ _named_ parameter. - factory ParameterBuilder.named( + /// Create a new _optional_ (but positional) parameter. + /// + /// See [ParameterBuilder.named] for an optional _named_ parameter. + factory ParameterBuilder.optional( String name, { bool field: false, TypeBuilder type, @@ -70,13 +64,22 @@ class ParameterBuilder extends _AbstractCodeBuilder { }) { return new ParameterBuilder._optional( name, - true, + false, field: field, type: type, defaultTo: defaultTo, ); } + ParameterBuilder._( + this._name, + this._isField, + this._isOptional, + this._isNamed, + this._type, + this._defaultTo, + ); + // Actual implementation of optional and named. factory ParameterBuilder._optional( String name, @@ -85,46 +88,76 @@ class ParameterBuilder extends _AbstractCodeBuilder { TypeBuilder type, ExpressionBuilder defaultTo, }) { + return new ParameterBuilder._( + name, + field, + true, + named, + type, + defaultTo, + ); + } + + /// Adds a metadata annotation from [builder]. + void addAnnotation(AnnotationBuilder builder) { + _annotations.add(builder); + } + + @override + FormalParameter toScopedAst(Scope scope) { FormalParameter astNode; - if (field) { - astNode = new FieldFormalParameter( + if (_isField) { + astNode = _createFieldFormalParameter(scope); + } else { + astNode = _createSimpleFormalParameter(scope); + } + if (_isOptional) { + astNode = _createDefaultFormalParameter( + astNode, + _isNamed, + _defaultTo, + scope, + ); + } + astNode.metadata.addAll(_annotations.map/**/((a) => a.toAst())); + return astNode; + } + + static DefaultFormalParameter _createDefaultFormalParameter( + FormalParameter parameter, + bool named, + ExpressionBuilder defaultTo, + Scope scope, + ) { + return new DefaultFormalParameter( + parameter, + named ? ParameterKind.NAMED : ParameterKind.POSITIONAL, + defaultTo != null + ? named ? new Token(TokenType.COLON, 0) : new Token(TokenType.EQ, 0) + : null, + defaultTo?.toAst(), + ); + } + + FieldFormalParameter _createFieldFormalParameter(Scope scope) => + new FieldFormalParameter( null, null, null, - type?.toAst(), + _type?.toScopedAst(scope), _this, null, - _stringId(name), + _stringId(_name), null, null, ); - } else { - astNode = new SimpleFormalParameter( + + SimpleFormalParameter _createSimpleFormalParameter(Scope scope) => + new SimpleFormalParameter( null, null, null, - type?.toAst(), - _stringId(name), + _type?.toScopedAst(scope), + _stringId(_name), ); - } - Token defaultToEq; - if (defaultTo != null) { - defaultToEq = - named ? new Token(TokenType.COLON, 0) : new Token(TokenType.EQ, 0); - } - astNode = new DefaultFormalParameter( - astNode, - named ? ParameterKind.NAMED : ParameterKind.POSITIONAL, - defaultToEq, - defaultTo?.toAst(), - ); - return new ParameterBuilder._(astNode); - } - - ParameterBuilder._(FormalParameter astNode) : super._(astNode); - - /// Adds a metadata annotation from [builder]. - void addAnnotation(AnnotationBuilder builder) { - _astNode.metadata.add(builder.toAst()); - } } diff --git a/pkgs/code_builder/lib/src/builders/type_builder.dart b/pkgs/code_builder/lib/src/builders/type_builder.dart index 45aac3213..19025c8b2 100644 --- a/pkgs/code_builder/lib/src/builders/type_builder.dart +++ b/pkgs/code_builder/lib/src/builders/type_builder.dart @@ -5,7 +5,7 @@ part of code_builder; /// Build a [TypeName] AST. -class TypeBuilder implements RequiresImport { +class TypeBuilder implements ScopeAware { final String _identifier; final String _importFrom; @@ -22,11 +22,10 @@ class TypeBuilder implements RequiresImport { List get requiredImports => [_importFrom]; @override - TypeName toAst() => new TypeName( - _stringId(_identifier), - null, - ); + TypeName toAst() => toScopedAst(const Scope.identity()); @override - TypeName toScopedAst(FileBuilder scope) => throw new UnimplementedError(); + TypeName toScopedAst(Scope scope) { + return new TypeName(scope.getIdentifier(_identifier, _importFrom), null); + } } diff --git a/pkgs/code_builder/lib/src/scope.dart b/pkgs/code_builder/lib/src/scope.dart index 92ead6c15..a96f32665 100644 --- a/pkgs/code_builder/lib/src/scope.dart +++ b/pkgs/code_builder/lib/src/scope.dart @@ -20,8 +20,11 @@ abstract class Scope { /// will be unique in a given scope (actual implementation may be naive). factory Scope() = _IncrementingScope; - /// Create a context that does _not_ apply any scoping. - factory Scope.identity() = _IdentityScope; + /// Create a context that just de-duplicates imports (no scoping). + factory Scope.dedupe() = _DeduplicatingScope; + + /// Create a context that does nothing. + const factory Scope.identity() = _IdentityScope; /// Given a [symbol] and its known [importUri], return an [Identifier]. Identifier getIdentifier(String symbol, String importUri); @@ -30,7 +33,7 @@ abstract class Scope { Iterable getImports(); } -class _IdentityScope implements Scope { +class _DeduplicatingScope implements Scope { final Set _imports = new Set(); @override @@ -45,6 +48,16 @@ class _IdentityScope implements Scope { } } +class _IdentityScope implements Scope { + const _IdentityScope(); + + @override + Identifier getIdentifier(String symbol, _) => _stringId(symbol); + + @override + Iterable getImports() => const []; +} + class _IncrementingScope implements Scope { final Map _imports = {}; diff --git a/pkgs/code_builder/lib/testing/equals_source.dart b/pkgs/code_builder/lib/testing/equals_source.dart index a706e7dcd..5c69e4f13 100644 --- a/pkgs/code_builder/lib/testing/equals_source.dart +++ b/pkgs/code_builder/lib/testing/equals_source.dart @@ -2,6 +2,9 @@ // 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:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/src/dart/ast/token.dart'; import 'package:code_builder/code_builder.dart'; import 'package:matcher/matcher.dart'; @@ -16,8 +19,41 @@ import 'package:matcher/matcher.dart'; /// /// If you have code that is not consider a valid compilation unit (like an /// expression, you should flip [format] to `false`). -Matcher equalsSource(String source, {bool format: true}) { - return new _EqualsSource(format ? dartfmt(source) : source, format); +Matcher equalsSource(String source, {bool format: true, Scope scope}) { + return new _EqualsSource( + scope, + format ? dartfmt(source) : source, + format, + ); +} + +Identifier _stringId(String s) { + return new SimpleIdentifier(new StringToken(TokenType.STRING, s, 0)); +} + +/// Returns identifiers that are just the file name. +/// +/// For example `getIdentifier('Foo', 'package:foo/foo.dart')` would return +/// the identifier "foo.Foo". This isn't safe enough for use in a actual +/// code-gen but makes it easy to debug issues in our tests. +const Scope simpleNameScope = const _SimpleNameScope(); + +class _SimpleNameScope implements Scope { + const _SimpleNameScope(); + + @override + Identifier getIdentifier(String symbol, String importUri) { + var fileWithoutExt = + Uri.parse(importUri).pathSegments.last.split('.').first; + return new PrefixedIdentifier( + _stringId(fileWithoutExt), + new Token(TokenType.PERIOD, 0), + _stringId(symbol), + ); + } + + @override + Iterable getImports() => const []; } // Delegates to the default matcher (which delegates further). @@ -25,10 +61,11 @@ Matcher equalsSource(String source, {bool format: true}) { // Would be nice to just use more of package:matcher directly: // https://github.com/dart-lang/matcher/issues/36 class _EqualsSource extends Matcher { + final Scope _scope; final String _source; final bool _isFormatted; - _EqualsSource(this._source, this._isFormatted); + _EqualsSource(this._scope, this._source, this._isFormatted); @override Description describe(Description description) { @@ -55,11 +92,16 @@ class _EqualsSource extends Matcher { } String _formatAst(CodeBuilder builder) { - var ast = builder.toAst(); + AstNode astNode; + if (_scope != null && builder is ScopeAware) { + astNode = builder.toScopedAst(_scope); + } else { + astNode = builder.toAst(); + } if (_isFormatted) { - return prettyToSource(ast); + return prettyToSource(astNode); } else { - return ast.toSource(); + return astNode.toSource(); } } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 77cd407aa..d3f7b3227 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 0.1.0-dev+1 +version: 0.1.0-dev+2 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/method_builder_test.dart b/pkgs/code_builder/test/builders/method_builder_test.dart index 28bb930a6..e5696573a 100644 --- a/pkgs/code_builder/test/builders/method_builder_test.dart +++ b/pkgs/code_builder/test/builders/method_builder_test.dart @@ -22,6 +22,37 @@ void main() { ); }); + test('should emit a method returning a scoped Type', () { + expect( + new MethodBuilder( + name: 'toFoo', + returns: new TypeBuilder('Foo', importFrom: 'package:foo/foo.dart'), + )..addParameter(new ParameterBuilder( + 'context', + type: new TypeBuilder('Context', importFrom: 'package:bar/bar.dart'), + )), + equalsSource( + r''' + foo.Foo toFoo(bar.Context context) {} + ''', + scope: simpleNameScope, + )); + }); + + test('should emit a method returning a scoped Type and scoped Param', () { + expect( + new MethodBuilder( + name: 'toFoo', + returns: new TypeBuilder('Foo', importFrom: 'package:foo/foo.dart'), + ), + equalsSource( + r''' + foo.Foo toFoo() {} + ''', + scope: simpleNameScope, + )); + }); + test('should emit a method annotated', () { expect( new MethodBuilder(name: 'oldMethod')..addAnnotation(atDeprecated()), diff --git a/pkgs/code_builder/test/integration_test.dart b/pkgs/code_builder/test/integration_test.dart index 8510c7b84..4571d66e1 100644 --- a/pkgs/code_builder/test/integration_test.dart +++ b/pkgs/code_builder/test/integration_test.dart @@ -55,4 +55,40 @@ void main() { ), ); }); + + test('Emits a complex generated file with conflicting imports scoped', () { + 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', + ), + ))); + expect( + lib, + equalsSource( + r''' + import 'package:thing/thing.dart' as _i1; + import 'package:thing/alternative.dart' as _i2; + + _i1.Thing doThing() {} + _i2.Thing doOtherThing(_i1.Thing thing) {} + ''', + ), + ); + }); } diff --git a/pkgs/code_builder/test/scope_test.dart b/pkgs/code_builder/test/scope_test.dart index db32ead56..3f45a2f2f 100644 --- a/pkgs/code_builder/test/scope_test.dart +++ b/pkgs/code_builder/test/scope_test.dart @@ -6,7 +6,29 @@ void main() { group('Identity scope', () { Scope scope; - setUp(() => scope = new Scope.identity()); + setUp(() => scope = const Scope.identity()); + + test('should do nothing', () { + var identifiers = [ + scope.getIdentifier('Foo', 'package:foo/foo.dart'), + scope.getIdentifier('Bar', 'package:foo/foo.dart'), + scope.getIdentifier('Baz', 'package:baz/baz.dart'), + ].map/**/((i) => i.toSource()); + + expect(identifiers, [ + 'Foo', + 'Bar', + 'Baz', + ],); + + expect(scope.getImports(), isEmpty); + }); + }); + + group('Deduplicating scope', () { + Scope scope; + + setUp(() => scope = new Scope.dedupe()); test('should just output non-prefixed and de-duplicate imports', () { var identifiers = [ From 8a5f3f825fdfd4379cf23dcd7170811d7a6e35f5 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 16 Sep 2016 10:51:48 -0700 Subject: [PATCH 011/271] Add full scoping support for Library (dart-lang/code_builder#11) * Add full scoping support for Library * Address comments. --- pkgs/code_builder/CHANGELOG.md | 8 + pkgs/code_builder/lib/code_builder.dart | 63 +++---- .../lib/src/builders/annotation_builder.dart | 24 +-- .../lib/src/builders/class_builder.dart | 124 +++++++------ .../lib/src/builders/constructor_builder.dart | 64 ++++--- .../lib/src/builders/expression_builder.dart | 107 +++++++++--- .../lib/src/builders/field_builder.dart | 54 +++--- .../lib/src/builders/file_builder.dart | 163 +++++++++--------- .../lib/src/builders/method_builder.dart | 74 ++++---- .../lib/src/builders/parameter_builder.dart | 44 ++--- .../lib/src/builders/type_builder.dart | 10 +- pkgs/code_builder/lib/src/scope.dart | 8 +- .../lib/testing/equals_source.dart | 87 +++++----- pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/class_builder_test.dart | 34 ++-- .../test/builders/file_builder_test.dart | 4 +- .../test/builders/method_builder_test.dart | 18 +- pkgs/code_builder/test/integration_test.dart | 88 ++++++++-- pkgs/code_builder/test/scope_test.dart | 67 ++++--- 19 files changed, 602 insertions(+), 441 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index a11689988..1cb8ebe39 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.1.1 + +- Add concept of `Scope` and change `toAst` to support it + +Now your entire AST tree can be scoped and import directives +automatically added to a `LibraryBuilder` for you if you use +`LibraryBuilder.scope`. + ## 0.1.0 - Initial version diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index fc800e7d4..ab48ab7f6 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -44,17 +44,38 @@ 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); + +// Creates a deep copy of an AST node. +AstNode/*=E*/ _cloneAst/**/(AstNode/*=E*/ astNode) { + return new AstCloner().cloneNode/**/(astNode); +} + +Identifier _stringIdentifier(String s) { + return new SimpleIdentifier(new StringToken(TokenType.STRING, s, 0)); +} + +Literal _stringLiteral(String s) { + return new SimpleStringLiteral(new StringToken(TokenType.STRING, s, 0), s); +} + /// Base class for building and emitting a Dart language [AstNode]. abstract class CodeBuilder { /// Returns a copy-safe [AstNode] representing the current builder state. - A toAst(); + /// + /// Uses [scope] to output an AST re-written to use appropriate prefixes. + A toAst([Scope scope = const Scope.identity()]); } -// Simplifies some of the builders by having a mutable node we clone from. +@Deprecated('Builders are all becoming lazy') abstract class _AbstractCodeBuilder extends CodeBuilder { final A _astNode; @@ -62,42 +83,8 @@ abstract class _AbstractCodeBuilder extends CodeBuilder { /// Returns a copy-safe [AstNode] representing the current builder state. @override - A toAst() => _cloneAst/**/(_astNode); + A toAst([_]) => _cloneAst/**/(_astNode); @override String toString() => '$runtimeType: ${_astNode.toSource()}'; } - -/// Marker interface for builders that need an import to work. -/// -/// **NOTE**: This currently (as of 0.2.0) has no effect. It is planned that -/// the [FileBuilder] will be able to act as a scope 'resolver' and subtly -/// rewrite the AST tree to use prefixing if required (or requested). -abstract class ScopeAware implements CodeBuilder { - @override - A toAst() => toScopedAst(const Scope.identity()); - - /// Creates a copy-safe [AstNode] representing the current builder state. - /// - /// Uses [scope] to output an AST re-written to use appropriate prefixes. - A toScopedAst(Scope scope) => throw new UnimplementedError(); -} - -// Creates a defensive copy of an AST node. -AstNode/*=E*/ _cloneAst/**/(AstNode/*=E*/ astNode) { - return new AstCloner().cloneNode/**/(astNode); -} - -final DartFormatter _dartfmt = new DartFormatter(); - -/// Returns [source] formatted by `dartfmt`. -@visibleForTesting -String dartfmt(String source) => _dartfmt.format(source); - -Literal _stringLit(String s) { - return new SimpleStringLiteral(new StringToken(TokenType.STRING, s, 0), s); -} - -Identifier _stringId(String s) { - return new SimpleIdentifier(new StringToken(TokenType.STRING, s, 0)); -} diff --git a/pkgs/code_builder/lib/src/builders/annotation_builder.dart b/pkgs/code_builder/lib/src/builders/annotation_builder.dart index a209a4644..1ce7b70eb 100644 --- a/pkgs/code_builder/lib/src/builders/annotation_builder.dart +++ b/pkgs/code_builder/lib/src/builders/annotation_builder.dart @@ -16,7 +16,7 @@ part of code_builder; /// void destroyTheWorld() { ... } /// /// To create a `@DoNotUse('Blows up')` use [AnnotationBuilder.invoke]. -abstract class AnnotationBuilder implements ScopeAware { +abstract class AnnotationBuilder implements CodeBuilder { /// Create a new annotated `const` [constructor] invocation. /// /// May optionally specify an [importFrom] to auto-prefix the annotation _if_ @@ -46,8 +46,7 @@ abstract class AnnotationBuilder implements ScopeAware { [String importFrom]) = _ReferenceAnnotationBuilder; } -class _ConstructorAnnotationBuilder extends ScopeAware - implements AnnotationBuilder { +class _ConstructorAnnotationBuilder implements AnnotationBuilder { final String _constructor; final ExpressionBuilder _expression; final String _importFrom; @@ -56,15 +55,12 @@ class _ConstructorAnnotationBuilder extends ScopeAware [this._importFrom]); @override - List get requiredImports => [_importFrom]; - - @override - Annotation toAst() { - var expressionAst = _expression.toAst(); + Annotation toAst([Scope scope = const Scope.identity()]) { + var expressionAst = _expression.toAst(scope); if (expressionAst is MethodInvocation) { return new Annotation( null, - _stringId(_constructor), + scope.getIdentifier(_constructor, _importFrom), null, null, // TODO(matanl): InvocationExpression needs to be public API. @@ -82,17 +78,11 @@ class _ReferenceAnnotationBuilder implements AnnotationBuilder { const _ReferenceAnnotationBuilder(this._reference, [this._importFrom]); @override - List get requiredImports => [_importFrom]; - - @override - Annotation toAst() => new Annotation( + Annotation toAst([Scope scope = const Scope.identity()]) => new Annotation( null, - _stringId(_reference), + scope.getIdentifier(_reference, _importFrom), null, null, null, ); - - @override - Annotation toScopedAst(_) => throw new UnimplementedError(); } diff --git a/pkgs/code_builder/lib/src/builders/class_builder.dart b/pkgs/code_builder/lib/src/builders/class_builder.dart index e9ca4170e..afb3cbc12 100644 --- a/pkgs/code_builder/lib/src/builders/class_builder.dart +++ b/pkgs/code_builder/lib/src/builders/class_builder.dart @@ -5,79 +5,107 @@ part of code_builder; /// Builds a [ClassDeclaration] AST. -class ClassBuilder extends _AbstractCodeBuilder { +class ClassBuilder implements CodeBuilder { static Token _abstract = new KeywordToken(Keyword.ABSTRACT, 0); static Token _extends = new KeywordToken(Keyword.EXTENDS, 0); static Token _implements = new KeywordToken(Keyword.IMPLEMENTS, 0); static Token _with = new KeywordToken(Keyword.WITH, 0); + final String _name; + final bool _isAbstract; + final TypeBuilder _extend; + final Iterable _implement; + final Iterable _mixin; + + final List _fields = []; + final List _methods = []; + final List _metadata = []; + final List _constructors = []; + /// Create a new builder for a `class` named [name]. /// /// Optionally, define another class to [extend] or classes to either /// [implement] or [mixin]. You may also define a `class` as [abstract]. factory ClassBuilder( String name, { - bool abstract: false, - String extend, - Iterable implement: const [], - Iterable mixin: const [], - }) { - var astNode = _emptyClassDeclaration()..name = _stringId(name); - if (abstract) { - astNode.abstractKeyword = _abstract; - } - if (extend != null) { - astNode.extendsClause = new ExtendsClause( - _extends, - new TypeName( - _stringId(extend), - null, - )); - } - if (implement.isNotEmpty) { - astNode.implementsClause = new ImplementsClause( - _implements, - implement - .map/**/((i) => new TypeName(_stringId(i), null)) - .toList()); - } - if (mixin.isNotEmpty) { - astNode.withClause = new WithClause( - _with, - mixin - .map/**/((i) => new TypeName(_stringId(i), null)) - .toList()); - } - return new ClassBuilder._(astNode); - } + TypeBuilder extend, + Iterable implement: const [], + Iterable mixin: const [], + }) => + new ClassBuilder._( + name, + false, + extend, + new List.unmodifiable(implement), + new List.unmodifiable(mixin), + ); - ClassBuilder._(ClassDeclaration astNode) : super._(astNode); + factory ClassBuilder.asAbstract(String name, + {TypeBuilder extend, + Iterable implement: const [], + Iterable mixin: const []}) => + new ClassBuilder._( + name, + true, + extend, + new List.unmodifiable(implement), + new List.unmodifiable(mixin), + ); + + ClassBuilder._( + this._name, + this._isAbstract, + this._extend, + this._implement, + this._mixin, + ); /// Adds an annotation [builder] as metadata. void addAnnotation(AnnotationBuilder builder) { - _astNode.metadata.add(builder.toAst()); + _metadata.add(builder); } /// Adds a constructor [builder]. void addConstructor(ConstructorBuilder builder) { - var astNode = builder.toAst(); - if (astNode.returnType == null) { - astNode.returnType = _astNode.name; - } - _astNode.members.add(astNode); + _constructors.add(builder); } /// Adds a field [builder] as a member on the class. - void addField(FieldBuilder builder, {bool static: false}) { - _astNode.members.add(builder.toFieldAst(static: static)); + void addField(FieldBuilder builder) { + _fields.add(builder); } /// Adds a method [builder] as a member on the class. - void addMethod(MethodBuilder builder, {bool static: false}) { - _astNode.members.add(builder.toMethodAst( - static: static, - canBeAbstract: _astNode.abstractKeyword != null, - )); + void addMethod(MethodBuilder builder) { + _methods.add(builder); + } + + @override + ClassDeclaration toAst([Scope scope = const Scope.identity()]) { + var astNode = _emptyClassDeclaration()..name = _stringIdentifier(_name); + if (_isAbstract) { + astNode.abstractKeyword = _abstract; + } + if (_extend != null) { + astNode.extendsClause = new ExtendsClause(_extends, _extend.toAst(scope)); + } + if (_implement.isNotEmpty) { + astNode.implementsClause = new ImplementsClause(_implements, + _implement.map/**/((i) => i.toAst(scope)).toList()); + } + if (_mixin.isNotEmpty) { + astNode.withClause = new WithClause( + _with, _mixin.map/**/((i) => i.toAst(scope)).toList()); + } + astNode + ..metadata.addAll(_metadata.map/**/((a) => a.toAst(scope))); + astNode + ..members.addAll(_fields.map/**/((f) => f.toFieldAst(scope))) + ..members.addAll(_constructors.map/**/( + (c) => c.toAst(scope)..returnType = _stringIdentifier(_name))) + ..members + .addAll(_methods.map/**/((m) => m.toMethodAst(scope))); + return astNode; } static ClassDeclaration _emptyClassDeclaration() => new ClassDeclaration( diff --git a/pkgs/code_builder/lib/src/builders/constructor_builder.dart b/pkgs/code_builder/lib/src/builders/constructor_builder.dart index 0839a05cb..cf01588ab 100644 --- a/pkgs/code_builder/lib/src/builders/constructor_builder.dart +++ b/pkgs/code_builder/lib/src/builders/constructor_builder.dart @@ -6,55 +6,51 @@ part of code_builder; /// Builds a [ConstructorDeclaration] AST. /// -/// Similar to [MethodBuilder] but adds constructor-only features. -/// -/// Use [ConstructorBuilder.initializeFields] to create something like: -/// class Foo { -/// final _one; -/// final _two; -/// -/// Foo(this._one, this._two); -/// } -class ConstructorBuilder extends _AbstractCodeBuilder { +/// Similar to [MethodBuilder] but with constructor-only features. +class ConstructorBuilder implements CodeBuilder { static final Token _const = new KeywordToken(Keyword.CONST, 0); static final Token _this = new KeywordToken(Keyword.THIS, 0); - /// Create a simple [ConstructorBuilder] that initializes class fields. + final bool _isConstant; + final String _name; + final List _parameters = []; + + factory ConstructorBuilder([String name]) { + return new ConstructorBuilder._(false, name); + } + + factory ConstructorBuilder.isConst([String name]) { + return new ConstructorBuilder._(true, name); + } + + ConstructorBuilder._(this._isConstant, this._name); + + /// Lazily adds [parameter]. /// - /// May optionally be [constant] compatible, or have a [name]. - factory ConstructorBuilder.initializeFields( - {bool constant: false, - String name, - Iterable positionalArguments: const [], - Iterable optionalArguments: const [], - Iterable namedArguments: const []}) { - var parameters = []; - for (var a in positionalArguments) { - parameters.add(new ParameterBuilder(a, field: true).toAst()); - } - for (var a in optionalArguments) { - parameters.add(new ParameterBuilder.optional(a, field: true).toAst()); - } - for (var a in namedArguments) { - parameters.add(new ParameterBuilder.named(a, field: true).toAst()); - } + /// When the method is emitted as an AST, [ParameterBuilder.toAst] is used. + void addParameter(ParameterBuilder builder) { + _parameters.add(builder); + } + + @override + ConstructorDeclaration toAst([Scope scope = const Scope.identity()]) { var astNode = new ConstructorDeclaration( null, null, null, null, - constant ? _const : null, + _isConstant ? _const : null, null, null, - name != null ? _stringId(name) : null, - MethodBuilder._emptyParameters()..parameters.addAll(parameters), + _name != null ? _stringIdentifier(_name) : null, + MethodBuilder._emptyParameters() + ..parameters.addAll( + _parameters.map/**/((p) => p.toAst(scope))), null, null, null, new EmptyFunctionBody(MethodBuilder._semicolon), ); - return new ConstructorBuilder._(astNode); + return astNode; } - - ConstructorBuilder._(ConstructorDeclaration astNode) : super._(astNode); } diff --git a/pkgs/code_builder/lib/src/builders/expression_builder.dart b/pkgs/code_builder/lib/src/builders/expression_builder.dart index 365dc6559..823e00419 100644 --- a/pkgs/code_builder/lib/src/builders/expression_builder.dart +++ b/pkgs/code_builder/lib/src/builders/expression_builder.dart @@ -23,16 +23,22 @@ final Token _openP = new Token(TokenType.OPEN_PAREN, 0); final Token _semicolon = new Token(TokenType.SEMICOLON, 0); // TODO(matanl): Make this part of the public API. See annotation_builder.dart. -ExpressionFunctionBody _asFunctionBody(CodeBuilder expression) { +ExpressionFunctionBody _asFunctionBody( + CodeBuilder expression, + Scope scope, +) { return new ExpressionFunctionBody( null, null, - expression.toAst(), + expression.toAst(scope), _semicolon, ); } -FunctionExpression _asFunctionExpression(CodeBuilder expression) { +FunctionExpression _asFunctionExpression( + CodeBuilder expression, + Scope scope, +) { return new FunctionExpression( null, new FormalParameterList( @@ -42,7 +48,7 @@ FunctionExpression _asFunctionExpression(CodeBuilder expression) { null, _closeP, ), - _asFunctionBody(expression), + _asFunctionBody(expression, scope), ); } @@ -73,6 +79,7 @@ abstract class ExpressionBuilder implements CodeBuilder { /// Optionally specify [positional] and [named] arguments. factory ExpressionBuilder.invoke( String name, { + String importFrom, Iterable> positional: const [], Map> named: const {}, }) { @@ -80,6 +87,21 @@ abstract class ExpressionBuilder implements CodeBuilder { name, new List>.unmodifiable(positional), new Map>.unmodifiable(named), + importFrom, + ); + } + + factory ExpressionBuilder.invokeNew( + TypeBuilder type, { + String name, + Iterable> positional: const [], + Map> named: const {}, + }) { + return new _InvokeExpression.newInstance( + type, + name, + new List>.unmodifiable(positional), + new Map>.unmodifiable(named), ); } @@ -93,10 +115,14 @@ abstract class ExpressionBuilder implements CodeBuilder { }); // TODO(matanl): Rename to invoke when factory is removed. /// Returns wrapped as a [ExpressionFunctionBody] AST. - ExpressionFunctionBody toFunctionBody() => _asFunctionBody(this); + ExpressionFunctionBody toFunctionBody( + [Scope scope = const Scope.identity()]) => + _asFunctionBody(this, scope); /// Returns wrapped as a [FunctionExpression] AST. - FunctionExpression toFunctionExpression() => _asFunctionExpression(this); + FunctionExpression toFunctionExpression( + [Scope scope = const Scope.identity()]) => + _asFunctionExpression(this, scope); /// Converts to a [StatementBuilder]. /// @@ -118,7 +144,7 @@ class LiteralBool extends _LiteralExpression { const LiteralBool(this._value); @override - BooleanLiteral toAst() => _value ? _true : _false; + BooleanLiteral toAst([_]) => _value ? _true : _false; } /// Represents an expression value of a literal number. @@ -129,8 +155,10 @@ class LiteralInt extends _LiteralExpression { const LiteralInt(this._value); @override - IntegerLiteral toAst() => - new IntegerLiteral(new StringToken(TokenType.INT, '$_value', 0), _value); + IntegerLiteral toAst([_]) => new IntegerLiteral( + new StringToken(TokenType.INT, '$_value', 0), + _value, + ); } /// Represents an expression value of a literal `'string'`. @@ -141,7 +169,7 @@ class LiteralString extends _LiteralExpression { const LiteralString(this._value); @override - StringLiteral toAst() => new SimpleStringLiteral( + StringLiteral toAst([_]) => new SimpleStringLiteral( new StringToken( TokenType.STRING, "'$_value'", @@ -151,26 +179,41 @@ class LiteralString extends _LiteralExpression { ); } -class _InvokeExpression extends ExpressionBuilder - implements CodeBuilder { +class _InvokeExpression extends ExpressionBuilder { static final Token _colon = new Token(TokenType.COLON, 0); + final String _importFrom; final ExpressionBuilder _target; final String _name; final List> _positionalArguments; final Map> _namedArguments; + final TypeBuilder _type; const _InvokeExpression( this._name, this._positionalArguments, this._namedArguments, + this._importFrom, ) : _target = null, + _type = null, + super._(); + + const _InvokeExpression.newInstance( + this._type, + this._name, + this._positionalArguments, + this._namedArguments, + ) + : _target = null, + _importFrom = null, super._(); const _InvokeExpression.target( this._name, this._target, this._positionalArguments, this._namedArguments) - : super._(); + : _importFrom = null, + _type = null, + super._(); @override ExpressionBuilder invokeSelf( @@ -181,30 +224,42 @@ class _InvokeExpression extends ExpressionBuilder _invokeSelfImpl(this, name, positional: positional, named: named); @override - InvocationExpression toAst() { + Expression toAst([Scope scope = const Scope.identity()]) { + // TODO(matanl): Move to TypeBuilder.newInstance. + if (_type != null) { + return new InstanceCreationExpression( + new KeywordToken(Keyword.NEW, 0), + new ConstructorName( + _type.toAst(scope), + _name != null ? new Token(TokenType.PERIOD, 0) : null, + _name != null ? _stringIdentifier(_name) : null, + ), + _getArgumentList(scope), + ); + } return new MethodInvocation( - _target?.toAst(), + _target?.toAst(scope), _target != null ? new Token(TokenType.PERIOD, 0) : null, - _stringId(_name), + _stringIdentifier(_name), null, - _getArgumentList(), + _getArgumentList(scope), ); } @override StatementBuilder toStatement() => new StatementBuilder.fromExpression(this); - ArgumentList _getArgumentList() { + ArgumentList _getArgumentList(Scope scope) { return new ArgumentList( new Token(TokenType.OPEN_CURLY_BRACKET, 0), - _positionalArguments.map/* p.toAst()).toList() + _positionalArguments.map/* p.toAst(scope)).toList() ..addAll(_namedArguments.keys .map/**/((name) => new NamedExpression( new Label( - _stringId(name), + _stringIdentifier(name), _colon, ), - _namedArguments[name].toAst(), + _namedArguments[name].toAst(scope), ))), new Token(TokenType.CLOSE_CURLY_BRACKET, 0), ); @@ -224,10 +279,14 @@ abstract class _LiteralExpression _invokeSelfImpl(this, name, positional: positional, named: named); @override - ExpressionFunctionBody toFunctionBody() => _asFunctionBody(this); + ExpressionFunctionBody toFunctionBody( + [Scope scope = const Scope.identity()]) => + _asFunctionBody(this, scope); @override - FunctionExpression toFunctionExpression() => _asFunctionExpression(this); + FunctionExpression toFunctionExpression( + [Scope scope = const Scope.identity()]) => + _asFunctionExpression(this, scope); @override StatementBuilder toStatement() => new StatementBuilder.fromExpression(this); @@ -239,5 +298,5 @@ class _LiteralNull extends _LiteralExpression { const _LiteralNull(); @override - NullLiteral toAst() => _null; + NullLiteral toAst([_]) => _null; } diff --git a/pkgs/code_builder/lib/src/builders/field_builder.dart b/pkgs/code_builder/lib/src/builders/field_builder.dart index c6e9e2c24..5977e5546 100644 --- a/pkgs/code_builder/lib/src/builders/field_builder.dart +++ b/pkgs/code_builder/lib/src/builders/field_builder.dart @@ -19,6 +19,7 @@ class FieldBuilder implements CodeBuilder { final bool _isConst; final bool _isFinal; + final bool _isStatic; final ExpressionBuilder _initialize; final String _name; final TypeBuilder _type; @@ -30,11 +31,13 @@ class FieldBuilder implements CodeBuilder { this._name, { TypeBuilder type, ExpressionBuilder initialize, + bool asStatic: false, }) : this._type = type, this._initialize = initialize, this._isFinal = false, - this._isConst = false; + this._isConst = false, + this._isStatic = asStatic; /// Create a new field builder that emits a `const` field. /// @@ -43,11 +46,13 @@ class FieldBuilder implements CodeBuilder { this._name, { TypeBuilder type, ExpressionBuilder initialize, + bool asStatic: false, }) : this._type = type, this._initialize = initialize, this._isFinal = false, - this._isConst = true; + this._isConst = true, + this._isStatic = false; /// Create a new field builder that emits a `final` field. /// @@ -56,21 +61,13 @@ class FieldBuilder implements CodeBuilder { this._name, { TypeBuilder type, ExpressionBuilder initialize, + bool asStatic: false, }) : this._type = type, this._initialize = initialize, this._isFinal = true, - this._isConst = false; - - Token _getVariableKeyword() { - if (_isFinal) { - return _final; - } - if (_isConst) { - return _const; - } - return _type == null ? _var : null; - } + this._isConst = false, + this._isStatic = asStatic; /// Returns a copy-safe [AstNode] representing the current builder state. /// @@ -79,32 +76,43 @@ class FieldBuilder implements CodeBuilder { /// [toVariablesAst]. @override @visibleForTesting - Declaration toAst() => toFieldAst(); + Declaration toAst([Scope scope = const Scope.identity()]) => + toFieldAst(scope); /// Returns a copy-safe [FieldDeclaration] AST representing current state. - FieldDeclaration toFieldAst({ - bool static: false, - }) => + FieldDeclaration toFieldAst([Scope scope = const Scope.identity()]) => new FieldDeclaration( null, null, - static ? _static : null, - toVariablesAst(), + _isStatic ? _static : null, + toVariablesAst(scope), null, ); /// Returns a copy-safe [VariableDeclaration] AST representing current state. - VariableDeclarationList toVariablesAst() => new VariableDeclarationList( + VariableDeclarationList toVariablesAst( + [Scope scope = const Scope.identity()]) => + new VariableDeclarationList( null, null, _getVariableKeyword(), - _type?.toAst(), + _type?.toAst(scope), [ new VariableDeclaration( - _stringId(_name), + _stringIdentifier(_name), _initialize != null ? _equals : null, - _initialize?.toAst(), + _initialize?.toAst(scope), ) ], ); + + Token _getVariableKeyword() { + if (_isFinal) { + return _final; + } + if (_isConst) { + return _const; + } + return _type == null ? _var : null; + } } diff --git a/pkgs/code_builder/lib/src/builders/file_builder.dart b/pkgs/code_builder/lib/src/builders/file_builder.dart index d6fdcc76b..8e3c026df 100644 --- a/pkgs/code_builder/lib/src/builders/file_builder.dart +++ b/pkgs/code_builder/lib/src/builders/file_builder.dart @@ -5,12 +5,33 @@ part of code_builder; CompilationUnit _emptyCompilationUnit() => new CompilationUnit( - null, - null, - null, - null, - null, - ); + null, + null, + null, + null, + null, + ); + +/// An `export` directive in a [LibraryBuilder]. +class ExportBuilder extends _AbstractCodeBuilder { + /// Create a new `export` directive exporting [uri]. + factory ExportBuilder(String uri) { + var astNode = _createExportDirective()..uri = _stringLiteral("'$uri'"); + return new ExportBuilder._(astNode); + } + + ExportBuilder._(ExportDirective astNode) : super._(astNode); + + static ExportDirective _createExportDirective() => new ExportDirective( + null, + null, + null, + null, + null, + null, + null, + ); +} /// Builds files of Dart source code. /// @@ -24,6 +45,39 @@ abstract class FileBuilder extends _AbstractCodeBuilder { } } +/// An `import` directive in a [FileBuilder]. +class ImportBuilder extends _AbstractCodeBuilder { + static Token _as = new KeywordToken(Keyword.AS, 0); + + /// Create a new `import` directive importing [uri]. + /// + /// Optionally prefix [as]. + factory ImportBuilder(String uri, {String as}) { + var astNode = _createImportDirective()..uri = _stringLiteral("'$uri'"); + if (as != null) { + astNode + ..asKeyword = _as + ..prefix = _stringIdentifier(as); + } + return new ImportBuilder._(astNode); + } + + ImportBuilder._(ImportDirective astNode) : super._(astNode); + + static ImportDirective _createImportDirective() => new ImportDirective( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + ); +} + /// Builds a standalone Dart library [CompilationUnit] AST. class LibraryBuilder extends FileBuilder { static final Token _library = new KeywordToken(Keyword.LIBRARY, 0); @@ -35,13 +89,14 @@ class LibraryBuilder extends FileBuilder { var astNode = _emptyCompilationUnit(); if (name != null) { astNode.directives.add(new LibraryDirective( - null, - null, - _library, - new LibraryIdentifier([_stringId(name)]), - null,)); + null, + null, + _library, + new LibraryIdentifier([_stringIdentifier(name)]), + null, + )); } - return new LibraryBuilder._(astNode, new Scope.dedupe()); + return new LibraryBuilder._(astNode, const Scope.identity()); } /// Create a new standalone Dart library, optionally with a [name]. @@ -53,11 +108,12 @@ class LibraryBuilder extends FileBuilder { var astNode = _emptyCompilationUnit(); if (name != null) { astNode.directives.add(new LibraryDirective( - null, - null, - _library, - new LibraryIdentifier([_stringId(name)]), - null,)); + null, + null, + _library, + new LibraryIdentifier([_stringIdentifier(name)]), + null, + )); } return new LibraryBuilder._(astNode, scope ?? new Scope()); } @@ -66,11 +122,7 @@ class LibraryBuilder extends FileBuilder { @override void addDeclaration(CodeBuilder declaration) { - if (declaration is ScopeAware) { - _astNode.declarations.add(declaration.toScopedAst(_scope)); - } else { - super.addDeclaration(declaration); - } + _astNode.declarations.add(declaration.toAst(_scope)); } /// Adds [directive]'s resulting AST to the source. @@ -79,7 +131,7 @@ class LibraryBuilder extends FileBuilder { } @override - CompilationUnit toAst() { + CompilationUnit toAst([_]) { var originalAst = super.toAst(); originalAst.directives..addAll(_scope.getImports().map((i) => i.toAst())); return originalAst; @@ -95,68 +147,15 @@ class PartBuilder extends FileBuilder { factory PartBuilder(String name) { var astNode = _emptyCompilationUnit(); astNode.directives.add(new PartOfDirective( - null, - null, - _part, - _of, - new LibraryIdentifier([_stringId(name)]), - null, - )); - return new PartBuilder._(astNode); - } - - PartBuilder._(CompilationUnit astNode) : super._(astNode); -} -/// An `export` directive in a [LibraryBuilder]. -class ExportBuilder extends _AbstractCodeBuilder { - /// Create a new `export` directive exporting [uri]. - factory ExportBuilder(String uri) { - var astNode = _createExportDirective()..uri = _stringLit("'$uri'"); - return new ExportBuilder._(astNode); - } - - ExportBuilder._(ExportDirective astNode) : super._(astNode); - - static ExportDirective _createExportDirective() => new ExportDirective( null, null, + _part, + _of, + new LibraryIdentifier([_stringIdentifier(name)]), null, - null, - null, - null, - null, - ); -} - -/// An `import` directive in a [FileBuilder]. -class ImportBuilder extends _AbstractCodeBuilder { - static Token _as = new KeywordToken(Keyword.AS, 0); - - /// Create a new `import` directive importing [uri]. - /// - /// Optionally prefix [as]. - factory ImportBuilder(String uri, {String as}) { - var astNode = _createImportDirective()..uri = _stringLit("'$uri'"); - if (as != null) { - astNode - ..asKeyword = _as - ..prefix = _stringId(as); - } - return new ImportBuilder._(astNode); + )); + return new PartBuilder._(astNode); } - ImportBuilder._(ImportDirective astNode) : super._(astNode); - - static ImportDirective _createImportDirective() => new ImportDirective( - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - ); + PartBuilder._(CompilationUnit astNode) : super._(astNode); } diff --git a/pkgs/code_builder/lib/src/builders/method_builder.dart b/pkgs/code_builder/lib/src/builders/method_builder.dart index f43b756ba..33a6fdfd2 100644 --- a/pkgs/code_builder/lib/src/builders/method_builder.dart +++ b/pkgs/code_builder/lib/src/builders/method_builder.dart @@ -11,9 +11,7 @@ part of code_builder; /// the top level and within other methods) via [toFunctionAst]. /// /// To return nothing (`void`), use [MethodBuilder.returnVoid]. -class MethodBuilder implements - CodeBuilder, - ScopeAware { +class MethodBuilder implements CodeBuilder { static Token _abstract = new KeywordToken(Keyword.ABSTRACT, 0); static Token _semicolon = new Token(TokenType.SEMICOLON, 0); static Token _static = new KeywordToken(Keyword.STATIC, 0); @@ -26,25 +24,39 @@ class MethodBuilder implements final List _parameters = []; final List _statements = []; + final bool _isAbstract; + final bool _isStatic; + ExpressionBuilder _returnExpression; TypeBuilder _returnType; /// Create a new method builder, /// /// Optionally set a [returns] type. - factory MethodBuilder({String name, TypeBuilder returns}) { - return new MethodBuilder._(name, returns); + factory MethodBuilder({ + String name, + TypeBuilder returns, + bool abstract: false, + bool static: false, + }) { + return new MethodBuilder._(name, returns, static, abstract); } /// Creates a `void`-returning MethodBuilder with [name]. - factory MethodBuilder.returnVoid([String name]) { - return new MethodBuilder._(name, _typeVoid); + factory MethodBuilder.returnVoid({ + String name, + bool abstract: false, + bool static: false, + }) { + return new MethodBuilder._(name, _typeVoid, static, abstract); } - MethodBuilder._(this._name, this._returnType); - - @override - List get requiredImports => null; + MethodBuilder._( + this._name, + this._returnType, + this._isStatic, + this._isAbstract, + ); /// Lazily adds [annotation]. /// @@ -81,63 +93,57 @@ class MethodBuilder implements /// [toMethodAst]. @override @visibleForTesting - Declaration toAst() => toScopedAst(const Scope.identity()); + Declaration toAst([Scope scope = const Scope.identity()]) => + toFunctionAst(scope); /// Returns a copy-safe [FunctionDeclaration] AST representing current state. - FunctionDeclaration toFunctionAst({Scope scope: const Scope.identity()}) { + FunctionDeclaration toFunctionAst([Scope scope = const Scope.identity()]) { var functionAst = _emptyFunction() - ..metadata.addAll(_annotations.map/**/((a) => a.toAst())) - ..name = _stringId(_name) - ..returnType = _returnType?.toScopedAst(scope); + ..metadata.addAll(_annotations.map/**/((a) => a.toAst(scope))) + ..name = _stringIdentifier(_name) + ..returnType = _returnType?.toAst(scope); if (_returnExpression != null) { functionAst.functionExpression = _returnExpression.toFunctionExpression(); } else { functionAst.functionExpression = new FunctionExpression( null, _emptyParameters(), - _blockBody(_statements.map/**/((s) => s.toAst())), + _blockBody(_statements.map/**/((s) => s.toAst(scope))), ); } if (_parameters.isNotEmpty) { functionAst.functionExpression.parameters.parameters - .addAll(_parameters.map/**/((p) => p.toScopedAst(scope))); + .addAll(_parameters.map/**/((p) => p.toAst(scope))); } return functionAst; } /// Returns a copy-safe [FunctionDeclaration] AST representing current state. - MethodDeclaration toMethodAst({ - bool static: false, - bool canBeAbstract: false, - Scope scope: const Scope.identity(), - }) { + MethodDeclaration toMethodAst([Scope scope = const Scope.identity()]) { var methodAst = _emptyMethod() - ..metadata.addAll(_annotations.map/**/((a) => a.toAst())) - ..name = _stringId(_name) - ..returnType = _returnType?.toScopedAst(scope); - FunctionBody methodBody = _returnExpression?.toFunctionBody(); - if (static) { + ..metadata.addAll(_annotations.map/**/((a) => a.toAst(scope))) + ..name = _stringIdentifier(_name) + ..returnType = _returnType?.toAst(scope); + FunctionBody methodBody = _returnExpression?.toFunctionBody(scope); + if (_isStatic) { methodAst.modifierKeyword = _static; if (methodBody == null) { methodBody = _blockBody(); } } if (methodBody == null) { - methodBody = canBeAbstract + methodBody = _isAbstract ? new EmptyFunctionBody(_semicolon) - : _blockBody(_statements.map/**/((s) => s.toAst())); + : _blockBody(_statements.map/**/((s) => s.toAst(scope))); } if (_parameters.isNotEmpty) { methodAst.parameters.parameters - .addAll(_parameters.map/**/((p) => p.toScopedAst(scope))); + .addAll(_parameters.map/**/((p) => p.toAst(scope))); } methodAst.body = methodBody; return methodAst; } - @override - Declaration toScopedAst(Scope scope) => toFunctionAst(scope: scope); - @override String toString() => 'MethodBuilder ${toAst().toSource()}'; diff --git a/pkgs/code_builder/lib/src/builders/parameter_builder.dart b/pkgs/code_builder/lib/src/builders/parameter_builder.dart index 16466f656..886ca2415 100644 --- a/pkgs/code_builder/lib/src/builders/parameter_builder.dart +++ b/pkgs/code_builder/lib/src/builders/parameter_builder.dart @@ -9,7 +9,7 @@ part of code_builder; /// A parameter is part of a built [MethodBuilder], and can refer to a /// class-member (field) variable (see the `field` property in the /// constructors). -class ParameterBuilder extends ScopeAware { +class ParameterBuilder implements CodeBuilder { static final Token _this = new KeywordToken(Keyword.THIS, 0); final String _name; @@ -104,7 +104,7 @@ class ParameterBuilder extends ScopeAware { } @override - FormalParameter toScopedAst(Scope scope) { + FormalParameter toAst([Scope scope = const Scope.identity()]) { FormalParameter astNode; if (_isField) { astNode = _createFieldFormalParameter(scope); @@ -123,31 +123,15 @@ class ParameterBuilder extends ScopeAware { return astNode; } - static DefaultFormalParameter _createDefaultFormalParameter( - FormalParameter parameter, - bool named, - ExpressionBuilder defaultTo, - Scope scope, - ) { - return new DefaultFormalParameter( - parameter, - named ? ParameterKind.NAMED : ParameterKind.POSITIONAL, - defaultTo != null - ? named ? new Token(TokenType.COLON, 0) : new Token(TokenType.EQ, 0) - : null, - defaultTo?.toAst(), - ); - } - FieldFormalParameter _createFieldFormalParameter(Scope scope) => new FieldFormalParameter( null, null, null, - _type?.toScopedAst(scope), + _type?.toAst(scope), _this, null, - _stringId(_name), + _stringIdentifier(_name), null, null, ); @@ -157,7 +141,23 @@ class ParameterBuilder extends ScopeAware { null, null, null, - _type?.toScopedAst(scope), - _stringId(_name), + _type?.toAst(scope), + _stringIdentifier(_name), ); + + static DefaultFormalParameter _createDefaultFormalParameter( + FormalParameter parameter, + bool named, + ExpressionBuilder defaultTo, + Scope scope, + ) { + return new DefaultFormalParameter( + parameter, + named ? ParameterKind.NAMED : ParameterKind.POSITIONAL, + defaultTo != null + ? named ? new Token(TokenType.COLON, 0) : new Token(TokenType.EQ, 0) + : null, + defaultTo?.toAst(), + ); + } } diff --git a/pkgs/code_builder/lib/src/builders/type_builder.dart b/pkgs/code_builder/lib/src/builders/type_builder.dart index 19025c8b2..cff6f2f43 100644 --- a/pkgs/code_builder/lib/src/builders/type_builder.dart +++ b/pkgs/code_builder/lib/src/builders/type_builder.dart @@ -5,7 +5,7 @@ part of code_builder; /// Build a [TypeName] AST. -class TypeBuilder implements ScopeAware { +class TypeBuilder implements CodeBuilder { final String _identifier; final String _importFrom; @@ -19,13 +19,7 @@ class TypeBuilder implements ScopeAware { : _importFrom = importFrom; @override - List get requiredImports => [_importFrom]; - - @override - TypeName toAst() => toScopedAst(const Scope.identity()); - - @override - TypeName toScopedAst(Scope scope) { + TypeName toAst([Scope scope = const Scope.identity()]) { return new TypeName(scope.getIdentifier(_identifier, _importFrom), null); } } diff --git a/pkgs/code_builder/lib/src/scope.dart b/pkgs/code_builder/lib/src/scope.dart index a96f32665..734ec7de5 100644 --- a/pkgs/code_builder/lib/src/scope.dart +++ b/pkgs/code_builder/lib/src/scope.dart @@ -39,7 +39,7 @@ class _DeduplicatingScope implements Scope { @override Identifier getIdentifier(String symbol, String import) { _imports.add(import); - return _stringId(symbol); + return _stringIdentifier(symbol); } @override @@ -52,7 +52,7 @@ class _IdentityScope implements Scope { const _IdentityScope(); @override - Identifier getIdentifier(String symbol, _) => _stringId(symbol); + Identifier getIdentifier(String symbol, _) => _stringIdentifier(symbol); @override Iterable getImports() => const []; @@ -66,8 +66,8 @@ class _IncrementingScope implements Scope { @override Identifier getIdentifier(String symbol, String import) { var newId = _imports.putIfAbsent(import, () => ++_counter); - return new PrefixedIdentifier(_stringId('_i$newId'), - new Token(TokenType.PERIOD, 0), _stringId(symbol)); + return new PrefixedIdentifier(_stringIdentifier('_i$newId'), + new Token(TokenType.PERIOD, 0), _stringIdentifier(symbol)); } @override diff --git a/pkgs/code_builder/lib/testing/equals_source.dart b/pkgs/code_builder/lib/testing/equals_source.dart index 5c69e4f13..1231cb014 100644 --- a/pkgs/code_builder/lib/testing/equals_source.dart +++ b/pkgs/code_builder/lib/testing/equals_source.dart @@ -8,6 +8,13 @@ import 'package:analyzer/src/dart/ast/token.dart'; import 'package:code_builder/code_builder.dart'; import 'package:matcher/matcher.dart'; +/// Returns identifiers that are just the file name. +/// +/// For example `getIdentifier('Foo', 'package:foo/foo.dart')` would return +/// the identifier "foo.Foo". This isn't safe enough for use in a actual +/// code-gen but makes it easy to debug issues in our tests. +const Scope simpleNameScope = const _SimpleNameScope(); + /// Returns a [Matcher] that checks a [CodeBuilder] versus [source]. /// /// On failure, uses the default string matcher to show a detailed diff between @@ -19,7 +26,11 @@ import 'package:matcher/matcher.dart'; /// /// If you have code that is not consider a valid compilation unit (like an /// expression, you should flip [format] to `false`). -Matcher equalsSource(String source, {bool format: true, Scope scope}) { +Matcher equalsSource( + String source, { + bool format: true, + Scope scope: const Scope.identity(), +}) { return new _EqualsSource( scope, format ? dartfmt(source) : source, @@ -31,35 +42,6 @@ Identifier _stringId(String s) { return new SimpleIdentifier(new StringToken(TokenType.STRING, s, 0)); } -/// Returns identifiers that are just the file name. -/// -/// For example `getIdentifier('Foo', 'package:foo/foo.dart')` would return -/// the identifier "foo.Foo". This isn't safe enough for use in a actual -/// code-gen but makes it easy to debug issues in our tests. -const Scope simpleNameScope = const _SimpleNameScope(); - -class _SimpleNameScope implements Scope { - const _SimpleNameScope(); - - @override - Identifier getIdentifier(String symbol, String importUri) { - var fileWithoutExt = - Uri.parse(importUri).pathSegments.last.split('.').first; - return new PrefixedIdentifier( - _stringId(fileWithoutExt), - new Token(TokenType.PERIOD, 0), - _stringId(symbol), - ); - } - - @override - Iterable getImports() => const []; -} - -// Delegates to the default matcher (which delegates further). -// -// Would be nice to just use more of package:matcher directly: -// https://github.com/dart-lang/matcher/issues/36 class _EqualsSource extends Matcher { final Scope _scope; final String _source; @@ -80,9 +62,11 @@ class _EqualsSource extends Matcher { bool verbose, ) { if (item is CodeBuilder) { + var origin = _formatAst(item); + print(origin); return equals(_source).describeMismatch( - _formatAst(item), - mismatchDescription, + origin, + mismatchDescription.addDescriptionOf(origin), matchState, verbose, ); @@ -91,25 +75,42 @@ class _EqualsSource extends Matcher { } } - String _formatAst(CodeBuilder builder) { - AstNode astNode; - if (_scope != null && builder is ScopeAware) { - astNode = builder.toScopedAst(_scope); - } else { - astNode = builder.toAst(); + @override + bool matches(item, _) { + if (item is CodeBuilder) { + return _formatAst(item) == _source; } + return false; + } + + String _formatAst(CodeBuilder builder) { + var astNode = builder.toAst(_scope); if (_isFormatted) { return prettyToSource(astNode); } else { return astNode.toSource(); } } +} + +// Delegates to the default matcher (which delegates further). +// +// Would be nice to just use more of package:matcher directly: +// https://github.com/dart-lang/matcher/issues/36 +class _SimpleNameScope implements Scope { + const _SimpleNameScope(); @override - bool matches(item, _) { - if (item is CodeBuilder) { - return _formatAst(item) == _source; - } - return false; + Identifier getIdentifier(String symbol, String importUri) { + var fileWithoutExt = + Uri.parse(importUri).pathSegments.last.split('.').first; + return new PrefixedIdentifier( + _stringId(fileWithoutExt), + new Token(TokenType.PERIOD, 0), + _stringId(symbol), + ); } + + @override + Iterable getImports() => const []; } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index d3f7b3227..ee334a71f 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 0.1.0-dev+2 +version: 0.1.1-dev description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/class_builder_test.dart b/pkgs/code_builder/test/builders/class_builder_test.dart index ac4cf9168..e20cb54d9 100644 --- a/pkgs/code_builder/test/builders/class_builder_test.dart +++ b/pkgs/code_builder/test/builders/class_builder_test.dart @@ -14,28 +14,32 @@ void main() { test('should emit an abstract class', () { expect( - new ClassBuilder('Animal', abstract: true), + new ClassBuilder.asAbstract('Animal'), equalsSource('abstract class Animal {}'), ); }); test('should emit a class extending another class', () { expect( - new ClassBuilder('Animal', extend: 'Organism'), + new ClassBuilder('Animal', extend: new TypeBuilder('Organism')), equalsSource('class Animal extends Organism {}'), ); }); test('should emit a class implementing another class', () { expect( - new ClassBuilder('Animal', implement: ['Delicious']), + new ClassBuilder('Animal', implement: [new TypeBuilder('Delicious')]), equalsSource('class Animal implements Delicious {}'), ); }); test('should emit a class extending and mixing in another class', () { expect( - new ClassBuilder('Animal', extend: 'Organism', mixin: ['Breathing']), + new ClassBuilder( + 'Animal', + extend: new TypeBuilder('Organism'), + mixin: [new TypeBuilder('Breathing')], + ), equalsSource('class Animal extends Organism with Breathing {}'), ); }); @@ -57,9 +61,9 @@ void main() { test('should emit an abstract class with an abstract method', () { expect( - new ClassBuilder('Animal', abstract: true) + new ClassBuilder.asAbstract('Animal') ..addMethod( - new MethodBuilder.returnVoid('eat'), + new MethodBuilder.returnVoid(name: 'eat', abstract: true), ), equalsSource(r''' abstract class Animal { @@ -75,9 +79,9 @@ void main() { ..addMethod( new MethodBuilder( name: 'create', + static: true, returns: new TypeBuilder('Animal'), )..setExpression(literalNull), - static: true, ), equalsSource(r''' class Animal { @@ -116,7 +120,7 @@ void main() { }); test('default constructor', () { - clazz.addConstructor(new ConstructorBuilder.initializeFields()); + clazz.addConstructor(new ConstructorBuilder()); expect( clazz, equalsSource( @@ -129,8 +133,7 @@ void main() { }); test('default const constructor', () { - clazz.addConstructor( - new ConstructorBuilder.initializeFields(constant: true)); + clazz.addConstructor(new ConstructorBuilder.isConst()); expect( clazz, equalsSource( @@ -143,10 +146,13 @@ void main() { }); test('initializing fields', () { - clazz.addConstructor(new ConstructorBuilder.initializeFields( - positionalArguments: ['a'], - optionalArguments: ['b'], - )); + clazz.addConstructor(new ConstructorBuilder() + ..addParameter( + new ParameterBuilder('a', field: true), + ) + ..addParameter( + new ParameterBuilder.optional('b', field: true), + )); expect( clazz, equalsSource( diff --git a/pkgs/code_builder/test/builders/file_builder_test.dart b/pkgs/code_builder/test/builders/file_builder_test.dart index 98e21360f..a38092fbf 100644 --- a/pkgs/code_builder/test/builders/file_builder_test.dart +++ b/pkgs/code_builder/test/builders/file_builder_test.dart @@ -12,8 +12,8 @@ void main() { }); test('should emit a file with a library directive', () { - expect( - new LibraryBuilder('code_builder'), equalsSource('library code_builder;')); + expect(new LibraryBuilder('code_builder'), + equalsSource('library code_builder;')); }); test('should emit a file with a part of directive', () { diff --git a/pkgs/code_builder/test/builders/method_builder_test.dart b/pkgs/code_builder/test/builders/method_builder_test.dart index e5696573a..7f6f3484d 100644 --- a/pkgs/code_builder/test/builders/method_builder_test.dart +++ b/pkgs/code_builder/test/builders/method_builder_test.dart @@ -10,7 +10,7 @@ import 'package:test/test.dart'; void main() { test('should emit a simple "void" method', () { expect( - new MethodBuilder.returnVoid('main'), + new MethodBuilder.returnVoid(name: 'main'), equalsSource('void main() {}'), ); }); @@ -27,10 +27,12 @@ void main() { new MethodBuilder( name: 'toFoo', returns: new TypeBuilder('Foo', importFrom: 'package:foo/foo.dart'), - )..addParameter(new ParameterBuilder( - 'context', - type: new TypeBuilder('Context', importFrom: 'package:bar/bar.dart'), - )), + ) + ..addParameter(new ParameterBuilder( + 'context', + type: + new TypeBuilder('Context', importFrom: 'package:bar/bar.dart'), + )), equalsSource( r''' foo.Foo toFoo(bar.Context context) {} @@ -117,7 +119,7 @@ void main() { group('with statements', () { test('should work with an expression', () { expect( - new MethodBuilder.returnVoid('main') + new MethodBuilder.returnVoid(name: 'main') ..addStatement(const LiteralString('Hello World').toStatement()), equalsSource(r''' void main() { @@ -129,7 +131,7 @@ void main() { test('should work invoking an expression', () { expect( - new MethodBuilder.returnVoid('main') + new MethodBuilder.returnVoid(name: 'main') ..addStatement( new ExpressionBuilder.invoke('print', positional: [ const LiteralString('Hello World').invokeSelf( @@ -151,7 +153,7 @@ void main() { MethodBuilder method; setUp(() { - method = new MethodBuilder.returnVoid('main'); + method = new MethodBuilder.returnVoid(name: 'main'); }); test('single required parameter', () { diff --git a/pkgs/code_builder/test/integration_test.dart b/pkgs/code_builder/test/integration_test.dart index 4571d66e1..1791796a9 100644 --- a/pkgs/code_builder/test/integration_test.dart +++ b/pkgs/code_builder/test/integration_test.dart @@ -10,29 +10,87 @@ import 'package:test/test.dart'; // Closely mirrors the API you would need to do dependency injection :) void main() { test('Emits a complex generated file', () { - var clazz = new ClassBuilder(r'Injector', implement: ['App']) + var clazz = + new ClassBuilder(r'Injector', implement: [new TypeBuilder('App')]) + ..addField(new FieldBuilder.isFinal( + '_module', + type: const TypeBuilder('Module'), + )) + ..addConstructor(new ConstructorBuilder() + ..addParameter(new ParameterBuilder('_module', field: true))) + ..addMethod( + new MethodBuilder( + name: 'getThing', + returns: const TypeBuilder('Thing'), + ) + ..addAnnotation(atOverride) + ..setExpression(new ExpressionBuilder.invokeNew( + const TypeBuilder('Thing'), + positional: [ + new ExpressionBuilder.invoke('_module.getDep1'), + new ExpressionBuilder.invoke('_module.getDep2'), + ], + )), + ); + var lib = new LibraryBuilder() + ..addDirective( + new ImportBuilder('app.dart'), + ) + ..addDeclaration(clazz); + expect( + lib, + equalsSource( + r''' + import 'app.dart'; + + class Injector implements App { + final Module _module; + + Injector(this._module); + + @override + Thing getThing() => new Thing(_module.getDep1(), _module.getDep2()); + } + ''', + ), + ); + }); + + test('Emits a complex generated file with scoping applied', () { + var clazz = new ClassBuilder( + r'Injector', + implement: [new TypeBuilder('App', importFrom: 'package:app/app.dart')], + ) ..addField(new FieldBuilder.isFinal( '_module', - type: const TypeBuilder('Module'), - )) - ..addConstructor(new ConstructorBuilder.initializeFields( - positionalArguments: ['_module'], + type: const TypeBuilder( + 'Module', + importFrom: 'package:app/app.dart', + ), )) + ..addConstructor(new ConstructorBuilder() + ..addParameter(new ParameterBuilder('_module', field: true))) ..addMethod( new MethodBuilder( name: 'getThing', - returns: const TypeBuilder('Thing'), + returns: const TypeBuilder( + 'Thing', + importFrom: 'package:app/thing.dart', + ), ) ..addAnnotation(atOverride) - ..setExpression(new ExpressionBuilder.invoke( - 'new Thing', + ..setExpression(new ExpressionBuilder.invokeNew( + const TypeBuilder( + 'Thing', + importFrom: 'package:app/thing.dart', + ), positional: [ new ExpressionBuilder.invoke('_module.getDep1'), new ExpressionBuilder.invoke('_module.getDep2'), ], )), ); - var lib = new LibraryBuilder() + var lib = new LibraryBuilder.scope() ..addDirective( new ImportBuilder('app.dart'), ) @@ -42,14 +100,18 @@ void main() { equalsSource( r''' import 'app.dart'; + import 'package:app/app.dart' as _i1; + import 'dart:core' as _i2; + import 'package:app/thing.dart' as _i3; - class Injector implements App { - final Module _module; + + class Injector implements _i1.App { + final _i1.Module _module; Injector(this._module); - @override - Thing getThing() => new Thing(_module.getDep1(), _module.getDep2()); + @_i2.override + _i3.Thing getThing() => new _i3.Thing(_module.getDep1(), _module.getDep2()); } ''', ), diff --git a/pkgs/code_builder/test/scope_test.dart b/pkgs/code_builder/test/scope_test.dart index 3f45a2f2f..1d16b9ee1 100644 --- a/pkgs/code_builder/test/scope_test.dart +++ b/pkgs/code_builder/test/scope_test.dart @@ -9,17 +9,20 @@ void main() { setUp(() => scope = const Scope.identity()); test('should do nothing', () { - var identifiers = [ + var identifiers = [ scope.getIdentifier('Foo', 'package:foo/foo.dart'), scope.getIdentifier('Bar', 'package:foo/foo.dart'), scope.getIdentifier('Baz', 'package:baz/baz.dart'), ].map/**/((i) => i.toSource()); - expect(identifiers, [ - 'Foo', - 'Bar', - 'Baz', - ],); + expect( + identifiers, + [ + 'Foo', + 'Bar', + 'Baz', + ], + ); expect(scope.getImports(), isEmpty); }); @@ -31,22 +34,28 @@ void main() { setUp(() => scope = new Scope.dedupe()); test('should just output non-prefixed and de-duplicate imports', () { - var identifiers = [ + var identifiers = [ scope.getIdentifier('Foo', 'package:foo/foo.dart'), scope.getIdentifier('Bar', 'package:foo/foo.dart'), scope.getIdentifier('Baz', 'package:baz/baz.dart'), ].map/**/((i) => i.toSource()); - expect(identifiers, [ - 'Foo', - 'Bar', - 'Baz', - ],); + expect( + identifiers, + [ + 'Foo', + 'Bar', + 'Baz', + ], + ); - expect(scope.getImports().map/**/((i) => i.toAst().toSource()), [ - r"import 'package:foo/foo.dart';", - r"import 'package:baz/baz.dart';", - ],); + expect( + scope.getImports().map/**/((i) => i.toAst().toSource()), + [ + r"import 'package:foo/foo.dart';", + r"import 'package:baz/baz.dart';", + ], + ); }); }); @@ -56,22 +65,28 @@ void main() { setUp(() => scope = new Scope()); test('should out prefixed with a counter', () { - var identifiers = [ + var identifiers = [ scope.getIdentifier('Foo', 'package:foo/foo.dart'), scope.getIdentifier('Bar', 'package:foo/foo.dart'), scope.getIdentifier('Baz', 'package:baz/baz.dart'), ].map/**/((i) => i.toSource()); - expect(identifiers, [ - '_i1.Foo', - '_i1.Bar', - '_i2.Baz', - ],); + expect( + identifiers, + [ + '_i1.Foo', + '_i1.Bar', + '_i2.Baz', + ], + ); - expect(scope.getImports().map/**/((i) => i.toAst().toSource()), [ - r"import 'package:foo/foo.dart' as _i1;", - r"import 'package:baz/baz.dart' as _i2;", - ],); + expect( + scope.getImports().map/**/((i) => i.toAst().toSource()), + [ + r"import 'package:foo/foo.dart' as _i1;", + r"import 'package:baz/baz.dart' as _i2;", + ], + ); }); }); } From 2bc837d642e111249f5fa7df7eee96eb5bd52c1f Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 19 Sep 2016 09:55:12 -0700 Subject: [PATCH 012/271] Cleanup: Make all ASTs lazy (no _AbstractCodeBuilder) (dart-lang/code_builder#12) * Make all builders lazy, remove AST cloning. * Fix breakages due to bad refactor of FileBuilder * Small pubspec increment * Update pubspec to allow pub publish. * Add headers, upstream analyzer patch API * Address comments. * Fix outstanding lints. --- pkgs/code_builder/README.md | 66 +++++++-- pkgs/code_builder/lib/code_builder.dart | 21 +-- pkgs/code_builder/lib/src/analyzer_patch.dart | 65 +++++++++ .../lib/src/builders/class_builder.dart | 3 +- .../lib/src/builders/constructor_builder.dart | 6 +- .../lib/src/builders/expression_builder.dart | 9 +- .../lib/src/builders/file_builder.dart | 127 +++++++++--------- .../lib/src/builders/statement_builder.dart | 24 ++-- pkgs/code_builder/lib/src/pretty_printer.dart | 4 +- pkgs/code_builder/lib/src/scope.dart | 6 +- pkgs/code_builder/pubspec.yaml | 12 +- .../test/builders/file_builder_test.dart | 2 +- pkgs/code_builder/test/integration_test.dart | 7 +- pkgs/code_builder/test/scope_test.dart | 4 + 14 files changed, 234 insertions(+), 122 deletions(-) create mode 100644 pkgs/code_builder/lib/src/analyzer_patch.dart diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index d9659906d..334a4e038 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -3,20 +3,35 @@ [![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) -Code builder is a fluent Dart API for generating valid Dart source code. +`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 generation was traditionally done through a series of +package-specific string concatenations which usually results in messy +and sometimes invalid Dart code that is not easily readable and is very +difficult to refactor. -Code builder uses the [analyzer](analyzer) package to create real Dart +`code_builder` uses the [analyzer](analyzer) package to create real Dart language ASTs, which, while not guaranteed to be correct, always follows the analyzer's own understood format. [analyzer]: https://pub.dartlang.org/packages/analyzer -Code builder also adds a more narrow and user-friendly API. For example -creating a class with a method is an easy affair: +## Experimental + +While `code_builder` is considered *stable*, the APIs are subject to +frequent breaking change - a number of Dart language features are not +yet implemented that make it unsuitable for all forms of code +generation. + +**Contributions are [welcome][welcome]!** + +[welcome]: CONTRIBUTING.md + +## Usage + +Code builder has a narrow and user-friendly API. + +For example creating a class with a method: ```dart new ClassBuilder('Animal', extends: 'Organism') @@ -32,4 +47,39 @@ class Animal extends Organism { } ``` -This package is in development and APIs are subject to frequent change. +Have a complicated set of dependencies for your generated code? +`code_builder` supports automatic scoping of your ASTs to automatically +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', + ), + ))); +``` + +Outputs: +```dart +import 'package:thing/thing.dart' as _i1; +import 'package:thing/alternative.dart' as _i2; + +_i1.Thing doThing() {} +_i2.Thing doOtherThing(_i1.Thing thing) {} +``` diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index ab48ab7f6..2b3d189fc 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -34,6 +34,8 @@ import 'package:analyzer/src/dart/ast/token.dart'; import 'package:dart_style/dart_style.dart'; import 'package:meta/meta.dart'; +import 'src/analyzer_patch.dart'; + part 'src/builders/annotation_builder.dart'; part 'src/builders/class_builder.dart'; part 'src/builders/constructor_builder.dart'; @@ -54,11 +56,6 @@ final DartFormatter _dartfmt = new DartFormatter(); @visibleForTesting String dartfmt(String source) => _dartfmt.format(source); -// Creates a deep copy of an AST node. -AstNode/*=E*/ _cloneAst/**/(AstNode/*=E*/ astNode) { - return new AstCloner().cloneNode/**/(astNode); -} - Identifier _stringIdentifier(String s) { return new SimpleIdentifier(new StringToken(TokenType.STRING, s, 0)); } @@ -74,17 +71,3 @@ abstract class CodeBuilder { /// Uses [scope] to output an AST re-written to use appropriate prefixes. A toAst([Scope scope = const Scope.identity()]); } - -@Deprecated('Builders are all becoming lazy') -abstract class _AbstractCodeBuilder extends CodeBuilder { - final A _astNode; - - _AbstractCodeBuilder._(this._astNode); - - /// Returns a copy-safe [AstNode] representing the current builder state. - @override - A toAst([_]) => _cloneAst/**/(_astNode); - - @override - String toString() => '$runtimeType: ${_astNode.toSource()}'; -} diff --git a/pkgs/code_builder/lib/src/analyzer_patch.dart b/pkgs/code_builder/lib/src/analyzer_patch.dart new file mode 100644 index 000000000..5b27d772e --- /dev/null +++ b/pkgs/code_builder/lib/src/analyzer_patch.dart @@ -0,0 +1,65 @@ +// 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. + +import 'package:analyzer/src/generated/java_core.dart'; + +/// Implements both old-API [PrintWriter] and new-API [StringBuffer]. +/// +/// This makes it easier to re-use our `pretty_printer` until analyzer updates. +class PrintBuffer implements PrintWriter, StringBuffer { + final StringBuffer _impl = new StringBuffer(); + + @override + void clear() {} + + @override + bool get isEmpty => _impl.isEmpty; + + @override + bool get isNotEmpty => _impl.isNotEmpty; + + @override + int get length => _impl.length; + + @override + void newLine() { + _impl.writeln(); + } + + @override + void print(x) { + _impl.write(x); + } + + @override + void printf(String fmt, List args) => throw new UnimplementedError(); + + @override + void println(String s) { + _impl.writeln(s); + } + + @override + void write(Object obj) { + _impl.write(obj); + } + + @override + void writeAll(Iterable objects, [String separator = ""]) { + _impl.writeAll(objects); + } + + @override + void writeCharCode(int charCode) { + _impl.writeCharCode(charCode); + } + + @override + void writeln([Object obj = ""]) { + _impl.writeln(obj); + } + + @override + String toString() => _impl.toString(); +} diff --git a/pkgs/code_builder/lib/src/builders/class_builder.dart b/pkgs/code_builder/lib/src/builders/class_builder.dart index afb3cbc12..df9b3ab94 100644 --- a/pkgs/code_builder/lib/src/builders/class_builder.dart +++ b/pkgs/code_builder/lib/src/builders/class_builder.dart @@ -25,7 +25,7 @@ class ClassBuilder implements CodeBuilder { /// Create a new builder for a `class` named [name]. /// /// Optionally, define another class to [extend] or classes to either - /// [implement] or [mixin]. You may also define a `class` as [abstract]. + /// [implement] or [mixin]. factory ClassBuilder( String name, { TypeBuilder extend, @@ -40,6 +40,7 @@ class ClassBuilder implements CodeBuilder { new List.unmodifiable(mixin), ); + /// Create a new builder for an `abstract class` named [name]. factory ClassBuilder.asAbstract(String name, {TypeBuilder extend, Iterable implement: const [], diff --git a/pkgs/code_builder/lib/src/builders/constructor_builder.dart b/pkgs/code_builder/lib/src/builders/constructor_builder.dart index cf01588ab..e53e053fc 100644 --- a/pkgs/code_builder/lib/src/builders/constructor_builder.dart +++ b/pkgs/code_builder/lib/src/builders/constructor_builder.dart @@ -15,17 +15,21 @@ class ConstructorBuilder implements CodeBuilder { final String _name; final List _parameters = []; + /// Create a new builder for a constructor, optionally with a [name]. factory ConstructorBuilder([String name]) { return new ConstructorBuilder._(false, name); } + /// Create a new builder for a constructor, optionally with a [name]. + /// + /// The resulting constructor will be `const`. factory ConstructorBuilder.isConst([String name]) { return new ConstructorBuilder._(true, name); } ConstructorBuilder._(this._isConstant, this._name); - /// Lazily adds [parameter]. + /// Lazily adds [builder]. /// /// When the method is emitted as an AST, [ParameterBuilder.toAst] is used. void addParameter(ParameterBuilder builder) { diff --git a/pkgs/code_builder/lib/src/builders/expression_builder.dart b/pkgs/code_builder/lib/src/builders/expression_builder.dart index 823e00419..1baea0122 100644 --- a/pkgs/code_builder/lib/src/builders/expression_builder.dart +++ b/pkgs/code_builder/lib/src/builders/expression_builder.dart @@ -76,7 +76,7 @@ ExpressionBuilder _invokeSelfImpl( abstract class ExpressionBuilder implements CodeBuilder { /// Invoke [name] (which should be available in the local scope). /// - /// Optionally specify [positional] and [named] arguments. + /// May specify [positional] and [named] arguments. factory ExpressionBuilder.invoke( String name, { String importFrom, @@ -91,6 +91,9 @@ abstract class ExpressionBuilder implements CodeBuilder { ); } + /// Invoke the 'new' operator on [type]. + /// + /// May use a [name] of a constructor and [positional] and [named] arguments. factory ExpressionBuilder.invokeNew( TypeBuilder type, { String name, @@ -247,7 +250,7 @@ class _InvokeExpression extends ExpressionBuilder { } @override - StatementBuilder toStatement() => new StatementBuilder.fromExpression(this); + StatementBuilder toStatement() => new _ExpressionStatementBuilder(this); ArgumentList _getArgumentList(Scope scope) { return new ArgumentList( @@ -289,7 +292,7 @@ abstract class _LiteralExpression _asFunctionExpression(this, scope); @override - StatementBuilder toStatement() => new StatementBuilder.fromExpression(this); + StatementBuilder toStatement() => new _ExpressionStatementBuilder(this); } class _LiteralNull extends _LiteralExpression { diff --git a/pkgs/code_builder/lib/src/builders/file_builder.dart b/pkgs/code_builder/lib/src/builders/file_builder.dart index 8e3c026df..3b65df3ff 100644 --- a/pkgs/code_builder/lib/src/builders/file_builder.dart +++ b/pkgs/code_builder/lib/src/builders/file_builder.dart @@ -13,14 +13,18 @@ CompilationUnit _emptyCompilationUnit() => new CompilationUnit( ); /// An `export` directive in a [LibraryBuilder]. -class ExportBuilder extends _AbstractCodeBuilder { +class ExportBuilder implements CodeBuilder { + final String _uri; + /// Create a new `export` directive exporting [uri]. - factory ExportBuilder(String uri) { - var astNode = _createExportDirective()..uri = _stringLiteral("'$uri'"); - return new ExportBuilder._(astNode); - } + factory ExportBuilder(String uri) = ExportBuilder._; + + const ExportBuilder._(this._uri); - ExportBuilder._(ExportDirective astNode) : super._(astNode); + @override + ExportDirective toAst([_]) { + return _createExportDirective()..uri = _stringLiteral("'$_uri'"); + } static ExportDirective _createExportDirective() => new ExportDirective( null, @@ -36,33 +40,41 @@ class ExportBuilder extends _AbstractCodeBuilder { /// Builds files of Dart source code. /// /// See [LibraryBuilder] and [PartBuilder] for concrete implementations. -abstract class FileBuilder extends _AbstractCodeBuilder { - FileBuilder._(CompilationUnit astNode) : super._(astNode); +abstract class FileBuilder implements CodeBuilder { + final List> _declarations = + >[]; + + FileBuilder._(); /// Adds [declaration]'s resulting AST to the source. void addDeclaration(CodeBuilder declaration) { - _astNode.declarations.add(declaration.toAst()); + _declarations.add(declaration); } + + @override + @mustCallSuper + CompilationUnit toAst([Scope scope = const Scope.identity()]) => + _emptyCompilationUnit() + ..declarations + .addAll(_declarations.map/**/((d) => d.toAst(scope))); } /// An `import` directive in a [FileBuilder]. -class ImportBuilder extends _AbstractCodeBuilder { - static Token _as = new KeywordToken(Keyword.AS, 0); +class ImportBuilder implements CodeBuilder { + final String _uri; + final String _prefix; /// Create a new `import` directive importing [uri]. /// - /// Optionally prefix [as]. - factory ImportBuilder(String uri, {String as}) { - var astNode = _createImportDirective()..uri = _stringLiteral("'$uri'"); - if (as != null) { - astNode - ..asKeyword = _as - ..prefix = _stringIdentifier(as); - } - return new ImportBuilder._(astNode); - } + /// Optionally prefix [prefix]. + const factory ImportBuilder(String uri, {String prefix}) = ImportBuilder._; + + const ImportBuilder._(this._uri, {String prefix}) : _prefix = prefix; - ImportBuilder._(ImportDirective astNode) : super._(astNode); + @override + ImportDirective toAst([_]) => _createImportDirective() + ..uri = _stringLiteral("'$_uri'") + ..prefix = _prefix != null ? _stringIdentifier(_prefix) : null; static ImportDirective _createImportDirective() => new ImportDirective( null, @@ -82,57 +94,47 @@ class ImportBuilder extends _AbstractCodeBuilder { class LibraryBuilder extends FileBuilder { static final Token _library = new KeywordToken(Keyword.LIBRARY, 0); + final String _name; final Scope _scope; + final List> _directives = >[]; + /// Create a new standalone Dart library, optionally with a [name]. factory LibraryBuilder([String name]) { - var astNode = _emptyCompilationUnit(); - if (name != null) { - astNode.directives.add(new LibraryDirective( - null, - null, - _library, - new LibraryIdentifier([_stringIdentifier(name)]), - null, - )); - } - return new LibraryBuilder._(astNode, const Scope.identity()); + return new LibraryBuilder._(name, const Scope.identity()); } /// Create a new standalone Dart library, optionally with a [name]. /// - /// As references are added in the library that implements [ScopeAware] + /// As references are added in the library that implements [CodeBuilder] /// they are re-written to avoid collisions and the imports are automatically /// included at the top with optional prefixes. factory LibraryBuilder.scope({String name, Scope scope}) { - var astNode = _emptyCompilationUnit(); - if (name != null) { - astNode.directives.add(new LibraryDirective( - null, - null, - _library, - new LibraryIdentifier([_stringIdentifier(name)]), - null, - )); - } - return new LibraryBuilder._(astNode, scope ?? new Scope()); + return new LibraryBuilder._(name, scope ?? new Scope()); } - LibraryBuilder._(CompilationUnit astNode, this._scope) : super._(astNode); - - @override - void addDeclaration(CodeBuilder declaration) { - _astNode.declarations.add(declaration.toAst(_scope)); - } + LibraryBuilder._(this._name, this._scope) : super._(); /// Adds [directive]'s resulting AST to the source. void addDirective(CodeBuilder directive) { - _astNode.directives.add(directive.toAst()); + _directives.add(directive); } @override CompilationUnit toAst([_]) { - var originalAst = super.toAst(); + var originalAst = super.toAst(_scope); + if (_name != null) { + originalAst.directives.add( + new LibraryDirective( + null, + null, + _library, + new LibraryIdentifier([_stringIdentifier(_name)]), + null, + ), + ); + } + originalAst.directives..addAll(_directives.map((d) => d.toAst())); originalAst.directives..addAll(_scope.getImports().map((i) => i.toAst())); return originalAst; } @@ -143,19 +145,24 @@ class PartBuilder extends FileBuilder { static final Token _part = new KeywordToken(Keyword.PART, 0); static final Token _of = new StringToken(TokenType.KEYWORD, 'of', 0); + final String _name; + /// Create a new `part of` source file. - factory PartBuilder(String name) { - var astNode = _emptyCompilationUnit(); - astNode.directives.add(new PartOfDirective( + factory PartBuilder(String name) = PartBuilder._; + + PartBuilder._(this._name) : super._(); + + @override + CompilationUnit toAst([Scope scope = const Scope.identity()]) { + var originalAst = super.toAst(); + originalAst.directives.add(new PartOfDirective( null, null, _part, _of, - new LibraryIdentifier([_stringIdentifier(name)]), + new LibraryIdentifier([_stringIdentifier(_name)]), null, )); - return new PartBuilder._(astNode); + return originalAst; } - - PartBuilder._(CompilationUnit astNode) : super._(astNode); } diff --git a/pkgs/code_builder/lib/src/builders/statement_builder.dart b/pkgs/code_builder/lib/src/builders/statement_builder.dart index e7d0db959..eb02e423f 100644 --- a/pkgs/code_builder/lib/src/builders/statement_builder.dart +++ b/pkgs/code_builder/lib/src/builders/statement_builder.dart @@ -6,17 +6,19 @@ part of code_builder; /// Builds a [Statement] AST. abstract class StatementBuilder implements CodeBuilder { - /// Returns a new [StatementBuilder] from the result of [ExpressionBuilder]. - factory StatementBuilder.fromExpression(ExpressionBuilder builder) { - return new _ExpressionStatementBuilder(new ExpressionStatement( - builder.toAst(), - _semicolon, - )); - } + StatementBuilder._sealed(); } -class _ExpressionStatementBuilder - extends _AbstractCodeBuilder - implements StatementBuilder { - _ExpressionStatementBuilder(ExpressionStatement astNode) : super._(astNode); +class _ExpressionStatementBuilder implements StatementBuilder { + final ExpressionBuilder _expression; + + _ExpressionStatementBuilder(this._expression); + + @override + Statement toAst([Scope scope = const Scope.identity()]) { + return new ExpressionStatement( + _expression.toAst(scope), + new Token(TokenType.SEMICOLON, 0), + ); + } } diff --git a/pkgs/code_builder/lib/src/pretty_printer.dart b/pkgs/code_builder/lib/src/pretty_printer.dart index 31bbc16ae..e1036e0b7 100644 --- a/pkgs/code_builder/lib/src/pretty_printer.dart +++ b/pkgs/code_builder/lib/src/pretty_printer.dart @@ -11,7 +11,7 @@ part of code_builder; /// This is the _recommended_ output (but not required) when comparing ASTs /// to expected golden files/text blobs. String prettyToSource(AstNode astNode) { - var buffer = new StringBuffer(); + var buffer = new PrintBuffer(); var visitor = new _PrettyToSourceVisitor(buffer); astNode.accept(visitor); return dartfmt(buffer.toString()); @@ -23,7 +23,7 @@ class _PrettyToSourceVisitor extends ToSourceVisitor { // https://github.com/dart-lang/sdk/issues/27301 final StringBuffer _buffer; - _PrettyToSourceVisitor(StringBuffer buffer) + _PrettyToSourceVisitor(PrintBuffer buffer) : _buffer = buffer, super(buffer); diff --git a/pkgs/code_builder/lib/src/scope.dart b/pkgs/code_builder/lib/src/scope.dart index 734ec7de5..ab5f38390 100644 --- a/pkgs/code_builder/lib/src/scope.dart +++ b/pkgs/code_builder/lib/src/scope.dart @@ -1,3 +1,7 @@ +// 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. + part of code_builder; /// Determines an [Identifier] deppending on where it appears. @@ -73,6 +77,6 @@ class _IncrementingScope implements Scope { @override Iterable getImports() { return _imports.keys.map/* new ImportBuilder(i, as: '_i${_imports[i]}')); + (i) => new ImportBuilder(i, prefix: '_i${_imports[i]}')); } } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index ee334a71f..2920693fc 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 0.1.1-dev +version: 0.1.2 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -8,16 +8,10 @@ environment: sdk: '>=1.9.1 <2.0.0' dependencies: - analyzer: - dart_style: + analyzer: '>=0.28.1 <0.29.0' + dart_style: ^0.2.10 matcher: ^0.12.0+2 meta: ^1.0.2 dev_dependencies: test: ^0.12.0 - -dependency_overrides: - # As of 9-13-2016, this is the internal SHA. This means we can't publish to - # pub, but at least can develop with code that will work out of the box on - # the internal repo. - analyzer: 0.29.0-alpha.0 diff --git a/pkgs/code_builder/test/builders/file_builder_test.dart b/pkgs/code_builder/test/builders/file_builder_test.dart index a38092fbf..8329b979e 100644 --- a/pkgs/code_builder/test/builders/file_builder_test.dart +++ b/pkgs/code_builder/test/builders/file_builder_test.dart @@ -32,7 +32,7 @@ void main() { test('should emit an import directive and a prefix', () { expect( - new ImportBuilder('package:foo/foo.dart', as: 'foo'), + new ImportBuilder('package:foo/foo.dart', prefix: 'foo'), equalsSource("import 'package:foo/foo.dart' as foo;"), ); }); diff --git a/pkgs/code_builder/test/integration_test.dart b/pkgs/code_builder/test/integration_test.dart index 1791796a9..f7565a861 100644 --- a/pkgs/code_builder/test/integration_test.dart +++ b/pkgs/code_builder/test/integration_test.dart @@ -90,16 +90,11 @@ void main() { ], )), ); - var lib = new LibraryBuilder.scope() - ..addDirective( - new ImportBuilder('app.dart'), - ) - ..addDeclaration(clazz); + var lib = new LibraryBuilder.scope()..addDeclaration(clazz); expect( lib, equalsSource( r''' - import 'app.dart'; import 'package:app/app.dart' as _i1; import 'dart:core' as _i2; import 'package:app/thing.dart' as _i3; diff --git a/pkgs/code_builder/test/scope_test.dart b/pkgs/code_builder/test/scope_test.dart index 1d16b9ee1..a75532a89 100644 --- a/pkgs/code_builder/test/scope_test.dart +++ b/pkgs/code_builder/test/scope_test.dart @@ -1,3 +1,7 @@ +// 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. + import 'package:analyzer/analyzer.dart'; import 'package:code_builder/code_builder.dart'; import 'package:test/test.dart'; From 1368510c5cabbb8a327ffd18159556a8619fd8b6 Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Fri, 23 Sep 2016 14:43:58 -0700 Subject: [PATCH 013/271] Add assignment expressions. (dart-lang/code_builder#13) Add assignment expressions. Assignment expressions can be either normal or null-aware (using ??=). This commit also does some cleanup regarding Tokens, moving all Token literals to a shared file. --- pkgs/code_builder/lib/code_builder.dart | 11 +-- .../lib/src/builders/class_builder.dart | 13 +-- .../lib/src/builders/constructor_builder.dart | 7 +- .../lib/src/builders/expression_builder.dart | 80 ++++++++++------- .../lib/src/builders/field_builder.dart | 17 ++-- .../lib/src/builders/file_builder.dart | 11 +-- .../lib/src/builders/method_builder.dart | 16 ++-- .../lib/src/builders/parameter_builder.dart | 8 +- .../lib/src/builders/statement_builder.dart | 2 +- pkgs/code_builder/lib/src/scope.dart | 4 +- pkgs/code_builder/lib/src/tokens.dart | 89 +++++++++++++++++++ .../lib/testing/equals_source.dart | 9 +- pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/method_builder_test.dart | 33 +++++++ 14 files changed, 205 insertions(+), 97 deletions(-) create mode 100644 pkgs/code_builder/lib/src/tokens.dart diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 2b3d189fc..2df5a4deb 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -30,11 +30,11 @@ library code_builder; import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/token.dart'; -import 'package:analyzer/src/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'; @@ -56,13 +56,10 @@ final DartFormatter _dartfmt = new DartFormatter(); @visibleForTesting String dartfmt(String source) => _dartfmt.format(source); -Identifier _stringIdentifier(String s) { - return new SimpleIdentifier(new StringToken(TokenType.STRING, s, 0)); -} +SimpleIdentifier _stringIdentifier(String s) => + new SimpleIdentifier(stringToken(s)); -Literal _stringLiteral(String s) { - return new SimpleStringLiteral(new StringToken(TokenType.STRING, s, 0), s); -} +Literal _stringLiteral(String s) => new SimpleStringLiteral(stringToken(s), s); /// Base class for building and emitting a Dart language [AstNode]. abstract class CodeBuilder { diff --git a/pkgs/code_builder/lib/src/builders/class_builder.dart b/pkgs/code_builder/lib/src/builders/class_builder.dart index df9b3ab94..bd6a26024 100644 --- a/pkgs/code_builder/lib/src/builders/class_builder.dart +++ b/pkgs/code_builder/lib/src/builders/class_builder.dart @@ -6,11 +6,6 @@ part of code_builder; /// Builds a [ClassDeclaration] AST. class ClassBuilder implements CodeBuilder { - static Token _abstract = new KeywordToken(Keyword.ABSTRACT, 0); - static Token _extends = new KeywordToken(Keyword.EXTENDS, 0); - static Token _implements = new KeywordToken(Keyword.IMPLEMENTS, 0); - static Token _with = new KeywordToken(Keyword.WITH, 0); - final String _name; final bool _isAbstract; final TypeBuilder _extend; @@ -85,18 +80,18 @@ class ClassBuilder implements CodeBuilder { ClassDeclaration toAst([Scope scope = const Scope.identity()]) { var astNode = _emptyClassDeclaration()..name = _stringIdentifier(_name); if (_isAbstract) { - astNode.abstractKeyword = _abstract; + astNode.abstractKeyword = $abstract; } if (_extend != null) { - astNode.extendsClause = new ExtendsClause(_extends, _extend.toAst(scope)); + astNode.extendsClause = new ExtendsClause($extends, _extend.toAst(scope)); } if (_implement.isNotEmpty) { - astNode.implementsClause = new ImplementsClause(_implements, + astNode.implementsClause = new ImplementsClause($implements, _implement.map/**/((i) => i.toAst(scope)).toList()); } if (_mixin.isNotEmpty) { astNode.withClause = new WithClause( - _with, _mixin.map/**/((i) => i.toAst(scope)).toList()); + $with, _mixin.map/**/((i) => i.toAst(scope)).toList()); } astNode ..metadata.addAll(_metadata.map/**/((a) => a.toAst(scope))); diff --git a/pkgs/code_builder/lib/src/builders/constructor_builder.dart b/pkgs/code_builder/lib/src/builders/constructor_builder.dart index e53e053fc..8758d8b87 100644 --- a/pkgs/code_builder/lib/src/builders/constructor_builder.dart +++ b/pkgs/code_builder/lib/src/builders/constructor_builder.dart @@ -8,9 +8,6 @@ part of code_builder; /// /// Similar to [MethodBuilder] but with constructor-only features. class ConstructorBuilder implements CodeBuilder { - static final Token _const = new KeywordToken(Keyword.CONST, 0); - static final Token _this = new KeywordToken(Keyword.THIS, 0); - final bool _isConstant; final String _name; final List _parameters = []; @@ -43,7 +40,7 @@ class ConstructorBuilder implements CodeBuilder { null, null, null, - _isConstant ? _const : null, + _isConstant ? $const : null, null, null, _name != null ? _stringIdentifier(_name) : null, @@ -53,7 +50,7 @@ class ConstructorBuilder implements CodeBuilder { null, null, null, - new EmptyFunctionBody(MethodBuilder._semicolon), + new EmptyFunctionBody($semicolon), ); return astNode; } diff --git a/pkgs/code_builder/lib/src/builders/expression_builder.dart b/pkgs/code_builder/lib/src/builders/expression_builder.dart index 1baea0122..7175c8c9b 100644 --- a/pkgs/code_builder/lib/src/builders/expression_builder.dart +++ b/pkgs/code_builder/lib/src/builders/expression_builder.dart @@ -14,15 +14,8 @@ const literalNull = const _LiteralNull(); /// Represents an expression value of `true`. const literalTrue = const LiteralBool(true); -// Returns wrapped as a [ExpressionFunctionBody] AST. -final Token _closeP = new Token(TokenType.CLOSE_PAREN, 0); - -// Returns wrapped as a [FunctionExpression] AST. -final Token _openP = new Token(TokenType.OPEN_PAREN, 0); - -final Token _semicolon = new Token(TokenType.SEMICOLON, 0); - // TODO(matanl): Make this part of the public API. See annotation_builder.dart. +// Returns wrapped as a [ExpressionFunctionBody] AST. ExpressionFunctionBody _asFunctionBody( CodeBuilder expression, Scope scope, @@ -31,10 +24,11 @@ ExpressionFunctionBody _asFunctionBody( null, null, expression.toAst(scope), - _semicolon, + $semicolon, ); } +// Returns wrapped as a [FunctionExpression] AST. FunctionExpression _asFunctionExpression( CodeBuilder expression, Scope scope, @@ -42,11 +36,11 @@ FunctionExpression _asFunctionExpression( return new FunctionExpression( null, new FormalParameterList( - _openP, + $openParen, const [], null, null, - _closeP, + $closeParen, ), _asFunctionBody(expression, scope), ); @@ -108,6 +102,15 @@ abstract class ExpressionBuilder implements CodeBuilder { ); } + /// Assign [left] to [right]. + /// + /// If [nullAware] is true, the assignment uses the `??=` operator. + factory ExpressionBuilder.assignment( + String left, CodeBuilder right, + {bool nullAware: false}) { + return new _AssignmentExpression(left, right, nullAware: nullAware); + } + const ExpressionBuilder._(); /// Return a new [ExpressionBuilder] invoking the result of this expression. @@ -136,10 +139,8 @@ abstract class ExpressionBuilder implements CodeBuilder { /// Creates a new literal `bool` value. class LiteralBool extends _LiteralExpression { - static final BooleanLiteral _true = - new BooleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); - static final BooleanLiteral _false = - new BooleanLiteral(new KeywordToken(Keyword.FALSE, 0), false); + static final BooleanLiteral _true = new BooleanLiteral($true, true); + static final BooleanLiteral _false = new BooleanLiteral($false, false); final bool _value; @@ -159,7 +160,7 @@ class LiteralInt extends _LiteralExpression { @override IntegerLiteral toAst([_]) => new IntegerLiteral( - new StringToken(TokenType.INT, '$_value', 0), + intToken(_value), _value, ); } @@ -173,18 +174,12 @@ class LiteralString extends _LiteralExpression { @override StringLiteral toAst([_]) => new SimpleStringLiteral( - new StringToken( - TokenType.STRING, - "'$_value'", - 0, - ), + stringToken("'$_value'"), _value, ); } class _InvokeExpression extends ExpressionBuilder { - static final Token _colon = new Token(TokenType.COLON, 0); - final String _importFrom; final ExpressionBuilder _target; final String _name; @@ -231,10 +226,10 @@ class _InvokeExpression extends ExpressionBuilder { // TODO(matanl): Move to TypeBuilder.newInstance. if (_type != null) { return new InstanceCreationExpression( - new KeywordToken(Keyword.NEW, 0), + $new, new ConstructorName( _type.toAst(scope), - _name != null ? new Token(TokenType.PERIOD, 0) : null, + _name != null ? $period : null, _name != null ? _stringIdentifier(_name) : null, ), _getArgumentList(scope), @@ -242,7 +237,7 @@ class _InvokeExpression extends ExpressionBuilder { } return new MethodInvocation( _target?.toAst(scope), - _target != null ? new Token(TokenType.PERIOD, 0) : null, + _target != null ? $period : null, _stringIdentifier(_name), null, _getArgumentList(scope), @@ -254,21 +249,46 @@ class _InvokeExpression extends ExpressionBuilder { ArgumentList _getArgumentList(Scope scope) { return new ArgumentList( - new Token(TokenType.OPEN_CURLY_BRACKET, 0), + $openCurly, _positionalArguments.map/* p.toAst(scope)).toList() ..addAll(_namedArguments.keys .map/**/((name) => new NamedExpression( new Label( _stringIdentifier(name), - _colon, + $colon, ), _namedArguments[name].toAst(scope), ))), - new Token(TokenType.CLOSE_CURLY_BRACKET, 0), + $closeCurly, ); } } +class _AssignmentExpression extends ExpressionBuilder { + final String left; + final CodeBuilder right; + final bool nullAware; + + _AssignmentExpression(this.left, this.right, {this.nullAware: false}) + : super._(); + + @override + ExpressionBuilder invokeSelf(String name, + {Iterable> positional: const [], + Map> named: const {}}) { + return _invokeSelfImpl(this, name, positional: positional, named: named); + } + + @override + Expression toAst([Scope scope = const Scope.identity()]) { + return new AssignmentExpression(_stringIdentifier(left), + nullAware ? $nullAwareEquals : $equals, right.toAst(scope)); + } + + @override + StatementBuilder toStatement() => new _ExpressionStatementBuilder(this); +} + abstract class _LiteralExpression implements ExpressionBuilder, CodeBuilder { const _LiteralExpression(); @@ -296,7 +316,7 @@ abstract class _LiteralExpression } class _LiteralNull extends _LiteralExpression { - static NullLiteral _null = new NullLiteral(new KeywordToken(Keyword.NULL, 0)); + static final NullLiteral _null = new NullLiteral($null); const _LiteralNull(); diff --git a/pkgs/code_builder/lib/src/builders/field_builder.dart b/pkgs/code_builder/lib/src/builders/field_builder.dart index 5977e5546..82839b1ec 100644 --- a/pkgs/code_builder/lib/src/builders/field_builder.dart +++ b/pkgs/code_builder/lib/src/builders/field_builder.dart @@ -10,13 +10,6 @@ part of code_builder; /// AST (for class members) via [toFieldAst] or a variable declaration (used /// both at the top-level and within methods) via [toVariablesAst]. class FieldBuilder implements CodeBuilder { - static Token _equals = new Token(TokenType.EQ, 0); - static Token _semicolon = new Token(TokenType.SEMICOLON, 0); - static Token _static = new KeywordToken(Keyword.STATIC, 0); - static Token _final = new KeywordToken(Keyword.FINAL, 0); - static Token _const = new KeywordToken(Keyword.CONST, 0); - static Token _var = new KeywordToken(Keyword.VAR, 0); - final bool _isConst; final bool _isFinal; final bool _isStatic; @@ -84,7 +77,7 @@ class FieldBuilder implements CodeBuilder { new FieldDeclaration( null, null, - _isStatic ? _static : null, + _isStatic ? $static : null, toVariablesAst(scope), null, ); @@ -100,7 +93,7 @@ class FieldBuilder implements CodeBuilder { [ new VariableDeclaration( _stringIdentifier(_name), - _initialize != null ? _equals : null, + _initialize != null ? $equals : null, _initialize?.toAst(scope), ) ], @@ -108,11 +101,11 @@ class FieldBuilder implements CodeBuilder { Token _getVariableKeyword() { if (_isFinal) { - return _final; + return $final; } if (_isConst) { - return _const; + return $const; } - return _type == null ? _var : null; + return _type == null ? $var : null; } } diff --git a/pkgs/code_builder/lib/src/builders/file_builder.dart b/pkgs/code_builder/lib/src/builders/file_builder.dart index 3b65df3ff..1b386b7fa 100644 --- a/pkgs/code_builder/lib/src/builders/file_builder.dart +++ b/pkgs/code_builder/lib/src/builders/file_builder.dart @@ -92,8 +92,6 @@ class ImportBuilder implements CodeBuilder { /// Builds a standalone Dart library [CompilationUnit] AST. class LibraryBuilder extends FileBuilder { - static final Token _library = new KeywordToken(Keyword.LIBRARY, 0); - final String _name; final Scope _scope; @@ -128,7 +126,7 @@ class LibraryBuilder extends FileBuilder { new LibraryDirective( null, null, - _library, + $library, new LibraryIdentifier([_stringIdentifier(_name)]), null, ), @@ -142,9 +140,6 @@ class LibraryBuilder extends FileBuilder { /// Builds a `part of` [CompilationUnit] AST for an existing Dart library. class PartBuilder extends FileBuilder { - static final Token _part = new KeywordToken(Keyword.PART, 0); - static final Token _of = new StringToken(TokenType.KEYWORD, 'of', 0); - final String _name; /// Create a new `part of` source file. @@ -158,8 +153,8 @@ class PartBuilder extends FileBuilder { originalAst.directives.add(new PartOfDirective( null, null, - _part, - _of, + $part, + $of, new LibraryIdentifier([_stringIdentifier(_name)]), null, )); diff --git a/pkgs/code_builder/lib/src/builders/method_builder.dart b/pkgs/code_builder/lib/src/builders/method_builder.dart index 33a6fdfd2..252c836cd 100644 --- a/pkgs/code_builder/lib/src/builders/method_builder.dart +++ b/pkgs/code_builder/lib/src/builders/method_builder.dart @@ -12,10 +12,6 @@ part of code_builder; /// /// To return nothing (`void`), use [MethodBuilder.returnVoid]. class MethodBuilder implements CodeBuilder { - static Token _abstract = new KeywordToken(Keyword.ABSTRACT, 0); - static Token _semicolon = new Token(TokenType.SEMICOLON, 0); - static Token _static = new KeywordToken(Keyword.STATIC, 0); - // Void is a "type" that is only valid as a return type on a method. static const TypeBuilder _typeVoid = const TypeBuilder('void'); @@ -126,14 +122,14 @@ class MethodBuilder implements CodeBuilder { ..returnType = _returnType?.toAst(scope); FunctionBody methodBody = _returnExpression?.toFunctionBody(scope); if (_isStatic) { - methodAst.modifierKeyword = _static; + methodAst.modifierKeyword = $static; if (methodBody == null) { methodBody = _blockBody(); } } if (methodBody == null) { methodBody = _isAbstract - ? new EmptyFunctionBody(_semicolon) + ? new EmptyFunctionBody($semicolon) : _blockBody(_statements.map/**/((s) => s.toAst(scope))); } if (_parameters.isNotEmpty) { @@ -152,9 +148,9 @@ class MethodBuilder implements CodeBuilder { null, null, new Block( - new Token(TokenType.OPEN_CURLY_BRACKET, 0), + $openCurly, statements?.toList(), - new Token(TokenType.CLOSE_CURLY_BRACKET, 0), + $closeCurly, ), ); @@ -187,10 +183,10 @@ class MethodBuilder implements CodeBuilder { ); static FormalParameterList _emptyParameters() => new FormalParameterList( - new Token(TokenType.OPEN_PAREN, 0), + $openParen, [], null, null, - new Token(TokenType.CLOSE_PAREN, 0), + $closeParen, ); } diff --git a/pkgs/code_builder/lib/src/builders/parameter_builder.dart b/pkgs/code_builder/lib/src/builders/parameter_builder.dart index 886ca2415..9f38cd47c 100644 --- a/pkgs/code_builder/lib/src/builders/parameter_builder.dart +++ b/pkgs/code_builder/lib/src/builders/parameter_builder.dart @@ -10,8 +10,6 @@ part of code_builder; /// class-member (field) variable (see the `field` property in the /// constructors). class ParameterBuilder implements CodeBuilder { - static final Token _this = new KeywordToken(Keyword.THIS, 0); - final String _name; final bool _isField; final bool _isOptional; @@ -129,7 +127,7 @@ class ParameterBuilder implements CodeBuilder { null, null, _type?.toAst(scope), - _this, + $this, null, _stringIdentifier(_name), null, @@ -154,9 +152,7 @@ class ParameterBuilder implements CodeBuilder { return new DefaultFormalParameter( parameter, named ? ParameterKind.NAMED : ParameterKind.POSITIONAL, - defaultTo != null - ? named ? new Token(TokenType.COLON, 0) : new Token(TokenType.EQ, 0) - : null, + defaultTo != null ? named ? $colon : $equals : null, defaultTo?.toAst(), ); } diff --git a/pkgs/code_builder/lib/src/builders/statement_builder.dart b/pkgs/code_builder/lib/src/builders/statement_builder.dart index eb02e423f..683753d5d 100644 --- a/pkgs/code_builder/lib/src/builders/statement_builder.dart +++ b/pkgs/code_builder/lib/src/builders/statement_builder.dart @@ -18,7 +18,7 @@ class _ExpressionStatementBuilder implements StatementBuilder { Statement toAst([Scope scope = const Scope.identity()]) { return new ExpressionStatement( _expression.toAst(scope), - new Token(TokenType.SEMICOLON, 0), + $semicolon, ); } } diff --git a/pkgs/code_builder/lib/src/scope.dart b/pkgs/code_builder/lib/src/scope.dart index ab5f38390..f852b0fac 100644 --- a/pkgs/code_builder/lib/src/scope.dart +++ b/pkgs/code_builder/lib/src/scope.dart @@ -70,8 +70,8 @@ class _IncrementingScope implements Scope { @override Identifier getIdentifier(String symbol, String import) { var newId = _imports.putIfAbsent(import, () => ++_counter); - return new PrefixedIdentifier(_stringIdentifier('_i$newId'), - new Token(TokenType.PERIOD, 0), _stringIdentifier(symbol)); + return new PrefixedIdentifier( + _stringIdentifier('_i$newId'), $period, _stringIdentifier(symbol)); } @override diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart new file mode 100644 index 000000000..2ca6c83b9 --- /dev/null +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -0,0 +1,89 @@ +// 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. + +import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/src/dart/ast/token.dart'; + +// Keywords +/// The `abstract` token. +final Token $abstract = new KeywordToken(Keyword.ABSTRACT, 0); + +/// The `extends` token. +final Token $extends = new KeywordToken(Keyword.EXTENDS, 0); + +/// The `implements` token. +final Token $implements = new KeywordToken(Keyword.IMPLEMENTS, 0); + +/// The `with` token. +final Token $with = new KeywordToken(Keyword.WITH, 0); + +/// The `static` token. +final Token $static = new KeywordToken(Keyword.STATIC, 0); + +/// The `final` token. +final Token $final = new KeywordToken(Keyword.FINAL, 0); + +/// The `const` token. +final Token $const = new KeywordToken(Keyword.CONST, 0); + +/// The `var` token. +final Token $var = new KeywordToken(Keyword.VAR, 0); + +/// The `this` token. +final Token $this = new KeywordToken(Keyword.THIS, 0); + +/// The `library` token. +final Token $library = new KeywordToken(Keyword.LIBRARY, 0); + +/// The `part` token. +final Token $part = new KeywordToken(Keyword.PART, 0); + +/// The `of` token. +final Token $of = new StringToken(TokenType.KEYWORD, 'of', 0); + +/// The `true` token. +final Token $true = new KeywordToken(Keyword.TRUE, 0); + +/// The `false` token. +final Token $false = new KeywordToken(Keyword.FALSE, 0); + +/// The `null` token. +final Token $null = new KeywordToken(Keyword.NULL, 0); + +/// The `new` token. +final Token $new = new KeywordToken(Keyword.NEW, 0); + +// Simple tokens +/// The '(' token. +final Token $openParen = new Token(TokenType.OPEN_PAREN, 0); + +/// The ')' token. +final Token $closeParen = new Token(TokenType.CLOSE_PAREN, 0); + +/// The '{' token. +final Token $openCurly = new Token(TokenType.OPEN_CURLY_BRACKET, 0); + +/// The '}' token. +final Token $closeCurly = new Token(TokenType.CLOSE_CURLY_BRACKET, 0); + +/// The ':' token. +final Token $colon = new Token(TokenType.COLON, 0); + +/// The ';' token. +final Token $semicolon = new Token(TokenType.SEMICOLON, 0); + +/// The '=' token. +final Token $equals = new Token(TokenType.EQ, 0); + +/// The '??=' token. +final Token $nullAwareEquals = new Token(TokenType.QUESTION_QUESTION_EQ, 0); + +/// The '.' token. +final Token $period = new Token(TokenType.PERIOD, 0); + +/// Returns a string token for the given string [s]. +StringToken stringToken(String s) => new StringToken(TokenType.STRING, s, 0); + +/// Returns an int token for the given int [value]. +StringToken intToken(int value) => new StringToken(TokenType.INT, '$value', 0); diff --git a/pkgs/code_builder/lib/testing/equals_source.dart b/pkgs/code_builder/lib/testing/equals_source.dart index 1231cb014..e79036c19 100644 --- a/pkgs/code_builder/lib/testing/equals_source.dart +++ b/pkgs/code_builder/lib/testing/equals_source.dart @@ -3,9 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/token.dart'; -import 'package:analyzer/src/dart/ast/token.dart'; import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/src/tokens.dart'; import 'package:matcher/matcher.dart'; /// Returns identifiers that are just the file name. @@ -38,9 +37,7 @@ Matcher equalsSource( ); } -Identifier _stringId(String s) { - return new SimpleIdentifier(new StringToken(TokenType.STRING, s, 0)); -} +Identifier _stringId(String s) => new SimpleIdentifier(stringToken(s)); class _EqualsSource extends Matcher { final Scope _scope; @@ -106,7 +103,7 @@ class _SimpleNameScope implements Scope { Uri.parse(importUri).pathSegments.last.split('.').first; return new PrefixedIdentifier( _stringId(fileWithoutExt), - new Token(TokenType.PERIOD, 0), + $period, _stringId(symbol), ); } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 2920693fc..483ee3a68 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 0.1.2 +version: 0.1.3 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/method_builder_test.dart b/pkgs/code_builder/test/builders/method_builder_test.dart index 7f6f3484d..3b0c70e6b 100644 --- a/pkgs/code_builder/test/builders/method_builder_test.dart +++ b/pkgs/code_builder/test/builders/method_builder_test.dart @@ -129,6 +129,39 @@ void main() { ); }); + test('should work with an assignment', () { + expect( + new MethodBuilder.returnVoid(name: 'main') + ..addStatement(new ExpressionBuilder.assignment( + 'foo', + const LiteralString('Hello World'), + ) + .toStatement()), + equalsSource(r''' + void main() { + foo = 'Hello World'; + } + '''), + ); + }); + + test('should work with a null-aware assignment', () { + expect( + new MethodBuilder.returnVoid(name: 'main') + ..addStatement(new ExpressionBuilder.assignment( + 'foo', + const LiteralString('Hello World'), + nullAware: true, + ) + .toStatement()), + equalsSource(r''' + void main() { + foo ??= 'Hello World'; + } + '''), + ); + }); + test('should work invoking an expression', () { expect( new MethodBuilder.returnVoid(name: 'main') From 9e2522794df4398c93dbaaed7da752d1f293e63c Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 27 Oct 2016 10:24:44 +0200 Subject: [PATCH 014/271] Rewrite: 1.0.0-alpha, with full statement support, fluid syntax (dart-lang/code_builder#15) * 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. . * . * . --- pkgs/code_builder/.gitignore | 16 - pkgs/code_builder/.travis.yml | 2 +- pkgs/code_builder/CHANGELOG.md | 4 + pkgs/code_builder/README.md | 47 +- pkgs/code_builder/analysis_options.yaml | 8 - pkgs/code_builder/doc/SHORT_LINKS.md | 10 + pkgs/code_builder/lib/code_builder.dart | 95 ++-- pkgs/code_builder/lib/dart/async.dart | 41 ++ pkgs/code_builder/lib/dart/core.dart | 339 ++++++++----- pkgs/code_builder/lib/src/analyzer_patch.dart | 12 +- .../lib/src/builders/annotation.dart | 49 ++ .../lib/src/builders/annotation_builder.dart | 88 ---- pkgs/code_builder/lib/src/builders/class.dart | 273 +++++++++++ .../lib/src/builders/class_builder.dart | 121 ----- .../lib/src/builders/constructor_builder.dart | 57 --- .../lib/src/builders/expression.dart | 359 ++++++++++++++ .../lib/src/builders/expression/assert.dart | 23 + .../lib/src/builders/expression/assign.dart | 53 +++ .../src/builders/expression/invocation.dart | 96 ++++ .../lib/src/builders/expression/negate.dart | 35 ++ .../src/builders/expression/operators.dart | 21 + .../lib/src/builders/expression/return.dart | 19 + .../lib/src/builders/expression_builder.dart | 325 ------------- pkgs/code_builder/lib/src/builders/field.dart | 170 +++++++ .../lib/src/builders/field_builder.dart | 111 ----- pkgs/code_builder/lib/src/builders/file.dart | 156 ++++++ .../lib/src/builders/file_builder.dart | 163 ------- .../code_builder/lib/src/builders/method.dart | 446 ++++++++++++++++++ .../lib/src/builders/method_builder.dart | 192 -------- .../lib/src/builders/parameter.dart | 213 +++++++++ .../lib/src/builders/parameter_builder.dart | 159 ------- .../lib/src/builders/reference.dart | 56 +++ .../code_builder/lib/src/builders/shared.dart | 27 ++ .../lib/src/builders/statement.dart | 71 +++ .../lib/src/builders/statement/block.dart | 27 ++ .../lib/src/builders/statement/if.dart | 95 ++++ .../lib/src/builders/statement_builder.dart | 24 - pkgs/code_builder/lib/src/builders/type.dart | 99 ++++ .../lib/src/builders/type/new_instance.dart | 53 +++ .../lib/src/builders/type_builder.dart | 25 - pkgs/code_builder/lib/src/pretty_printer.dart | 28 +- pkgs/code_builder/lib/src/scope.dart | 110 +++-- pkgs/code_builder/lib/src/tokens.dart | 138 ++++-- pkgs/code_builder/lib/testing.dart | 100 ++++ .../lib/testing/equals_source.dart | 113 ----- pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/class_builder_test.dart | 167 ------- .../test/builders/class_test.dart | 163 +++++++ .../test/builders/expression_test.dart | 247 ++++++++++ .../test/builders/field_builder_test.dart | 49 -- .../test/builders/field_test.dart | 33 ++ .../test/builders/file_builder_test.dart | 46 -- .../test/builders/method_builder_test.dart | 343 -------------- .../test/builders/method_test.dart | 172 +++++++ .../test/builders/parameter_builder.dart | 50 ++ .../test/builders/reference_test.dart | 9 + .../test/builders/shared_test.dart | 17 + .../test/builders/statement_test.dart | 85 ++++ .../code_builder/test/builders/type_test.dart | 71 +++ pkgs/code_builder/test/e2e_test.dart | 108 +++++ pkgs/code_builder/test/integration_test.dart | 151 ------ pkgs/code_builder/test/scope_test.dart | 152 +++--- pkgs/code_builder/tool/presubmit.sh | 29 ++ pkgs/code_builder/tool/travis.sh | 28 -- 64 files changed, 4013 insertions(+), 2578 deletions(-) create mode 100644 pkgs/code_builder/doc/SHORT_LINKS.md create mode 100644 pkgs/code_builder/lib/dart/async.dart create mode 100644 pkgs/code_builder/lib/src/builders/annotation.dart delete mode 100644 pkgs/code_builder/lib/src/builders/annotation_builder.dart create mode 100644 pkgs/code_builder/lib/src/builders/class.dart delete mode 100644 pkgs/code_builder/lib/src/builders/class_builder.dart delete mode 100644 pkgs/code_builder/lib/src/builders/constructor_builder.dart create mode 100644 pkgs/code_builder/lib/src/builders/expression.dart create mode 100644 pkgs/code_builder/lib/src/builders/expression/assert.dart create mode 100644 pkgs/code_builder/lib/src/builders/expression/assign.dart create mode 100644 pkgs/code_builder/lib/src/builders/expression/invocation.dart create mode 100644 pkgs/code_builder/lib/src/builders/expression/negate.dart create mode 100644 pkgs/code_builder/lib/src/builders/expression/operators.dart create mode 100644 pkgs/code_builder/lib/src/builders/expression/return.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression_builder.dart create mode 100644 pkgs/code_builder/lib/src/builders/field.dart delete mode 100644 pkgs/code_builder/lib/src/builders/field_builder.dart create mode 100644 pkgs/code_builder/lib/src/builders/file.dart delete mode 100644 pkgs/code_builder/lib/src/builders/file_builder.dart create mode 100644 pkgs/code_builder/lib/src/builders/method.dart delete mode 100644 pkgs/code_builder/lib/src/builders/method_builder.dart create mode 100644 pkgs/code_builder/lib/src/builders/parameter.dart delete mode 100644 pkgs/code_builder/lib/src/builders/parameter_builder.dart create mode 100644 pkgs/code_builder/lib/src/builders/reference.dart create mode 100644 pkgs/code_builder/lib/src/builders/shared.dart create mode 100644 pkgs/code_builder/lib/src/builders/statement.dart create mode 100644 pkgs/code_builder/lib/src/builders/statement/block.dart create mode 100644 pkgs/code_builder/lib/src/builders/statement/if.dart delete mode 100644 pkgs/code_builder/lib/src/builders/statement_builder.dart create mode 100644 pkgs/code_builder/lib/src/builders/type.dart create mode 100644 pkgs/code_builder/lib/src/builders/type/new_instance.dart delete mode 100644 pkgs/code_builder/lib/src/builders/type_builder.dart create mode 100644 pkgs/code_builder/lib/testing.dart delete mode 100644 pkgs/code_builder/lib/testing/equals_source.dart delete mode 100644 pkgs/code_builder/test/builders/class_builder_test.dart create mode 100644 pkgs/code_builder/test/builders/class_test.dart create mode 100644 pkgs/code_builder/test/builders/expression_test.dart delete mode 100644 pkgs/code_builder/test/builders/field_builder_test.dart create mode 100644 pkgs/code_builder/test/builders/field_test.dart delete mode 100644 pkgs/code_builder/test/builders/file_builder_test.dart delete mode 100644 pkgs/code_builder/test/builders/method_builder_test.dart create mode 100644 pkgs/code_builder/test/builders/method_test.dart create mode 100644 pkgs/code_builder/test/builders/parameter_builder.dart create mode 100644 pkgs/code_builder/test/builders/reference_test.dart create mode 100644 pkgs/code_builder/test/builders/shared_test.dart create mode 100644 pkgs/code_builder/test/builders/statement_test.dart create mode 100644 pkgs/code_builder/test/builders/type_test.dart create mode 100644 pkgs/code_builder/test/e2e_test.dart delete mode 100644 pkgs/code_builder/test/integration_test.dart create mode 100755 pkgs/code_builder/tool/presubmit.sh delete mode 100755 pkgs/code_builder/tool/travis.sh diff --git a/pkgs/code_builder/.gitignore b/pkgs/code_builder/.gitignore index 8d4854698..ae6cc48c5 100644 --- a/pkgs/code_builder/.gitignore +++ b/pkgs/code_builder/.gitignore @@ -1,5 +1,3 @@ -# See https://www.dartlang.org/tools/private-files.html - # Files and directories created by pub .buildlog .packages @@ -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 diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index 5826f9bc1..08997a645 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -4,4 +4,4 @@ dart: - dev - stable -script: ./tool/travis.sh +script: ./tool/presubmit.sh diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 1cb8ebe39..ffc86f365 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -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 diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 334a4e038..df51b80cf 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -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. @@ -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: @@ -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: @@ -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() {} ``` diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml index f7145dbf2..b256a69bb 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/analysis_options.yaml @@ -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 @@ -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 diff --git a/pkgs/code_builder/doc/SHORT_LINKS.md b/pkgs/code_builder/doc/SHORT_LINKS.md new file mode 100644 index 000000000..fc7063175 --- /dev/null +++ b/pkgs/code_builder/doc/SHORT_LINKS.md @@ -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 + \ No newline at end of file diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 2df5a4deb..950646846 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -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 { - /// 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; diff --git a/pkgs/code_builder/lib/dart/async.dart b/pkgs/code_builder/lib/dart/async.dart new file mode 100644 index 000000000..6025c39db --- /dev/null +++ b/pkgs/code_builder/lib/dart/async.dart @@ -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'); +} diff --git a/pkgs/code_builder/lib/dart/core.dart b/pkgs/code_builder/lib/dart/core.dart index f8c4e2170..9a5a0d7f0 100644 --- a/pkgs/code_builder/lib/dart/core.dart +++ b/pkgs/code_builder/lib/dart/core.dart @@ -2,136 +2,225 @@ // 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:core` library for use in code generation. +/// Contains references to the `dart:core` SDK for use in code generation. /// -/// This library is currently *experimental*, and is subject to change; it -/// currently is manually written but there might be a strong use case for this +/// 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/core.dart'; +/// +/// All references are _namespaced_ under [lib$core]. Try it: +/// // Outputs: print('Hello World') +/// core.print.call([literal('Hello World')]); +/// +/// If you are [missing a reference from `dart:core`](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.core; +import 'dart:core' as dart_core; + import 'package:code_builder/code_builder.dart'; -/// An alias for `new AnnotationBuilder('override')`. -const AnnotationBuilder atOverride = const AnnotationBuilder.reference( - 'override', - 'dart:core', -); - -/// An alias for `new TypeBuilder('bool')`. -const TypeBuilder typeBool = const TypeBuilder( - 'bool', - importFrom: 'dart:core', -); - -/// An alias for `new TypeBuilder('DateTime')`. -const TypeBuilder typeDateTime = const TypeBuilder( - 'DateTime', - importFrom: 'dart:core', -); - -/// An alias for `new TypeBuilder('double')`. -const TypeBuilder typeDouble = const TypeBuilder( - 'double', - importFrom: 'dart:core', -); - -/// An alias for `new TypeBuilder('Duration')`. -const TypeBuilder typeDuration = const TypeBuilder( - 'Duration', - importFrom: 'dart:core', -); - -/// An alias for `new TypeBuilder('Expando')`. -const TypeBuilder typeExpando = const TypeBuilder( - 'Expando', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('Function')`. -const TypeBuilder typeFunction = const TypeBuilder( - 'Function', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('int')`. -const TypeBuilder typeInt = const TypeBuilder( - 'int', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('Iterable')`. -const TypeBuilder typeIterable = const TypeBuilder( - 'Iterable', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('List')`. -const TypeBuilder typeList = const TypeBuilder( - 'List', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('Map')`. -const TypeBuilder typeMap = const TypeBuilder( - 'Map', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('Null')`. -const TypeBuilder typeNull = const TypeBuilder( - 'Null', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('num')`. -const TypeBuilder typeNum = const TypeBuilder( - 'num', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('Object')`. -const TypeBuilder typeObject = const TypeBuilder( - 'Object', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('Set')`. -const TypeBuilder typeSet = const TypeBuilder( - 'Set', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('String')`. -const TypeBuilder typeString = const TypeBuilder( - 'String', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('Symbol')`. -const TypeBuilder typeSymbol = const TypeBuilder( - 'Symbol', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('Type')`. -const TypeBuilder typeType = const TypeBuilder( - 'Type', - importFrom: 'dart:core', -); - -/// An alias for `const TypeBuilder('Uri')`. -const TypeBuilder typeUri = const TypeBuilder( - 'Uri', - importFrom: 'dart:core', -); - -/// Creates either a `@deprecated` or `@Deprecated('Message')` annotation. -AnnotationBuilder atDeprecated([String message]) { - if (message == null) { - return new AnnotationBuilder.reference('deprecated', 'dart:core'); +/// A namespace for references in `dart:core`. +final DartCore lib$core = new DartCore._(); + +/// References to the `dart:core` library for code generation. See [lib$core]. +class DartCore { + /// References [dart_core.bool]. + final ReferenceBuilder bool = _ref('bool'); + + /// References [dart_core.identical]. + final ReferenceBuilder identical = _ref('identical'); + + /// References [dart_core.deprecated]. + final ReferenceBuilder deprecated = _ref('deprecated'); + + /// References [dart_core.override]. + final ReferenceBuilder override = _ref('override'); + + /// References [dart_core.print]. + final ReferenceBuilder print = _ref('print'); + + /// References [dart_core.identityHashCode]. + final ReferenceBuilder identityHashCode = _ref('identityHashCode'); + + /// References [dart_core.int]. + final ReferenceBuilder int = _ref('int'); + + /// References [dart_core.AbstractClassInstantiationError]. + final ReferenceBuilder AbstractClassInstantiationError = + _ref('AbstractClassInstantiationError'); + + /// References [dart_core.ArgumentError]. + final ReferenceBuilder ArgumentError = _ref('ArgumentError'); + + /// References [dart_core.AssertionError]. + final ReferenceBuilder AssertionError = _ref('AssertionError'); + + /// References [dart_core.BidirectionalIterator]. + final ReferenceBuilder BidirectionalIterator = _ref('BidirectionalIterator'); + + /// References [dart_core.CastError]. + final ReferenceBuilder CastError = _ref('CastError'); + + /// References [dart_core.Comparable]. + final ReferenceBuilder Comparable = _ref('Comparable'); + + /// References [dart_core.Comparator] + final ReferenceBuilder Comparator = _ref('Comparator'); + + /// References [dart_core.ConcurrentModificationError]. + final ReferenceBuilder ConcurrentModificationError = + _ref('ConcurrentModificationError'); + + /// References [dart_core.CyclicInitializationError]. + final ReferenceBuilder CyclicInitializationError = + _ref('CyclicInitializationError'); + + /// References [dart_core.DateTime]. + final ReferenceBuilder DateTime = _ref('DateTime'); + + /// References [dart_core.Deprecated]. + final ReferenceBuilder Deprecated = _ref('Deprecated'); + + /// References [dart_core.Duration]. + final ReferenceBuilder Duration = _ref('Duration'); + + /// References [dart_core.Error]. + final ReferenceBuilder Error = _ref('Error'); + + /// References [dart_core.Exception]. + final ReferenceBuilder Exception = _ref('Exception'); + + /// References [dart_core.Expando]. + final ReferenceBuilder Expando = _ref('Expando'); + + /// References [dart_core.FallThroughError]. + final ReferenceBuilder FallThroughError = _ref('FallThroughError'); + + /// References [dart_core.FormatException]. + final ReferenceBuilder FormatException = _ref('FormatException'); + + /// References [dart_core.Function]. + final ReferenceBuilder Function = _ref('Function'); + + /// References [dart_core.IndexError]. + final ReferenceBuilder IndexError = _ref('IndexError'); + + /// References [dart_core.IntegerDivisionByZeroException]. + final ReferenceBuilder IntegerDivisionByZeroException = + _ref('IntegerDivisionByZeroException'); + + /// References [dart_core.Invocation]. + final ReferenceBuilder Invocation = _ref('Invocation'); + + /// References [dart_core.Iterable]. + final ReferenceBuilder Iterable = _ref('Iterable'); + + /// References [dart_core.Iterator]. + final ReferenceBuilder Iterator = _ref('Iterator'); + + /// References [dart_core.List]. + final ReferenceBuilder List = _ref('List'); + + /// References [dart_core.Map]. + final ReferenceBuilder Map = _ref('Map'); + + /// References [dart_core.Match]. + final ReferenceBuilder Match = _ref('Match'); + + /// References [dart_core.NoSuchMethodError]. + final ReferenceBuilder NoSuchMethodError = _ref('NoSuchMethodError'); + + /// References [dart_core.Null]. + final ReferenceBuilder Null = _ref('Null'); + + /// References [dart_core.NullThrownError]. + final ReferenceBuilder NullThrownError = _ref('NullThrownError'); + + /// References [dart_core.Object]. + final ReferenceBuilder Object = _ref('Object'); + + /// References [dart_core.OutOfMemoryError]. + final ReferenceBuilder OutOfMemoryError = _ref('OutOfMemoryError'); + + /// References [dart_core.Pattern]. + final ReferenceBuilder Pattern = _ref('Pattern'); + + /// References [dart_core.RangeError]. + final ReferenceBuilder RangeError = _ref('RangeError'); + + /// References [dart_core.RegExp]. + final ReferenceBuilder RegExp = _ref('RegExp'); + + /// References [dart_core.RuneIterator]. + final ReferenceBuilder RuneIterator = _ref('RuneIterator'); + + /// References [dart_core.Runes]. + final ReferenceBuilder Runes = _ref('Runes'); + + /// References [dart_core.Set]. + final ReferenceBuilder Set = _ref('Set'); + + /// References [dart_core.Sink]. + final ReferenceBuilder Sink = _ref('Sink'); + + /// References [dart_core.StackOverflowError]. + final ReferenceBuilder StackOverflowError = _ref('StackOverflowError'); + + /// References [dart_core.StackTrace]. + final ReferenceBuilder StackTrace = _ref('StackTrace'); + + /// References [dart_core.StateError]. + final ReferenceBuilder StateError = _ref('StateError'); + + /// References [dart_core.Stopwatch]. + final ReferenceBuilder Stopwatch = _ref('Stopwatch'); + + /// References [dart_core.String]. + final ReferenceBuilder String = _ref('String'); + + /// References [dart_core.StringBuffer]. + final ReferenceBuilder StringBuffer = _ref('StringBuffer'); + + /// References [dart_core.StringSink]. + final ReferenceBuilder StringSink = _ref('StringSink'); + + /// References [dart_core.Symbol]. + final ReferenceBuilder Symbol = _ref('Symbol'); + + /// References [dart_core.Type]. + final ReferenceBuilder Type = _ref('Type'); + + /// References [dart_core.TypeError]. + final ReferenceBuilder TypeError = _ref('TypeError'); + + /// References [dart_core.UnimplementedError]. + final ReferenceBuilder UnimplementedError = _ref('UnimplementedError'); + + /// References [dart_core.UnsupportedError]. + final ReferenceBuilder UnsupportedError = _ref('UnsupportedError'); + + /// References [dart_core.Uri]. + final ReferenceBuilder Uri = _ref('Uri'); + + /// References [dart_core.UriData]. + final ReferenceBuilder UriData = _ref('UriData'); + + /// References `void` type for returning nothing in a method. + /// + /// **NOTE**: As a language limitation, this cannot be named `void`. + final TypeBuilder $void = new TypeBuilder('void'); + + DartCore._(); + + static ReferenceBuilder _ref(dart_core.String name) { + return reference(name, 'dart:core'); } - return new AnnotationBuilder.invoke( - 'Deprecated', - positional: [new LiteralString(message)], - ); } diff --git a/pkgs/code_builder/lib/src/analyzer_patch.dart b/pkgs/code_builder/lib/src/analyzer_patch.dart index 5b27d772e..b4a71495a 100644 --- a/pkgs/code_builder/lib/src/analyzer_patch.dart +++ b/pkgs/code_builder/lib/src/analyzer_patch.dart @@ -10,9 +10,6 @@ import 'package:analyzer/src/generated/java_core.dart'; class PrintBuffer implements PrintWriter, StringBuffer { final StringBuffer _impl = new StringBuffer(); - @override - void clear() {} - @override bool get isEmpty => _impl.isEmpty; @@ -22,6 +19,9 @@ class PrintBuffer implements PrintWriter, StringBuffer { @override int get length => _impl.length; + @override + void clear() {} + @override void newLine() { _impl.writeln(); @@ -40,6 +40,9 @@ class PrintBuffer implements PrintWriter, StringBuffer { _impl.writeln(s); } + @override + String toString() => _impl.toString(); + @override void write(Object obj) { _impl.write(obj); @@ -59,7 +62,4 @@ class PrintBuffer implements PrintWriter, StringBuffer { void writeln([Object obj = ""]) { _impl.writeln(obj); } - - @override - String toString() => _impl.toString(); } diff --git a/pkgs/code_builder/lib/src/builders/annotation.dart b/pkgs/code_builder/lib/src/builders/annotation.dart new file mode 100644 index 000000000..404088af3 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/annotation.dart @@ -0,0 +1,49 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/src/builders/class.dart'; +import 'package:code_builder/src/builders/parameter.dart'; +import 'package:code_builder/src/builders/shared.dart'; + +/// Builds an [Annotation] AST when [buildAnnotation] is invoked. +abstract class AnnotationBuilder + implements ValidClassMember, ValidParameterMember { + /// Returns an [Annotation] AST representing the builder. + Annotation buildAnnotation([Scope scope]); +} + +/// An [AstBuilder] that can be annotated with [AnnotationBuilder]. +abstract class HasAnnotations implements AstBuilder { + /// Adds [annotation] to the builder. + void addAnnotation(AnnotationBuilder annotation); + + /// Adds [annotations] to the builder. + void addAnnotations(Iterable annotations); +} + +/// Implements [HasAnnotations]. +abstract class HasAnnotationsMixin implements HasAnnotations { + final List _annotations = []; + + @override + void addAnnotation(AnnotationBuilder annotation) { + _annotations.add(annotation); + } + + @override + void addAnnotations(Iterable annotations) { + _annotations.addAll(annotations); + } + + /// Returns a [List] of all built [Annotation]s. + List buildAnnotations([Scope scope]) => _annotations + .map/**/((a) => a.buildAnnotation(scope)) + .toList(); + + /// Clones all annotations to [clone]. + void copyAnnotationsTo(HasAnnotations clone) { + clone.addAnnotations(_annotations); + } +} diff --git a/pkgs/code_builder/lib/src/builders/annotation_builder.dart b/pkgs/code_builder/lib/src/builders/annotation_builder.dart deleted file mode 100644 index 1ce7b70eb..000000000 --- a/pkgs/code_builder/lib/src/builders/annotation_builder.dart +++ /dev/null @@ -1,88 +0,0 @@ -// 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. - -part of code_builder; - -/// Builds a metadata [Annotation] to be added to other AST elements. -/// -/// An annotation may either be a reference to an existing `const` identifier -/// _or_ to an invocation of a `const` class constructor. -/// -/// To create a `@doNotUse` reference, use [AnnotationBuilder.reference]: -/// const doNotUse = #do_not_use; -/// -/// @doNotUse -/// void destroyTheWorld() { ... } -/// -/// To create a `@DoNotUse('Blows up')` use [AnnotationBuilder.invoke]. -abstract class AnnotationBuilder implements CodeBuilder { - /// Create a new annotated `const` [constructor] invocation. - /// - /// May optionally specify an [importFrom] to auto-prefix the annotation _if_ - /// attached to a library where the import is not specified or is prefixed. - factory AnnotationBuilder.invoke( - String constructor, { - String importFrom, - Iterable> positional: const [], - Map> named: const {}, - }) { - return new _ConstructorAnnotationBuilder( - constructor, - new ExpressionBuilder.invoke( - null, - positional: positional, - named: named, - ), - importFrom, - ); - } - - /// Create a new annotated `const` [identifier]. - /// - /// May optionally specify an [importFrom] to auto-prefix the annotation _if_ - /// attached to a library where the import is not specified or is prefixed. - const factory AnnotationBuilder.reference(String identifier, - [String importFrom]) = _ReferenceAnnotationBuilder; -} - -class _ConstructorAnnotationBuilder implements AnnotationBuilder { - final String _constructor; - final ExpressionBuilder _expression; - final String _importFrom; - - _ConstructorAnnotationBuilder(this._constructor, this._expression, - [this._importFrom]); - - @override - Annotation toAst([Scope scope = const Scope.identity()]) { - var expressionAst = _expression.toAst(scope); - if (expressionAst is MethodInvocation) { - return new Annotation( - null, - scope.getIdentifier(_constructor, _importFrom), - null, - null, - // TODO(matanl): InvocationExpression needs to be public API. - expressionAst.argumentList, - ); - } - throw new UnsupportedError('Expression must be InvocationExpression'); - } -} - -class _ReferenceAnnotationBuilder implements AnnotationBuilder { - final String _importFrom; - final String _reference; - - const _ReferenceAnnotationBuilder(this._reference, [this._importFrom]); - - @override - Annotation toAst([Scope scope = const Scope.identity()]) => new Annotation( - null, - scope.getIdentifier(_reference, _importFrom), - null, - null, - null, - ); -} diff --git a/pkgs/code_builder/lib/src/builders/class.dart b/pkgs/code_builder/lib/src/builders/class.dart new file mode 100644 index 000000000..333d3e4a3 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/class.dart @@ -0,0 +1,273 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/src/builders/annotation.dart'; +import 'package:code_builder/src/builders/field.dart'; +import 'package:code_builder/src/builders/method.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/type.dart'; +import 'package:code_builder/src/tokens.dart'; + +/// A more short-hand way of constructing a [ClassBuilder]. +ClassBuilder clazz( + String name, [ + Iterable members = const [], +]) { + final clazz = new ClassBuilder(name); + for (final member in members) { + if (member is AnnotationBuilder) { + clazz.addAnnotation(member); + } else if (member is _TypeNameWrapper) { + if (member.extend) { + clazz.setExtends(member.type); + } else if (member.mixin) { + clazz.addMixin(member.type); + } else { + clazz.addImplement(member.type); + } + } else if (member is ConstructorBuilder) { + clazz.addConstructor(member); + } else if (member is _StaticFieldWrapper) { + var wrapped = member._member; + if (wrapped is MethodBuilder) { + clazz.addMethod(wrapped, asStatic: true); + } else { + clazz.addField(wrapped as FieldBuilder, asStatic: true); + } + } else if (member is FieldBuilder) { + clazz.addField(member); + } else if (member is MethodBuilder) { + clazz.addMethod(member); + } else { + throw new StateError('Invalid AST type: ${member.runtimeType}'); + } + } + return clazz; +} + +/// Wrap [member] to be emitted as a `static` method or field. +ValidClassMember asStatic(ValidClassMember member) { + return new _StaticFieldWrapper(member); +} + +class _StaticFieldWrapper implements ValidClassMember { + final ValidClassMember _member; + + _StaticFieldWrapper(this._member); + + @override + AstNode buildAst([Scope scope]) => + throw new UnsupportedError('Use inside varField'); +} + +/// Returns a wrapper around [type] for use with [clazz]. +_TypeNameWrapper extend(TypeBuilder type) { + return new _TypeNameWrapper( + type, + extend: true, + ); +} + +/// Returns a wrapper around [type] for use with [clazz]. +_TypeNameWrapper implement(TypeBuilder type) { + return new _TypeNameWrapper( + type, + implement: true, + ); +} + +/// Returns a wrapper around [type] for use with [clazz]. +_TypeNameWrapper mixin(TypeBuilder type) { + return new _TypeNameWrapper( + type, + mixin: true, + ); +} + +/// Lazily builds an [ClassDeclaration] AST when [buildClass] is invoked. +abstract class ClassBuilder + implements AstBuilder, HasAnnotations, TypeBuilder { + /// Returns a new [ClassBuilder] with [name]. + factory ClassBuilder( + String name, { + bool asAbstract, + TypeBuilder asExtends, + Iterable asWith, + Iterable asImplements, + }) = _ClassBuilderImpl; + + /// Adds a [constructor]. + void addConstructor(ConstructorBuilder constructor); + + /// Adds a [field]. + void addField(FieldBuilder field, {bool asStatic: false}); + + /// Adds an [interface] to implement. + void addImplement(TypeBuilder interface); + + /// Adds [interfaces] to implement. + void addImplements(Iterable interfaces); + + /// Adds a [method]. + void addMethod(MethodBuilder method, {bool asStatic: false}); + + /// Adds a [mixin]. + void addMixin(TypeBuilder mixin); + + /// Adds [mixins]. + void addMixins(Iterable mixins); + + /// Returns an [ClassDeclaration] AST representing the builder. + ClassDeclaration buildClass([Scope scope]); + + /// Sets [extend]. + void setExtends(TypeBuilder extend); +} + +/// A marker interface for an AST that could be added to [ClassBuilder]. +abstract class ValidClassMember implements AstBuilder {} + +class _ClassBuilderImpl extends Object + with AbstractTypeBuilderMixin, HasAnnotationsMixin + implements ClassBuilder { + final _constructors = []; + final _fields = {}; + final _methods = {}; + + TypeBuilder _extends; + final List _with; + final List _implements; + + final bool _asAbstract; + final String _name; + + _ClassBuilderImpl( + this._name, { + bool asAbstract: false, + TypeBuilder asExtends, + Iterable asWith: const [], + Iterable asImplements: const [], + }) + : _asAbstract = asAbstract, + _extends = asExtends, + _with = asWith.toList(), + _implements = asImplements.toList(); + + @override + void addConstructor(ConstructorBuilder constructor) { + _constructors.add(constructor); + } + + @override + void addField(FieldBuilder field, {bool asStatic: false}) { + _fields[field] = asStatic; + } + + @override + void addImplement(TypeBuilder interface) { + _implements.add(interface); + } + + @override + void addImplements(Iterable interfaces) { + _implements.addAll(interfaces); + } + + @override + void addMethod(MethodBuilder method, {bool asStatic: false}) { + _methods[method] = asStatic; + } + + @override + void addMixin(TypeBuilder mixin) { + _with.add(mixin); + } + + @override + void addMixins(Iterable mixins) { + _with.addAll(mixins); + } + + @override + ClassDeclaration buildAst([Scope scope]) => buildClass(scope); + + @override + ClassDeclaration buildClass([Scope scope]) { + var extend = _extends; + if (extend == null && _with.isNotEmpty) { + extend = lib$core.Object; + } + final clazz = new ClassDeclaration( + null, + buildAnnotations(scope), + _asAbstract ? $abstract : null, + $class, + stringIdentifier(_name), + null, + extend != null + ? new ExtendsClause( + $extends, + extend.buildType(scope), + ) + : null, + _with.isNotEmpty + ? new WithClause( + $with, + _with.map/**/((w) => w.buildType(scope)).toList(), + ) + : null, + _implements.isNotEmpty + ? new ImplementsClause( + $implements, + _implements.map/**/((i) => i.buildType(scope)).toList(), + ) + : null, + null, + null, + null, + ); + _fields.forEach((field, static) { + clazz.members.add(field.buildField(static, scope)); + }); + _constructors.forEach((constructor) { + clazz.members.add(constructor.buildConstructor( + this, + scope, + )); + }); + _methods.forEach((method, static) { + clazz.members.add(method.buildMethod(static, scope)); + }); + return clazz; + } + + @override + TypeName buildType([Scope scope]) { + return new TypeBuilder(_name).buildType(scope); + } + + @override + void setExtends(TypeBuilder extend) { + _extends = extend; + } +} + +class _TypeNameWrapper implements ValidClassMember { + final bool extend; + final bool implement; + final bool mixin; + final TypeBuilder type; + + _TypeNameWrapper( + this.type, { + this.extend: false, + this.implement: false, + this.mixin: false, + }); + + @override + AstNode buildAst([_]) => throw new UnsupportedError('Use within clazz'); +} diff --git a/pkgs/code_builder/lib/src/builders/class_builder.dart b/pkgs/code_builder/lib/src/builders/class_builder.dart deleted file mode 100644 index bd6a26024..000000000 --- a/pkgs/code_builder/lib/src/builders/class_builder.dart +++ /dev/null @@ -1,121 +0,0 @@ -// 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. - -part of code_builder; - -/// Builds a [ClassDeclaration] AST. -class ClassBuilder implements CodeBuilder { - final String _name; - final bool _isAbstract; - final TypeBuilder _extend; - final Iterable _implement; - final Iterable _mixin; - - final List _fields = []; - final List _methods = []; - final List _metadata = []; - final List _constructors = []; - - /// Create a new builder for a `class` named [name]. - /// - /// Optionally, define another class to [extend] or classes to either - /// [implement] or [mixin]. - factory ClassBuilder( - String name, { - TypeBuilder extend, - Iterable implement: const [], - Iterable mixin: const [], - }) => - new ClassBuilder._( - name, - false, - extend, - new List.unmodifiable(implement), - new List.unmodifiable(mixin), - ); - - /// Create a new builder for an `abstract class` named [name]. - factory ClassBuilder.asAbstract(String name, - {TypeBuilder extend, - Iterable implement: const [], - Iterable mixin: const []}) => - new ClassBuilder._( - name, - true, - extend, - new List.unmodifiable(implement), - new List.unmodifiable(mixin), - ); - - ClassBuilder._( - this._name, - this._isAbstract, - this._extend, - this._implement, - this._mixin, - ); - - /// Adds an annotation [builder] as metadata. - void addAnnotation(AnnotationBuilder builder) { - _metadata.add(builder); - } - - /// Adds a constructor [builder]. - void addConstructor(ConstructorBuilder builder) { - _constructors.add(builder); - } - - /// Adds a field [builder] as a member on the class. - void addField(FieldBuilder builder) { - _fields.add(builder); - } - - /// Adds a method [builder] as a member on the class. - void addMethod(MethodBuilder builder) { - _methods.add(builder); - } - - @override - ClassDeclaration toAst([Scope scope = const Scope.identity()]) { - var astNode = _emptyClassDeclaration()..name = _stringIdentifier(_name); - if (_isAbstract) { - astNode.abstractKeyword = $abstract; - } - if (_extend != null) { - astNode.extendsClause = new ExtendsClause($extends, _extend.toAst(scope)); - } - if (_implement.isNotEmpty) { - astNode.implementsClause = new ImplementsClause($implements, - _implement.map/**/((i) => i.toAst(scope)).toList()); - } - if (_mixin.isNotEmpty) { - astNode.withClause = new WithClause( - $with, _mixin.map/**/((i) => i.toAst(scope)).toList()); - } - astNode - ..metadata.addAll(_metadata.map/**/((a) => a.toAst(scope))); - astNode - ..members.addAll(_fields.map/**/((f) => f.toFieldAst(scope))) - ..members.addAll(_constructors.map/**/( - (c) => c.toAst(scope)..returnType = _stringIdentifier(_name))) - ..members - .addAll(_methods.map/**/((m) => m.toMethodAst(scope))); - return astNode; - } - - static ClassDeclaration _emptyClassDeclaration() => new ClassDeclaration( - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - ); -} diff --git a/pkgs/code_builder/lib/src/builders/constructor_builder.dart b/pkgs/code_builder/lib/src/builders/constructor_builder.dart deleted file mode 100644 index 8758d8b87..000000000 --- a/pkgs/code_builder/lib/src/builders/constructor_builder.dart +++ /dev/null @@ -1,57 +0,0 @@ -// 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. - -part of code_builder; - -/// Builds a [ConstructorDeclaration] AST. -/// -/// Similar to [MethodBuilder] but with constructor-only features. -class ConstructorBuilder implements CodeBuilder { - final bool _isConstant; - final String _name; - final List _parameters = []; - - /// Create a new builder for a constructor, optionally with a [name]. - factory ConstructorBuilder([String name]) { - return new ConstructorBuilder._(false, name); - } - - /// Create a new builder for a constructor, optionally with a [name]. - /// - /// The resulting constructor will be `const`. - factory ConstructorBuilder.isConst([String name]) { - return new ConstructorBuilder._(true, name); - } - - ConstructorBuilder._(this._isConstant, this._name); - - /// Lazily adds [builder]. - /// - /// When the method is emitted as an AST, [ParameterBuilder.toAst] is used. - void addParameter(ParameterBuilder builder) { - _parameters.add(builder); - } - - @override - ConstructorDeclaration toAst([Scope scope = const Scope.identity()]) { - var astNode = new ConstructorDeclaration( - null, - null, - null, - null, - _isConstant ? $const : null, - null, - null, - _name != null ? _stringIdentifier(_name) : null, - MethodBuilder._emptyParameters() - ..parameters.addAll( - _parameters.map/**/((p) => p.toAst(scope))), - null, - null, - null, - new EmptyFunctionBody($semicolon), - ); - return astNode; - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart new file mode 100644 index 000000000..faa78c738 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -0,0 +1,359 @@ +library code_builder.src.builders.expression; + +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/src/dart/ast/token.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/src/builders/method.dart'; +import 'package:code_builder/src/builders/parameter.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:code_builder/src/builders/statement/if.dart'; +import 'package:code_builder/src/builders/type.dart'; +import 'package:code_builder/src/tokens.dart'; + +part 'expression/assert.dart'; +part 'expression/assign.dart'; +part 'expression/invocation.dart'; +part 'expression/negate.dart'; +part 'expression/operators.dart'; +part 'expression/return.dart'; + +final _false = new BooleanLiteral(new KeywordToken(Keyword.FALSE, 0), true); + +final _null = new NullLiteral(new KeywordToken(Keyword.NULL, 0)); + +final _true = new BooleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); + +/// Returns a pre-defined literal expression of [value]. +/// +/// Only primitive values are allowed. +ExpressionBuilder literal(value) => new _LiteralExpression(_literal(value)); + +Literal _literal(value) { + if (value == null) { + return _null; + } else if (value is bool) { + return value ? _true : _false; + } else if (value is String) { + return new SimpleStringLiteral(stringToken("'$value'"), value); + } else if (value is int) { + return new IntegerLiteral(stringToken('$value'), value); + } else if (value is double) { + return new DoubleLiteral(stringToken('$value'), value); + } else if (value is List) { + return new ListLiteral( + null, + null, + $openBracket, + value.map/**/(_literal).toList(), + $closeBracket, + ); + } else if (value is Map) { + return new MapLiteral( + null, + null, + $openBracket, + value.keys.map/**/((k) { + return new MapLiteralEntry(_literal(k), $colon, _literal(value[k])); + }).toList(), + $closeBracket, + ); + } + throw new ArgumentError.value(value, 'Unsupported'); +} + +/// Implements much of [ExpressionBuilder]. +abstract class AbstractExpressionMixin implements ExpressionBuilder { + @override + ExpressionBuilder operator *(ExpressionBuilder other) { + return new _AsBinaryExpression( + this, + other, + $multiply, + ); + } + + @override + ExpressionBuilder operator +(ExpressionBuilder other) { + return new _AsBinaryExpression( + this, + other, + $plus, + ); + } + + @override + ExpressionBuilder operator -(ExpressionBuilder other) { + return new _AsBinaryExpression( + this, + other, + $minus, + ); + } + + @override + ExpressionBuilder operator /(ExpressionBuilder other) { + return new _AsBinaryExpression( + this, + other, + $divide, + ); + } + + @override + StatementBuilder asAssert() => new _AsAssert(this); + + @override + StatementBuilder asAssign( + String variable, { + bool nullAware: false, + }) => + new _AsAssign(this, variable, nullAware); + + @override + StatementBuilder asConst(String variable, [TypeBuilder type]) { + return new _AsAssignNew(this, variable, type, $const); + } + + @override + StatementBuilder asFinal(String variable, [TypeBuilder type]) { + return new _AsAssignNew(this, variable, type, $final); + } + + @override + IfStatementBuilder asIf() => new IfStatementBuilder(this); + + @override + StatementBuilder asReturn() => new _AsReturn(this); + + @override + StatementBuilder asStatement() => new _AsStatement(this); + + @override + StatementBuilder asVar(String variable, [TypeBuilder type]) { + return new _AsAssignNew(this, variable, type, $var); + } + + @override + Statement buildStatement([Scope scope]) { + return asStatement().buildStatement(scope); + } + + @override + InvocationBuilder call( + Iterable positionalArguments, [ + Map namedArguments = const {}, + ]) { + final invocation = new InvocationBuilder._(this); + positionalArguments.forEach(invocation.addPositionalArgument); + namedArguments.forEach(invocation.addNamedArgument); + return invocation; + } + + @override + ExpressionBuilder equals(ExpressionBuilder other) { + return new _AsBinaryExpression( + this, + other, + $equalsEquals, + ); + } + + @override + ExpressionBuilder identical(ExpressionBuilder other) { + return lib$core.identical.call([ + this, + other, + ]); + } + + @override + InvocationBuilder invoke( + String method, + Iterable positionalArguments, [ + Map namedArguments = const {}, + ]) { + final invocation = new InvocationBuilder._on(this, method); + positionalArguments.forEach(invocation.addPositionalArgument); + namedArguments.forEach(invocation.addNamedArgument); + return invocation; + } + + @override + ExpressionBuilder negate() => new _NegateExpression(this); + + @override + ExpressionBuilder negative() => new _NegativeExpression(this); + + @override + ExpressionBuilder notEquals(ExpressionBuilder other) { + return new _AsBinaryExpression( + this, + other, + $notEquals, + ); + } + + @override + ExpressionBuilder parentheses() => new _ParenthesesExpression(this); +} + +/// Builds an [Expression] AST when [buildExpression] is invoked. +abstract class ExpressionBuilder + implements AstBuilder, StatementBuilder, ValidParameterMember { + /// Returns as an [ExpressionBuilder] multiplying by [other]. + ExpressionBuilder operator *(ExpressionBuilder other); + + /// Returns as an [ExpressionBuilder] adding [other]. + ExpressionBuilder operator +(ExpressionBuilder other); + + /// Returns as an [ExpressionBuilder] subtracting [other]. + ExpressionBuilder operator -(ExpressionBuilder other); + + /// Returns as an [ExpressionBuilder] dividing by [other]. + ExpressionBuilder operator /(ExpressionBuilder other); + + /// Return as a [StatementBuilder] that `assert`s this expression. + StatementBuilder asAssert(); + + /// Returns as a [StatementBuilder] that assigns to an existing [variable]. + StatementBuilder asAssign(String variable, {bool nullAware}); + + /// Returns as a [StatementBuilder] that assigns to a new `const` [variable]. + StatementBuilder asConst(String variable, [TypeBuilder type]); + + /// Returns as a [StatementBuilder] that assigns to a new `final` [variable]. + StatementBuilder asFinal(String variable, [TypeBuilder type]); + + /// Returns as a [StatementBuilder] that builds an `if` statement. + IfStatementBuilder asIf(); + + /// Returns as a [StatementBuilder] that `return`s this expression. + StatementBuilder asReturn(); + + /// Returns _explicitly_ as a [StatementBuilder]. + /// + /// **NOTE**: [ExpressionBuilder] is _already_ usable as a [StatementBuilder] + /// directly; this API exists in order force [buildAst] to return a + /// [Statement] AST instead of an expression. + StatementBuilder asStatement(); + + /// Returns as a [StatementBuilder] that assigns to a new `var` [variable]. + /// + /// If [type] is supplied, the resulting statement is `{type} {variable} =`. + StatementBuilder asVar(String variable, [TypeBuilder type]); + + /// Returns an [Expression] AST representing the builder. + Expression buildExpression([Scope scope]); + + /// Returns as an [InvocationBuilder] with arguments added. + InvocationBuilder call( + Iterable positionalArguments, [ + Map namedArguments, + ]); + + /// Returns as an [ExpressionBuilder] comparing using `==` against [other]. + ExpressionBuilder equals(ExpressionBuilder other); + + /// Returns as an [ExpressionBuilder] comparing using `identical`. + ExpressionBuilder identical(ExpressionBuilder other); + + /// Returns as an [InvocationBuilder] on [method] of this expression. + InvocationBuilder invoke( + String method, + Iterable positionalArguments, [ + Map namedArguments, + ]); + + /// Returns as an [ExpressionBuilder] negating using the `!` operator. + ExpressionBuilder negate(); + + /// Returns as an [ExpressionBuilder] negating the value, + ExpressionBuilder negative(); + + /// Returns as an [ExpressionBuilder] comparing using `!=` against [other]. + ExpressionBuilder notEquals(ExpressionBuilder other); + + /// Returns as an [ExpressionBuilder] wrapped in parentheses. + ExpressionBuilder parentheses(); +} + +/// An [AstBuilder] that can add [ExpressionBuilder]. +abstract class HasExpressions implements AstBuilder { + final List _expressions = []; + + /// Adds [expression] to the builder. + void addExpression(ExpressionBuilder expression) { + _expressions.add(expression); + } + + /// Adds [expressions] to the builder. + void addExpressions(Iterable expressions) { + _expressions.addAll(expressions); + } +} + +/// Implements [HasExpressions]. +abstract class HasExpressionsMixin extends HasExpressions { + /// Returns a [List] of all built [Expression]s. + List buildExpressions([Scope scope]) => _expressions + .map/**/((e) => e.buildExpression(scope)) + .toList(); + + /// Clones all expressions to [clone]. + void cloneExpressionsTo(HasExpressions clone) { + clone.addExpressions(_expressions); + } +} + +class _AsStatement implements StatementBuilder { + final ExpressionBuilder _expression; + + _AsStatement(this._expression); + + @override + AstNode buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) { + return new ExpressionStatement( + _expression.buildExpression(scope), + $semicolon, + ); + } +} + +class _LiteralExpression extends Object with AbstractExpressionMixin { + final Literal _literal; + + _LiteralExpression(this._literal); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([_]) => _literal; +} + +class _ParenthesesExpression extends Object with AbstractExpressionMixin { + final ExpressionBuilder _expression; + + _ParenthesesExpression(this._expression); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return new ParenthesizedExpression( + $openParen, + _expression.buildExpression(scope), + $closeParen, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/assert.dart b/pkgs/code_builder/lib/src/builders/expression/assert.dart new file mode 100644 index 000000000..3313feec4 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/assert.dart @@ -0,0 +1,23 @@ +part of code_builder.src.builders.expression; + +class _AsAssert implements StatementBuilder { + final ExpressionBuilder _expression; + + _AsAssert(this._expression); + + @override + AstNode buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) { + return new AssertStatement( + $assert, + $openParen, + _expression.buildExpression(scope), + null, + null, + $closeParen, + null, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/assign.dart b/pkgs/code_builder/lib/src/builders/expression/assign.dart new file mode 100644 index 000000000..5c6b19167 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/assign.dart @@ -0,0 +1,53 @@ +part of code_builder.src.builders.expression; + +class _AsAssign extends AbstractExpressionMixin { + final String _name; + final bool _nullAware; + final ExpressionBuilder _value; + + _AsAssign(this._value, this._name, this._nullAware); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return new AssignmentExpression( + stringIdentifier(_name), + _nullAware ? $nullAwareEquals : $equals, + _value.buildExpression(scope), + ); + } +} + +class _AsAssignNew implements StatementBuilder { + final ExpressionBuilder _value; + final String _name; + final TypeBuilder _type; + final Token _modifier; + + _AsAssignNew(this._value, this._name, this._type, this._modifier); + + @override + AstNode buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) { + return new VariableDeclarationStatement( + new VariableDeclarationList( + null, + null, + _type == null || _modifier != $var ? _modifier : null, + _type?.buildType(scope), + [ + new VariableDeclaration( + stringIdentifier(_name), + $equals, + _value.buildExpression(scope), + ), + ], + ), + $semicolon, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/invocation.dart b/pkgs/code_builder/lib/src/builders/expression/invocation.dart new file mode 100644 index 000000000..1c015e6e2 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/invocation.dart @@ -0,0 +1,96 @@ +part of code_builder.src.builders.expression; + +/// Partial implementation of [InvocationBuilder]. +abstract class AbstractInvocationBuilderMixin implements InvocationBuilder { + final List _positional = []; + final Map _named = {}; + + @override + void addNamedArgument(String name, ExpressionBuilder argument) { + _named[name] = argument; + } + + @override + void addPositionalArgument(ExpressionBuilder argument) { + _positional.add(argument); + } + + /// Returns an [ArgumentList] AST. + ArgumentList buildArgumentList([Scope scope]) { + final allArguments = []; + allArguments.addAll( + _positional.map/**/((e) => e.buildExpression(scope))); + _named.forEach((name, e) { + allArguments.add(new NamedExpression( + new Label( + stringIdentifier(name), + $colon, + ), + e.buildExpression(scope), + )); + }); + return new ArgumentList( + $openParen, + allArguments, + $closeParen, + ); + } + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); +} + +/// Builds an invocation AST. +abstract class InvocationBuilder + implements ExpressionBuilder, StatementBuilder, ValidMethodMember { + factory InvocationBuilder._(ExpressionBuilder target) { + return new _FunctionInvocationBuilder(target); + } + + factory InvocationBuilder._on(ExpressionBuilder target, String method) { + return new _MethodInvocationBuilder(target, method); + } + + /// Adds [argument] as a [name]d argument to this method call. + void addNamedArgument(String name, ExpressionBuilder argument); + + /// Adds [argument] as a positional argument to this method call. + void addPositionalArgument(ExpressionBuilder argument); +} + +class _FunctionInvocationBuilder extends Object + with AbstractInvocationBuilderMixin, AbstractExpressionMixin + implements InvocationBuilder { + final ExpressionBuilder _target; + + _FunctionInvocationBuilder(this._target); + + @override + Expression buildExpression([Scope scope]) { + return new FunctionExpressionInvocation( + _target.buildExpression(scope), + null, + buildArgumentList(scope), + ); + } +} + +class _MethodInvocationBuilder extends Object + with AbstractInvocationBuilderMixin, AbstractExpressionMixin + implements InvocationBuilder { + final String _method; + final ExpressionBuilder _target; + + _MethodInvocationBuilder(this._target, this._method); + + @override + Expression buildExpression([Scope scope]) { + return new MethodInvocation( + _target.buildExpression(scope), + $period, + stringIdentifier(_method), + null, + buildArgumentList(scope), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/negate.dart b/pkgs/code_builder/lib/src/builders/expression/negate.dart new file mode 100644 index 000000000..d1d58d3dc --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/negate.dart @@ -0,0 +1,35 @@ +part of code_builder.src.builders.expression; + +class _NegateExpression extends AbstractExpressionMixin { + final ExpressionBuilder _expression; + + _NegateExpression(this._expression); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return new PrefixExpression( + $not, + _expression.parentheses().buildExpression(scope), + ); + } +} + +class _NegativeExpression extends AbstractExpressionMixin { + final ExpressionBuilder _expression; + + _NegativeExpression(this._expression); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return new PrefixExpression( + $minus, + _expression.parentheses().buildExpression(scope), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/operators.dart b/pkgs/code_builder/lib/src/builders/expression/operators.dart new file mode 100644 index 000000000..f36140a26 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/operators.dart @@ -0,0 +1,21 @@ +part of code_builder.src.builders.expression; + +class _AsBinaryExpression extends Object with AbstractExpressionMixin { + final ExpressionBuilder _left; + final ExpressionBuilder _right; + final Token _operator; + + _AsBinaryExpression(this._left, this._right, this._operator); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return new BinaryExpression( + _left.buildExpression(scope), + _operator, + _right.buildExpression(scope), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/return.dart b/pkgs/code_builder/lib/src/builders/expression/return.dart new file mode 100644 index 000000000..d57c7deff --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/return.dart @@ -0,0 +1,19 @@ +part of code_builder.src.builders.expression; + +class _AsReturn implements StatementBuilder { + final ExpressionBuilder _value; + + _AsReturn(this._value); + + @override + AstNode buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) { + return new ReturnStatement( + $return, + _value.buildExpression(), + $semicolon, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression_builder.dart b/pkgs/code_builder/lib/src/builders/expression_builder.dart deleted file mode 100644 index 7175c8c9b..000000000 --- a/pkgs/code_builder/lib/src/builders/expression_builder.dart +++ /dev/null @@ -1,325 +0,0 @@ -// 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. - -part of code_builder; - -// Shared functionality between ExpressionBuilder and _LiteralExpression. -/// Represents an expression value of `false`. -const literalFalse = const LiteralBool(false); - -/// Represents an expression value of `null`. -const literalNull = const _LiteralNull(); - -/// Represents an expression value of `true`. -const literalTrue = const LiteralBool(true); - -// TODO(matanl): Make this part of the public API. See annotation_builder.dart. -// Returns wrapped as a [ExpressionFunctionBody] AST. -ExpressionFunctionBody _asFunctionBody( - CodeBuilder expression, - Scope scope, -) { - return new ExpressionFunctionBody( - null, - null, - expression.toAst(scope), - $semicolon, - ); -} - -// Returns wrapped as a [FunctionExpression] AST. -FunctionExpression _asFunctionExpression( - CodeBuilder expression, - Scope scope, -) { - return new FunctionExpression( - null, - new FormalParameterList( - $openParen, - const [], - null, - null, - $closeParen, - ), - _asFunctionBody(expression, scope), - ); -} - -ExpressionBuilder _invokeSelfImpl( - ExpressionBuilder self, - String name, { - Iterable> positional: const [], - Map> named: const {}, -}) { - return new _InvokeExpression.target( - name, - self, - positional, - named, - ); -} - -/// Builds an [Expression] AST. -/// -/// For simple literal expressions see: -/// - [LiteralBool] and [literalTrue] [literalFalse] -/// - [LiteralInt] -/// - [LiteralString] -/// - [literalNull] -abstract class ExpressionBuilder implements CodeBuilder { - /// Invoke [name] (which should be available in the local scope). - /// - /// May specify [positional] and [named] arguments. - factory ExpressionBuilder.invoke( - String name, { - String importFrom, - Iterable> positional: const [], - Map> named: const {}, - }) { - return new _InvokeExpression( - name, - new List>.unmodifiable(positional), - new Map>.unmodifiable(named), - importFrom, - ); - } - - /// Invoke the 'new' operator on [type]. - /// - /// May use a [name] of a constructor and [positional] and [named] arguments. - factory ExpressionBuilder.invokeNew( - TypeBuilder type, { - String name, - Iterable> positional: const [], - Map> named: const {}, - }) { - return new _InvokeExpression.newInstance( - type, - name, - new List>.unmodifiable(positional), - new Map>.unmodifiable(named), - ); - } - - /// Assign [left] to [right]. - /// - /// If [nullAware] is true, the assignment uses the `??=` operator. - factory ExpressionBuilder.assignment( - String left, CodeBuilder right, - {bool nullAware: false}) { - return new _AssignmentExpression(left, right, nullAware: nullAware); - } - - const ExpressionBuilder._(); - - /// Return a new [ExpressionBuilder] invoking the result of this expression. - ExpressionBuilder invokeSelf( - String name, { - Iterable> positional: const [], - Map> named: const {}, - }); // TODO(matanl): Rename to invoke when factory is removed. - - /// Returns wrapped as a [ExpressionFunctionBody] AST. - ExpressionFunctionBody toFunctionBody( - [Scope scope = const Scope.identity()]) => - _asFunctionBody(this, scope); - - /// Returns wrapped as a [FunctionExpression] AST. - FunctionExpression toFunctionExpression( - [Scope scope = const Scope.identity()]) => - _asFunctionExpression(this, scope); - - /// Converts to a [StatementBuilder]. - /// - /// __Example use__: - /// literalNull.toStatement(); // ==> null; - StatementBuilder toStatement(); -} - -/// Creates a new literal `bool` value. -class LiteralBool extends _LiteralExpression { - static final BooleanLiteral _true = new BooleanLiteral($true, true); - static final BooleanLiteral _false = new BooleanLiteral($false, false); - - final bool _value; - - /// Returns the passed value as a [BooleanLiteral]. - const LiteralBool(this._value); - - @override - BooleanLiteral toAst([_]) => _value ? _true : _false; -} - -/// Represents an expression value of a literal number. -class LiteralInt extends _LiteralExpression { - final int _value; - - /// Returns the passed value as a [IntegerLiteral]. - const LiteralInt(this._value); - - @override - IntegerLiteral toAst([_]) => new IntegerLiteral( - intToken(_value), - _value, - ); -} - -/// Represents an expression value of a literal `'string'`. -class LiteralString extends _LiteralExpression { - final String _value; - - /// Returns the passed value as a [StringLiteral]. - const LiteralString(this._value); - - @override - StringLiteral toAst([_]) => new SimpleStringLiteral( - stringToken("'$_value'"), - _value, - ); -} - -class _InvokeExpression extends ExpressionBuilder { - final String _importFrom; - final ExpressionBuilder _target; - final String _name; - final List> _positionalArguments; - final Map> _namedArguments; - final TypeBuilder _type; - - const _InvokeExpression( - this._name, - this._positionalArguments, - this._namedArguments, - this._importFrom, - ) - : _target = null, - _type = null, - super._(); - - const _InvokeExpression.newInstance( - this._type, - this._name, - this._positionalArguments, - this._namedArguments, - ) - : _target = null, - _importFrom = null, - super._(); - - const _InvokeExpression.target( - this._name, this._target, this._positionalArguments, this._namedArguments) - : _importFrom = null, - _type = null, - super._(); - - @override - ExpressionBuilder invokeSelf( - String name, { - Iterable> positional: const [], - Map> named: const {}, - }) => - _invokeSelfImpl(this, name, positional: positional, named: named); - - @override - Expression toAst([Scope scope = const Scope.identity()]) { - // TODO(matanl): Move to TypeBuilder.newInstance. - if (_type != null) { - return new InstanceCreationExpression( - $new, - new ConstructorName( - _type.toAst(scope), - _name != null ? $period : null, - _name != null ? _stringIdentifier(_name) : null, - ), - _getArgumentList(scope), - ); - } - return new MethodInvocation( - _target?.toAst(scope), - _target != null ? $period : null, - _stringIdentifier(_name), - null, - _getArgumentList(scope), - ); - } - - @override - StatementBuilder toStatement() => new _ExpressionStatementBuilder(this); - - ArgumentList _getArgumentList(Scope scope) { - return new ArgumentList( - $openCurly, - _positionalArguments.map/* p.toAst(scope)).toList() - ..addAll(_namedArguments.keys - .map/**/((name) => new NamedExpression( - new Label( - _stringIdentifier(name), - $colon, - ), - _namedArguments[name].toAst(scope), - ))), - $closeCurly, - ); - } -} - -class _AssignmentExpression extends ExpressionBuilder { - final String left; - final CodeBuilder right; - final bool nullAware; - - _AssignmentExpression(this.left, this.right, {this.nullAware: false}) - : super._(); - - @override - ExpressionBuilder invokeSelf(String name, - {Iterable> positional: const [], - Map> named: const {}}) { - return _invokeSelfImpl(this, name, positional: positional, named: named); - } - - @override - Expression toAst([Scope scope = const Scope.identity()]) { - return new AssignmentExpression(_stringIdentifier(left), - nullAware ? $nullAwareEquals : $equals, right.toAst(scope)); - } - - @override - StatementBuilder toStatement() => new _ExpressionStatementBuilder(this); -} - -abstract class _LiteralExpression - implements ExpressionBuilder, CodeBuilder { - const _LiteralExpression(); - - @override - ExpressionBuilder invokeSelf( - String name, { - Iterable> positional: const [], - Map> named: const {}, - }) => - _invokeSelfImpl(this, name, positional: positional, named: named); - - @override - ExpressionFunctionBody toFunctionBody( - [Scope scope = const Scope.identity()]) => - _asFunctionBody(this, scope); - - @override - FunctionExpression toFunctionExpression( - [Scope scope = const Scope.identity()]) => - _asFunctionExpression(this, scope); - - @override - StatementBuilder toStatement() => new _ExpressionStatementBuilder(this); -} - -class _LiteralNull extends _LiteralExpression { - static final NullLiteral _null = new NullLiteral($null); - - const _LiteralNull(); - - @override - NullLiteral toAst([_]) => _null; -} diff --git a/pkgs/code_builder/lib/src/builders/field.dart b/pkgs/code_builder/lib/src/builders/field.dart new file mode 100644 index 000000000..51b5d978f --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/field.dart @@ -0,0 +1,170 @@ +import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/src/dart/ast/token.dart'; +import 'package:code_builder/src/builders/annotation.dart'; +import 'package:code_builder/src/builders/class.dart'; +import 'package:code_builder/src/builders/expression.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:code_builder/src/builders/type.dart'; +import 'package:code_builder/src/tokens.dart'; + +/// Short-hand for [FieldBuilder]. +FieldBuilder varField( + String name, { + TypeBuilder type, + ExpressionBuilder value, +}) { + return new FieldBuilder( + name, + type: type, + value: value, + ); +} + +/// Short-hand for [FieldBuilder.asFinal]. +FieldBuilder varFinal( + String name, { + TypeBuilder type, + ExpressionBuilder value, +}) { + return new FieldBuilder.asFinal( + name, + type: type, + value: value, + ); +} + +/// Short-hand for [FieldBuilder.asConst]. +FieldBuilder varConst( + String name, { + TypeBuilder type, + ExpressionBuilder value, +}) { + return new FieldBuilder.asConst( + name, + type: type, + value: value, + ); +} + +/// Lazily builds an field AST when builder is invoked. +abstract class FieldBuilder + implements + AstBuilder, + HasAnnotations, + StatementBuilder, + ValidClassMember { + /// Creates a new [FieldBuilder] defining a new `var`. + factory FieldBuilder( + String name, { + TypeBuilder type, + ExpressionBuilder value, + }) => + new _FieldBuilderImpl( + name, + keyword: type == null ? Keyword.VAR : null, + type: type, + value: value, + ); + + /// Creates a new [FieldBuilder] defining a new `const`. + factory FieldBuilder.asConst( + String name, { + TypeBuilder type, + ExpressionBuilder value, + }) => + new _FieldBuilderImpl( + name, + keyword: Keyword.CONST, + type: type, + value: value, + ); + + /// Creates a new [FieldBuilder] defining a new `final`. + factory FieldBuilder.asFinal( + String name, { + TypeBuilder type, + ExpressionBuilder value, + }) => + new _FieldBuilderImpl( + name, + keyword: Keyword.FINAL, + type: type, + value: value, + ); + + /// Returns as a [FieldDeclaration] AST. + FieldDeclaration buildField(bool static, [Scope scope]); + + /// Returns as a [TopLevelVariableDeclaration] AST. + TopLevelVariableDeclaration buildTopLevel([Scope scope]); +} + +class _FieldBuilderImpl extends Object + with HasAnnotationsMixin + implements FieldBuilder { + final Keyword _keyword; + final String _name; + final TypeBuilder _type; + final ExpressionBuilder _value; + + _FieldBuilderImpl( + String name, { + Keyword keyword, + TypeBuilder type, + ExpressionBuilder value, + }) + : _keyword = keyword, + _name = name, + _type = type, + _value = value; + + @override + TopLevelVariableDeclaration buildAst([Scope scope]) => buildTopLevel(scope); + + @override + FieldDeclaration buildField(bool static, [Scope scope]) { + return new FieldDeclaration( + null, + buildAnnotations(scope), + static ? $static : null, + _buildVariableList(scope), + $semicolon, + ); + } + + @override + Statement buildStatement([Scope scope]) { + return new VariableDeclarationStatement( + _buildVariableList(scope), + $semicolon, + ); + } + + @override + TopLevelVariableDeclaration buildTopLevel([Scope scope]) { + return new TopLevelVariableDeclaration( + null, + null, + _buildVariableList(scope), + $semicolon, + ); + } + + VariableDeclarationList _buildVariableList([Scope scope]) { + return new VariableDeclarationList( + null, + null, + _keyword != null ? new KeywordToken(_keyword, 0) : null, + _type?.buildType(scope), + [ + new VariableDeclaration( + stringIdentifier(_name), + _value != null ? $equals : null, + _value?.buildExpression(scope), + ) + ], + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/field_builder.dart b/pkgs/code_builder/lib/src/builders/field_builder.dart deleted file mode 100644 index 82839b1ec..000000000 --- a/pkgs/code_builder/lib/src/builders/field_builder.dart +++ /dev/null @@ -1,111 +0,0 @@ -// 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. - -part of code_builder; - -/// Builds either a [FieldDeclaration] or [VariableDeclaration] AST. -/// -/// While the API is the same, you may specifically ask for either a field -/// AST (for class members) via [toFieldAst] or a variable declaration (used -/// both at the top-level and within methods) via [toVariablesAst]. -class FieldBuilder implements CodeBuilder { - final bool _isConst; - final bool _isFinal; - final bool _isStatic; - final ExpressionBuilder _initialize; - final String _name; - final TypeBuilder _type; - - /// Create a new field builder. - /// - /// Optionally set a type and initializer. - FieldBuilder( - this._name, { - TypeBuilder type, - ExpressionBuilder initialize, - bool asStatic: false, - }) - : this._type = type, - this._initialize = initialize, - this._isFinal = false, - this._isConst = false, - this._isStatic = asStatic; - - /// Create a new field builder that emits a `const` field. - /// - /// Optionally set a type and initializer. - FieldBuilder.isConst( - this._name, { - TypeBuilder type, - ExpressionBuilder initialize, - bool asStatic: false, - }) - : this._type = type, - this._initialize = initialize, - this._isFinal = false, - this._isConst = true, - this._isStatic = false; - - /// Create a new field builder that emits a `final` field. - /// - /// Optionally set a type and initializer. - FieldBuilder.isFinal( - this._name, { - TypeBuilder type, - ExpressionBuilder initialize, - bool asStatic: false, - }) - : this._type = type, - this._initialize = initialize, - this._isFinal = true, - this._isConst = false, - this._isStatic = asStatic; - - /// Returns a copy-safe [AstNode] representing the current builder state. - /// - /// **NOTE**: This method exists primarily for testing and compatibility with - /// the [CodeBuilder] ADT. When possible, invoke [toFieldAst] or - /// [toVariablesAst]. - @override - @visibleForTesting - Declaration toAst([Scope scope = const Scope.identity()]) => - toFieldAst(scope); - - /// Returns a copy-safe [FieldDeclaration] AST representing current state. - FieldDeclaration toFieldAst([Scope scope = const Scope.identity()]) => - new FieldDeclaration( - null, - null, - _isStatic ? $static : null, - toVariablesAst(scope), - null, - ); - - /// Returns a copy-safe [VariableDeclaration] AST representing current state. - VariableDeclarationList toVariablesAst( - [Scope scope = const Scope.identity()]) => - new VariableDeclarationList( - null, - null, - _getVariableKeyword(), - _type?.toAst(scope), - [ - new VariableDeclaration( - _stringIdentifier(_name), - _initialize != null ? $equals : null, - _initialize?.toAst(scope), - ) - ], - ); - - Token _getVariableKeyword() { - if (_isFinal) { - return $final; - } - if (_isConst) { - return $const; - } - return _type == null ? $var : null; - } -} diff --git a/pkgs/code_builder/lib/src/builders/file.dart b/pkgs/code_builder/lib/src/builders/file.dart new file mode 100644 index 000000000..fc6e71be6 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/file.dart @@ -0,0 +1,156 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/tokens.dart'; + +/// Builds a file of Dart source code. +/// +/// See [LibraryBuilder] and [PartBuilder] for concrete implementations. +abstract class FileBuilder implements AstBuilder { + final List> _members = + >[]; + + FileBuilder._(); + + /// Adds a top-level field or class [member]. + void addMember(AstBuilder member) { + _members.add(member); + } + + /// Adds top-level field or class [members]. + void addMembers(Iterable> members) { + _members.addAll(members); + } +} + +/// Builds a standalone file (library) of Dart source code. +class LibraryBuilder extends FileBuilder { + final List> _directives = >[]; + final Scope _scope; + + /// Creates a new standalone Dart library, optionally with [name]. + factory LibraryBuilder([String name]) => + new LibraryBuilder._(name, Scope.identity); + + /// Creates a new standalone Dart library, optionally with [name]. + /// + /// Uses the default [Scope] implementation unless [scope] is set. + factory LibraryBuilder.scope({String name, Scope scope}) { + return new LibraryBuilder._(name, scope ?? new Scope()); + } + + LibraryBuilder._(String name, this._scope) : super._() { + if (name != null) { + _directives.add(new _LibraryDirectiveBuilder(name)); + } + } + + /// Adds a file [directive]. + void addDirective(AstBuilder directive) { + _directives.add(directive); + } + + /// Add file [directives]. + void addDirectives(Iterable> directives) { + _directives.addAll(directives); + } + + @override + CompilationUnit buildAst([_]) { + var members = _members.map((m) => m.buildAst(_scope)).toList(); + var directives = [] + ..addAll(_scope.toImports().map((d) => d.buildAst())) + ..addAll(_directives.map((d) => d.buildAst())); + return new CompilationUnit( + null, + null, + directives, + members, + null, + ); + } +} + +/// Lazily builds a partial file (part of) Dart source code. +class PartBuilder extends FileBuilder { + final String _name; + + /// Creates a partial Dart file. + factory PartBuilder(String name) = PartBuilder._; + + PartBuilder._(this._name) : super._(); + + @override + CompilationUnit buildAst([_]) { + return new CompilationUnit( + null, + null, + [ + new PartOfDirective( + null, + null, + $part, + $of, + new LibraryIdentifier([ + new SimpleIdentifier(stringToken(_name)), + ]), + $semicolon, + ) + ], + _members.map((m) => m.buildAst()).toList(), + null, + ); + } +} + +class _LibraryDirectiveBuilder implements AstBuilder { + final String _name; + + _LibraryDirectiveBuilder(this._name); + + @override + LibraryDirective buildAst([_]) { + return new LibraryDirective( + null, + null, + $library, + new LibraryIdentifier([ + new SimpleIdentifier( + stringToken(_name), + ), + ]), + $semicolon, + ); + } +} + +/// Lazily builds an [ImportDirective] AST when built. +class ImportBuilder implements AstBuilder { + final String _prefix; + final String _uri; + + factory ImportBuilder(String path, {String prefix}) { + return new ImportBuilder._(path, prefix); + } + + ImportBuilder._(this._uri, this._prefix); + + @override + ImportDirective buildAst([_]) { + return new ImportDirective( + null, + null, + null, + new SimpleStringLiteral(stringToken("'$_uri'"), _uri), + null, + null, + _prefix != null ? $as : null, + _prefix != null ? stringIdentifier(_prefix) : null, + null, + $semicolon, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/file_builder.dart b/pkgs/code_builder/lib/src/builders/file_builder.dart deleted file mode 100644 index 1b386b7fa..000000000 --- a/pkgs/code_builder/lib/src/builders/file_builder.dart +++ /dev/null @@ -1,163 +0,0 @@ -// 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. - -part of code_builder; - -CompilationUnit _emptyCompilationUnit() => new CompilationUnit( - null, - null, - null, - null, - null, - ); - -/// An `export` directive in a [LibraryBuilder]. -class ExportBuilder implements CodeBuilder { - final String _uri; - - /// Create a new `export` directive exporting [uri]. - factory ExportBuilder(String uri) = ExportBuilder._; - - const ExportBuilder._(this._uri); - - @override - ExportDirective toAst([_]) { - return _createExportDirective()..uri = _stringLiteral("'$_uri'"); - } - - static ExportDirective _createExportDirective() => new ExportDirective( - null, - null, - null, - null, - null, - null, - null, - ); -} - -/// Builds files of Dart source code. -/// -/// See [LibraryBuilder] and [PartBuilder] for concrete implementations. -abstract class FileBuilder implements CodeBuilder { - final List> _declarations = - >[]; - - FileBuilder._(); - - /// Adds [declaration]'s resulting AST to the source. - void addDeclaration(CodeBuilder declaration) { - _declarations.add(declaration); - } - - @override - @mustCallSuper - CompilationUnit toAst([Scope scope = const Scope.identity()]) => - _emptyCompilationUnit() - ..declarations - .addAll(_declarations.map/**/((d) => d.toAst(scope))); -} - -/// An `import` directive in a [FileBuilder]. -class ImportBuilder implements CodeBuilder { - final String _uri; - final String _prefix; - - /// Create a new `import` directive importing [uri]. - /// - /// Optionally prefix [prefix]. - const factory ImportBuilder(String uri, {String prefix}) = ImportBuilder._; - - const ImportBuilder._(this._uri, {String prefix}) : _prefix = prefix; - - @override - ImportDirective toAst([_]) => _createImportDirective() - ..uri = _stringLiteral("'$_uri'") - ..prefix = _prefix != null ? _stringIdentifier(_prefix) : null; - - static ImportDirective _createImportDirective() => new ImportDirective( - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - ); -} - -/// Builds a standalone Dart library [CompilationUnit] AST. -class LibraryBuilder extends FileBuilder { - final String _name; - final Scope _scope; - - final List> _directives = >[]; - - /// Create a new standalone Dart library, optionally with a [name]. - factory LibraryBuilder([String name]) { - return new LibraryBuilder._(name, const Scope.identity()); - } - - /// Create a new standalone Dart library, optionally with a [name]. - /// - /// As references are added in the library that implements [CodeBuilder] - /// they are re-written to avoid collisions and the imports are automatically - /// included at the top with optional prefixes. - factory LibraryBuilder.scope({String name, Scope scope}) { - return new LibraryBuilder._(name, scope ?? new Scope()); - } - - LibraryBuilder._(this._name, this._scope) : super._(); - - /// Adds [directive]'s resulting AST to the source. - void addDirective(CodeBuilder directive) { - _directives.add(directive); - } - - @override - CompilationUnit toAst([_]) { - var originalAst = super.toAst(_scope); - if (_name != null) { - originalAst.directives.add( - new LibraryDirective( - null, - null, - $library, - new LibraryIdentifier([_stringIdentifier(_name)]), - null, - ), - ); - } - originalAst.directives..addAll(_directives.map((d) => d.toAst())); - originalAst.directives..addAll(_scope.getImports().map((i) => i.toAst())); - return originalAst; - } -} - -/// Builds a `part of` [CompilationUnit] AST for an existing Dart library. -class PartBuilder extends FileBuilder { - final String _name; - - /// Create a new `part of` source file. - factory PartBuilder(String name) = PartBuilder._; - - PartBuilder._(this._name) : super._(); - - @override - CompilationUnit toAst([Scope scope = const Scope.identity()]) { - var originalAst = super.toAst(); - originalAst.directives.add(new PartOfDirective( - null, - null, - $part, - $of, - new LibraryIdentifier([_stringIdentifier(_name)]), - null, - )); - return originalAst; - } -} diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart new file mode 100644 index 000000000..2228d2f7d --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -0,0 +1,446 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/src/dart/ast/token.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/src/builders/annotation.dart'; +import 'package:code_builder/src/builders/class.dart'; +import 'package:code_builder/src/builders/parameter.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:code_builder/src/builders/type.dart'; +import 'package:code_builder/src/tokens.dart'; + +/// Short-hand for `new ConstructorBuilder(...)`. +ConstructorBuilder constructor( + [Iterable members = const []]) { + return _constructorImpl(members: members); +} + +/// Short-hand for `new ConstructorBuilder(name)`. +ConstructorBuilder constructorNamed(String name, + [Iterable members = const []]) { + return _constructorImpl(name: name, members: members); +} + +/// Short-hand for `new MethodBuilder.getter(...)`. +MethodBuilder getter( + String name, { + Iterable statements, + ExpressionBuilder returns, + TypeBuilder returnType, +}) { + if (returns != null) { + return new MethodBuilder.getter( + name, + returnType: returnType, + returns: returns, + ); + } else { + return new MethodBuilder.getter( + name, + returnType: returnType, + )..addStatements(statements); + } +} + +/// A more short-hand way of constructing a Lambda [MethodBuilder]. +MethodBuilder lambda( + String name, + ExpressionBuilder value, { + TypeBuilder returnType, +}) { + return new MethodBuilder(name, returns: value, returnType: returnType); +} + +/// A more short-hand way of constructing a [MethodBuilder]. +MethodBuilder method( + String name, [ + Iterable members = const [], +]) { + final List positional = []; + final List<_NamedParameterWrapper> named = <_NamedParameterWrapper>[]; + final List statements = []; + TypeBuilder returnType; + for (final member in members) { + if (member is TypeBuilder) { + returnType = member; + } else if (member is ParameterBuilder) { + positional.add(member); + } else if (member is _NamedParameterWrapper) { + named.add(member); + } else if (member is StatementBuilder) { + statements.add(member); + } else { + throw new StateError('Invalid AST type: ${member.runtimeType}'); + } + } + final method = new _MethodBuilderImpl( + name, + returns: returnType, + ); + positional.forEach(method.addPositional); + named.forEach((p) => method.addNamed(p._parameter)); + statements.forEach(method.addStatement); + return method; +} + +/// Returns a wrapper around [parameter] for use with [method]. +_NamedParameterWrapper named(ParameterBuilder parameter) { + return new _NamedParameterWrapper(parameter); +} + +/// Short-hand for `new MethodBuilder.setter(...)`. +MethodBuilder setter( + String name, + ParameterBuilder value, + Iterable statements, +) { + return new MethodBuilder.setter(name) + ..addPositional(value) + ..addStatements(statements); +} + +/// Returns a wrapper around [parameter] for use with [constructor]. +_FieldParameterWrapper thisField(Object parameter) { + assert(parameter is ParameterBuilder || parameter is _NamedParameterWrapper); + return new _FieldParameterWrapper(parameter); +} + +ConstructorBuilder _constructorImpl({ + Iterable members, + String name, +}) { + final List<_AddParameter> _addFunctions = <_AddParameter>[]; + for (final member in members) { + if (member is ParameterBuilder) { + _addFunctions.add((c) => c.addPositional(member)); + } else if (member is _NamedParameterWrapper) { + _addFunctions.add((c) => c.addNamed(member._parameter)); + } else if (member is _FieldParameterWrapper) { + if (member._parameter is _NamedParameterWrapper) { + _NamedParameterWrapper p = member._parameter; + _addFunctions.add((c) => c.addNamed(p._parameter, asField: true)); + } else if (member._parameter is ParameterBuilder) { + _addFunctions + .add((c) => c.addPositional(member._parameter, asField: true)); + } + } else if (member is StatementBuilder) { + _addFunctions.add((c) => c.addStatement(member)); + } else { + throw new StateError('Invalid AST type: ${member.runtimeType}'); + } + } + final constructor = new ConstructorBuilder(name); + _addFunctions.forEach((a) => a(constructor)); + return constructor; +} + +typedef void _AddParameter(ConstructorBuilder constructor); + +/// Lazily builds an [ConstructorBuilder] AST when built. +abstract class ConstructorBuilder + implements + AstBuilder, + HasParameters, + HasStatements, + ValidClassMember { + /// Create a new [ConstructorBuilder], optionally with a [name]. + factory ConstructorBuilder([String name]) = _NormalConstructorBuilder; + + @override + void addNamed(ParameterBuilder parameter, {bool asField: false}); + + @override + void addPositional(ParameterBuilder parameter, {bool asField: false}); + + /// Returns an [ConstructorDeclaration] AST representing the builder. + ConstructorDeclaration buildConstructor(TypeBuilder returnType, + [Scope scope]); +} + +/// Lazily builds a method/function AST when the builder is invoked. +abstract class MethodBuilder + implements HasAnnotations, HasParameters, HasStatements, ValidClassMember { + /// Creates a new [MethodBuilder]. + factory MethodBuilder(String name, + {ExpressionBuilder returns, TypeBuilder returnType}) { + if (returns != null) { + return new _LambdaMethodBuilder( + name, + returns, + returnType, + null, + ); + } else { + return new _MethodBuilderImpl( + name, + returns: returnType, + ); + } + } + + /// Creates a getter. + factory MethodBuilder.getter( + String name, { + TypeBuilder returnType, + ExpressionBuilder returns, + }) { + if (returns == null) { + return new _MethodBuilderImpl( + name, + returns: returnType, + property: Keyword.GET, + ); + } else { + return new _LambdaMethodBuilder( + name, + returns, + returnType, + Keyword.GET, + ); + } + } + + /// Creates a new [MethodBuilder] that returns `void`. + factory MethodBuilder.returnVoid(String name, {ExpressionBuilder returns}) { + if (returns == null) { + return new _MethodBuilderImpl(name, returns: lib$core.$void); + } + return new _LambdaMethodBuilder( + name, + returns, + lib$core.$void, + null, + ); + } + + /// Creates a setter. + factory MethodBuilder.setter( + String name, { + ExpressionBuilder returns, + }) { + if (returns == null) { + return new _MethodBuilderImpl( + name, + property: Keyword.SET, + ); + } else { + return new _LambdaMethodBuilder( + name, + returns, + null, + Keyword.SET, + ); + } + } + + /// Returns a [FunctionDeclaration] AST representing the builder. + FunctionDeclaration buildFunction([Scope scope]); + + /// Returns an [MethodDeclaration] AST representing the builder. + MethodDeclaration buildMethod(bool static, [Scope scope]); +} + +/// A marker interface for an AST that could be added to [ConstructorBuilder]. +abstract class ValidConstructorMember implements ValidMethodMember {} + +/// A marker interface for an AST that could be added to [MethodBuilder]. +abstract class ValidMethodMember implements AstBuilder {} + +class _FieldParameterWrapper + implements ValidConstructorMember, ValidMethodMember { + final Object /*ParameterBuilder|_NamedParameterWrapper*/ _parameter; + + _FieldParameterWrapper(this._parameter); + + @override + AstNode buildAst([_]) => throw new UnsupportedError('Use within method'); +} + +class _LambdaMethodBuilder extends Object + with HasAnnotationsMixin, HasParametersMixin + implements MethodBuilder { + final ExpressionBuilder _expression; + final String _name; + final TypeBuilder _returnType; + final Keyword _property; + + _LambdaMethodBuilder( + this._name, this._expression, this._returnType, this._property); + + @override + void addStatement(StatementBuilder statement) { + throw new UnsupportedError('Cannot add statement on a Lambda method'); + } + + @override + void addStatements(Iterable statements) { + throw new UnsupportedError('Cannot add statement on a Lambda method'); + } + + @override + AstNode buildAst([Scope scope]) => buildFunction(scope); + + @override + FunctionDeclaration buildFunction([Scope scope]) { + return new FunctionDeclaration( + null, + buildAnnotations(scope), + null, + _returnType?.buildType(scope), + _property != null ? new KeywordToken(_property, 0) : null, + identifier(scope, _name), + new FunctionExpression( + null, + _property != Keyword.GET ? buildParameterList(scope) : null, + new ExpressionFunctionBody( + null, + null, + _expression.buildExpression(scope), + $semicolon, + ), + ), + ); + } + + @override + MethodDeclaration buildMethod(bool static, [Scope scope]) { + return new MethodDeclaration( + null, + buildAnnotations(scope), + null, + static ? $static : null, + _returnType?.buildType(scope), + _property != null ? new KeywordToken(_property, 0) : null, + null, + stringIdentifier(_name), + null, + _property != Keyword.GET ? buildParameterList(scope) : null, + new ExpressionFunctionBody( + null, + null, + _expression.buildExpression(scope), + $semicolon, + ), + ); + } +} + +class _MethodBuilderImpl extends Object + with HasAnnotationsMixin, HasParametersMixin, HasStatementsMixin + implements MethodBuilder { + final String _name; + final TypeBuilder _returnType; + final Keyword _property; + + _MethodBuilderImpl( + this._name, { + TypeBuilder returns, + Keyword property, + }) + : _returnType = returns, + _property = property; + + @override + AstNode buildAst([Scope scope]) => buildFunction(scope); + + @override + FunctionDeclaration buildFunction([Scope scope]) { + return new FunctionDeclaration( + null, + buildAnnotations(scope), + null, + _returnType?.buildType(scope), + _property != null ? new KeywordToken(_property, 0) : null, + identifier(scope, _name), + new FunctionExpression( + null, + _property != Keyword.GET ? buildParameterList(scope) : null, + !hasStatements + ? new EmptyFunctionBody($semicolon) + : new BlockFunctionBody( + null, + null, + buildBlock(scope), + ), + ), + ); + } + + @override + MethodDeclaration buildMethod(bool static, [Scope scope]) { + return new MethodDeclaration( + null, + buildAnnotations(scope), + null, + static ? $static : null, + _returnType?.buildType(scope), + _property != null ? new KeywordToken(_property, 0) : null, + null, + identifier(scope, _name), + null, + _property != Keyword.GET ? buildParameterList(scope) : null, + !hasStatements + ? new EmptyFunctionBody($semicolon) + : new BlockFunctionBody( + null, + null, + buildBlock(scope), + ), + ); + } +} + +class _NamedParameterWrapper + implements ValidConstructorMember, ValidMethodMember { + final ParameterBuilder _parameter; + + _NamedParameterWrapper(this._parameter); + + @override + AstNode buildAst([_]) => throw new UnsupportedError('Use within method'); +} + +class _NormalConstructorBuilder extends Object + with HasAnnotationsMixin, HasParametersMixin, HasStatementsMixin + implements ConstructorBuilder { + final String _name; + + _NormalConstructorBuilder([this._name]); + + @override + ConstructorDeclaration buildAst([Scope scope]) { + throw new UnsupportedError('Can only be built as part of a class.'); + } + + @override + ConstructorDeclaration buildConstructor(TypeBuilder returnType, + [Scope scope]) { + return new ConstructorDeclaration( + null, + buildAnnotations(scope), + null, + null, + null, + returnType.buildType().name, + _name != null ? $period : null, + _name != null ? stringIdentifier(_name) : null, + buildParameterList(scope), + null, + null, + null, + !hasStatements + ? new EmptyFunctionBody($semicolon) + : new BlockFunctionBody( + null, + null, + buildBlock(scope), + ), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/method_builder.dart b/pkgs/code_builder/lib/src/builders/method_builder.dart deleted file mode 100644 index 252c836cd..000000000 --- a/pkgs/code_builder/lib/src/builders/method_builder.dart +++ /dev/null @@ -1,192 +0,0 @@ -// 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. - -part of code_builder; - -/// Builds either a [MethodDeclaration] or a [FunctionDeclaration]. -/// -/// While the API is the same, you may specifically ask for either a method -/// AST (for class members) via [toMethodAst] or a function AST (used both at -/// the top level and within other methods) via [toFunctionAst]. -/// -/// To return nothing (`void`), use [MethodBuilder.returnVoid]. -class MethodBuilder implements CodeBuilder { - // Void is a "type" that is only valid as a return type on a method. - static const TypeBuilder _typeVoid = const TypeBuilder('void'); - - final List _annotations = []; - final String _name; - final List _parameters = []; - final List _statements = []; - - final bool _isAbstract; - final bool _isStatic; - - ExpressionBuilder _returnExpression; - TypeBuilder _returnType; - - /// Create a new method builder, - /// - /// Optionally set a [returns] type. - factory MethodBuilder({ - String name, - TypeBuilder returns, - bool abstract: false, - bool static: false, - }) { - return new MethodBuilder._(name, returns, static, abstract); - } - - /// Creates a `void`-returning MethodBuilder with [name]. - factory MethodBuilder.returnVoid({ - String name, - bool abstract: false, - bool static: false, - }) { - return new MethodBuilder._(name, _typeVoid, static, abstract); - } - - MethodBuilder._( - this._name, - this._returnType, - this._isStatic, - this._isAbstract, - ); - - /// Lazily adds [annotation]. - /// - /// When the method is emitted as an AST, [AnnotationBuilder.toAst] is used. - void addAnnotation(AnnotationBuilder annotation) { - _annotations.add(annotation); - } - - /// Lazily adds [parameter]. - /// - /// When the method is emitted as an AST, [ParameterBuilder.toAst] is used. - void addParameter(ParameterBuilder parameter) { - _parameters.add(parameter); - } - - /// Lazily adds [statement]. - /// - /// When the method is emitted as an AST, [StatementBuilder.toAst] is used. - void addStatement(StatementBuilder statement) { - _statements.add(statement); - } - - /// Lazily sets [expression] as the lambda result of this method invocation. - /// - /// When the method is emitted as an AST, [ExpressionBuilder.toAst] is used. - void setExpression(ExpressionBuilder expression) { - _returnExpression = expression; - } - - /// Returns a copy-safe [AstNode] representing the current builder state. - /// - /// **NOTE**: This method exists primarily for testing and compatibility with - /// the [CodeBuilder] ADT. When possible, invoke [toFunctionAst] or - /// [toMethodAst]. - @override - @visibleForTesting - Declaration toAst([Scope scope = const Scope.identity()]) => - toFunctionAst(scope); - - /// Returns a copy-safe [FunctionDeclaration] AST representing current state. - FunctionDeclaration toFunctionAst([Scope scope = const Scope.identity()]) { - var functionAst = _emptyFunction() - ..metadata.addAll(_annotations.map/**/((a) => a.toAst(scope))) - ..name = _stringIdentifier(_name) - ..returnType = _returnType?.toAst(scope); - if (_returnExpression != null) { - functionAst.functionExpression = _returnExpression.toFunctionExpression(); - } else { - functionAst.functionExpression = new FunctionExpression( - null, - _emptyParameters(), - _blockBody(_statements.map/**/((s) => s.toAst(scope))), - ); - } - if (_parameters.isNotEmpty) { - functionAst.functionExpression.parameters.parameters - .addAll(_parameters.map/**/((p) => p.toAst(scope))); - } - return functionAst; - } - - /// Returns a copy-safe [FunctionDeclaration] AST representing current state. - MethodDeclaration toMethodAst([Scope scope = const Scope.identity()]) { - var methodAst = _emptyMethod() - ..metadata.addAll(_annotations.map/**/((a) => a.toAst(scope))) - ..name = _stringIdentifier(_name) - ..returnType = _returnType?.toAst(scope); - FunctionBody methodBody = _returnExpression?.toFunctionBody(scope); - if (_isStatic) { - methodAst.modifierKeyword = $static; - if (methodBody == null) { - methodBody = _blockBody(); - } - } - if (methodBody == null) { - methodBody = _isAbstract - ? new EmptyFunctionBody($semicolon) - : _blockBody(_statements.map/**/((s) => s.toAst(scope))); - } - if (_parameters.isNotEmpty) { - methodAst.parameters.parameters - .addAll(_parameters.map/**/((p) => p.toAst(scope))); - } - methodAst.body = methodBody; - return methodAst; - } - - @override - String toString() => 'MethodBuilder ${toAst().toSource()}'; - - static FunctionBody _blockBody([Iterable statements]) => - new BlockFunctionBody( - null, - null, - new Block( - $openCurly, - statements?.toList(), - $closeCurly, - ), - ); - - static FunctionDeclaration _emptyFunction() => new FunctionDeclaration( - null, - null, - null, - null, - null, - null, - new FunctionExpression( - null, - _emptyParameters(), - _blockBody(), - ), - ); - // TODO: implement requiredImports - static MethodDeclaration _emptyMethod() => new MethodDeclaration( - null, - null, - null, - null, - null, - null, - null, - null, - null, - _emptyParameters(), - null, - ); - - static FormalParameterList _emptyParameters() => new FormalParameterList( - $openParen, - [], - null, - null, - $closeParen, - ); -} diff --git a/pkgs/code_builder/lib/src/builders/parameter.dart b/pkgs/code_builder/lib/src/builders/parameter.dart new file mode 100644 index 000000000..58df28e33 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/parameter.dart @@ -0,0 +1,213 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/src/builders/annotation.dart'; +import 'package:code_builder/src/builders/method.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/type.dart'; +import 'package:code_builder/src/tokens.dart'; + +/// A short-hand way of constructing a [ParameterBuilder]. +ParameterBuilder parameter( + String name, [ + Iterable members = const [], +]) { + final List annotations = []; + ExpressionBuilder defaultTo; + bool defaultToSet = false; + TypeBuilder type; + for (final member in members) { + if (member is TypeBuilder) { + type = member; + } else if (member is AnnotationBuilder) { + annotations.add(member); + } else if (member is ExpressionBuilder) { + defaultTo = member; + defaultToSet = true; + } else { + throw new StateError('Invalid AST type: ${member.runtimeType}'); + } + } + var builder = new ParameterBuilder( + name, + type: type, + )..addAnnotations(annotations); + if (defaultToSet) { + builder = builder.asOptional(defaultTo); + } + return builder; +} + +/// An [AstBuilder] that can be built up using [ParameterBuilder]. +abstract class HasParameters implements AstBuilder { + /// Adds [parameter] to the builder. + void addNamed(ParameterBuilder parameter); + + /// Adds [parameter] to the builder. + void addPositional(ParameterBuilder parameter); +} + +/// Implements [HasParameters]. +abstract class HasParametersMixin implements HasParameters { + final List<_ParameterPair> _parameters = <_ParameterPair>[]; + + @override + void addNamed(ParameterBuilder parameter, {bool asField: false}) { + _parameters.add(new _ParameterPair.named(parameter, field: asField)); + } + + @override + void addPositional(ParameterBuilder parameter, {bool asField: false}) { + _parameters.add(new _ParameterPair(parameter, field: asField)); + } + + /// Builds a [FormalParameterList]. + FormalParameterList buildParameterList([Scope scope]) { + return new FormalParameterList( + $openParen, + _parameters + .map/**/((p) => p.buildParameter(scope)) + .toList(), + null, + null, + $closeParen, + ); + } +} + +/// Lazily builds an [FormalParameter] AST the builder is invoked. +abstract class ParameterBuilder + implements + AstBuilder, + HasAnnotations, + ValidConstructorMember, + ValidMethodMember { + /// Create a new builder for parameter [name]. + factory ParameterBuilder( + String name, { + TypeBuilder type, + }) = _SimpleParameterBuilder; + + /// Returns as an optional [ParameterBuilder] set to [defaultTo]. + ParameterBuilder asOptional([ExpressionBuilder defaultTo]); + + /// Returns a positional [FormalParameter] AST representing the builder. + FormalParameter buildNamed(bool field, [Scope scope]); + + /// Returns a positional [FormalParameter] AST representing the builder. + FormalParameter buildPositional(bool field, [Scope scope]); +} + +/// A marker interface for an AST that could be added to [ParameterBuilder]. +abstract class ValidParameterMember implements AstBuilder {} + +class _OptionalParameterBuilder extends Object + with HasAnnotationsMixin + implements ParameterBuilder { + final ParameterBuilder _parameter; + final ExpressionBuilder _expression; + + _OptionalParameterBuilder(this._parameter, [this._expression]); + + @override + ParameterBuilder asOptional([ExpressionBuilder defaultTo]) { + return new _OptionalParameterBuilder(_parameter, defaultTo); + } + + @override + FormalParameter buildAst([Scope scope]) => buildPositional(false, scope); + + @override + FormalParameter buildNamed(bool field, [Scope scope]) { + return new DefaultFormalParameter( + _parameter.buildPositional(field, scope), + ParameterKind.NAMED, + _expression != null ? $colon : null, + _expression?.buildExpression(scope), + ); + } + + @override + FormalParameter buildPositional(bool field, [Scope scope]) { + return new DefaultFormalParameter( + _parameter.buildPositional(field, scope), + ParameterKind.POSITIONAL, + _expression != null ? $equals : null, + _expression?.buildExpression(scope), + ); + } +} + +class _ParameterPair { + final bool _isField; + final bool _isNamed; + final ParameterBuilder _parameter; + + _ParameterPair(this._parameter, {bool field: false}) + : _isNamed = false, + _isField = field; + + _ParameterPair.named(this._parameter, {bool field: false}) + : _isNamed = true, + _isField = field; + + FormalParameter buildParameter([Scope scope]) { + return _isNamed + ? _parameter.buildNamed(_isField, scope) + : _parameter.buildPositional(_isField, scope); + } +} + +class _SimpleParameterBuilder extends Object + with HasAnnotationsMixin + implements ParameterBuilder { + final String _name; + final TypeBuilder _type; + + _SimpleParameterBuilder( + String name, { + TypeBuilder type, + }) + : _name = name, + _type = type; + + @override + ParameterBuilder asOptional([ExpressionBuilder defaultTo]) { + return new _OptionalParameterBuilder(this, defaultTo); + } + + @override + FormalParameter buildAst([Scope scope]) => buildPositional(false, scope); + + @override + FormalParameter buildNamed(bool field, [Scope scope]) { + return asOptional().buildNamed(field, scope); + } + + @override + FormalParameter buildPositional(bool field, [Scope scope]) { + if (field) { + return new FieldFormalParameter( + null, + buildAnnotations(scope), + null, + _type?.buildType(scope), + $this, + $period, + stringIdentifier(_name), + null, + null, + ); + } + return new SimpleFormalParameter( + null, + buildAnnotations(scope), + null, + _type?.buildType(scope), + stringIdentifier(_name), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/parameter_builder.dart b/pkgs/code_builder/lib/src/builders/parameter_builder.dart deleted file mode 100644 index 9f38cd47c..000000000 --- a/pkgs/code_builder/lib/src/builders/parameter_builder.dart +++ /dev/null @@ -1,159 +0,0 @@ -// 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. - -part of code_builder; - -/// Build a [FormalParameter] AST. -/// -/// A parameter is part of a built [MethodBuilder], and can refer to a -/// class-member (field) variable (see the `field` property in the -/// constructors). -class ParameterBuilder implements CodeBuilder { - final String _name; - final bool _isField; - final bool _isOptional; - final bool _isNamed; - final TypeBuilder _type; - final ExpressionBuilder _defaultTo; - - final List _annotations = []; - - /// Create a new _required_ parameter of [name]. - factory ParameterBuilder( - String name, { - bool field: false, - TypeBuilder type, - }) { - return new ParameterBuilder._( - name, - field, - false, - false, - type, - null, - ); - } - - /// Create a new _optional_ _named_ parameter. - factory ParameterBuilder.named( - String name, { - bool field: false, - TypeBuilder type, - ExpressionBuilder defaultTo, - }) { - return new ParameterBuilder._optional( - name, - true, - field: field, - type: type, - defaultTo: defaultTo, - ); - } - - /// Create a new _optional_ (but positional) parameter. - /// - /// See [ParameterBuilder.named] for an optional _named_ parameter. - factory ParameterBuilder.optional( - String name, { - bool field: false, - TypeBuilder type, - ExpressionBuilder defaultTo, - }) { - return new ParameterBuilder._optional( - name, - false, - field: field, - type: type, - defaultTo: defaultTo, - ); - } - - ParameterBuilder._( - this._name, - this._isField, - this._isOptional, - this._isNamed, - this._type, - this._defaultTo, - ); - - // Actual implementation of optional and named. - factory ParameterBuilder._optional( - String name, - bool named, { - bool field: false, - TypeBuilder type, - ExpressionBuilder defaultTo, - }) { - return new ParameterBuilder._( - name, - field, - true, - named, - type, - defaultTo, - ); - } - - /// Adds a metadata annotation from [builder]. - void addAnnotation(AnnotationBuilder builder) { - _annotations.add(builder); - } - - @override - FormalParameter toAst([Scope scope = const Scope.identity()]) { - FormalParameter astNode; - if (_isField) { - astNode = _createFieldFormalParameter(scope); - } else { - astNode = _createSimpleFormalParameter(scope); - } - if (_isOptional) { - astNode = _createDefaultFormalParameter( - astNode, - _isNamed, - _defaultTo, - scope, - ); - } - astNode.metadata.addAll(_annotations.map/**/((a) => a.toAst())); - return astNode; - } - - FieldFormalParameter _createFieldFormalParameter(Scope scope) => - new FieldFormalParameter( - null, - null, - null, - _type?.toAst(scope), - $this, - null, - _stringIdentifier(_name), - null, - null, - ); - - SimpleFormalParameter _createSimpleFormalParameter(Scope scope) => - new SimpleFormalParameter( - null, - null, - null, - _type?.toAst(scope), - _stringIdentifier(_name), - ); - - static DefaultFormalParameter _createDefaultFormalParameter( - FormalParameter parameter, - bool named, - ExpressionBuilder defaultTo, - Scope scope, - ) { - return new DefaultFormalParameter( - parameter, - named ? ParameterKind.NAMED : ParameterKind.POSITIONAL, - defaultTo != null ? named ? $colon : $equals : null, - defaultTo?.toAst(), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/reference.dart b/pkgs/code_builder/lib/src/builders/reference.dart new file mode 100644 index 000000000..31be042ec --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/reference.dart @@ -0,0 +1,56 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/src/builders/annotation.dart'; +import 'package:code_builder/src/builders/expression.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/type.dart'; +import 'package:code_builder/src/tokens.dart'; + +/// An explicit reference to `this`. +final ReferenceBuilder explicitThis = reference('this'); + +/// Creates a reference called [name]. +ReferenceBuilder reference(String name, [String importUri]) { + return new ReferenceBuilder._(name, importUri); +} + +/// An abstract way of representing other types of [AstBuilder]. +class ReferenceBuilder extends Object + with AbstractExpressionMixin, AbstractTypeBuilderMixin + implements AnnotationBuilder, ExpressionBuilder, TypeBuilder { + final String _importFrom; + final String _name; + + ReferenceBuilder._(this._name, [this._importFrom]); + + @override + Annotation buildAnnotation([Scope scope]) { + return new Annotation( + $at, + stringIdentifier(_name), + null, + null, + null, + ); + } + + @override + AstNode buildAst([Scope scope]) => throw new UnimplementedError(); + + @override + Expression buildExpression([Scope scope]) { + return identifier( + scope, + _name, + _importFrom, + ); + } + + @override + TypeName buildType([Scope scope]) { + return new TypeBuilder(_name, _importFrom).buildType(scope); + } +} diff --git a/pkgs/code_builder/lib/src/builders/shared.dart b/pkgs/code_builder/lib/src/builders/shared.dart new file mode 100644 index 000000000..3c1626405 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/shared.dart @@ -0,0 +1,27 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/src/scope.dart'; +import 'package:code_builder/src/tokens.dart'; + +export 'package:code_builder/src/scope.dart'; + +/// Returns a string [Literal] from [value]. +Identifier stringIdentifier(String value) => + new SimpleIdentifier(stringToken(value)); + +/// Lazily builds an analyzer [AstNode] when [buildAst] is invoked. +/// +/// Most builders should also have specific typed methods for returning their +/// type of AST node, such as `buildExpression` for returning an `Expression` +/// AST. +abstract class AstBuilder { + /// Returns an [AstNode] representing the state of the current builder. + /// + /// If [scope] is provided then identifiers are automatically prefixed and + /// imports are collected in order to emit a final File AST that does not + /// have conflicting or missing imports. + T buildAst([Scope scope]); +} diff --git a/pkgs/code_builder/lib/src/builders/statement.dart b/pkgs/code_builder/lib/src/builders/statement.dart new file mode 100644 index 000000000..d12b048c4 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/statement.dart @@ -0,0 +1,71 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/src/builders/method.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement/if.dart'; +import 'package:code_builder/src/tokens.dart'; + +export 'package:code_builder/src/builders/statement/if.dart' + show IfStatementBuilder, elseIf, elseThen, ifThen; + +/// An [AstBuilder] that can add [StatementBuilder]. +abstract class HasStatements implements AstBuilder { + /// Adds [statement] to the builder. + void addStatement(StatementBuilder statement); + + /// Adds [statements] to the builder. + void addStatements(Iterable statements); +} + +/// Implements [HasStatements]. +abstract class HasStatementsMixin implements HasStatements { + final List _statements = []; + + @override + void addStatement(StatementBuilder statement) { + _statements.add(statement); + } + + @override + void addStatements(Iterable statements) { + _statements.addAll(statements); + } + + /// Returns a [Block] statement. + Block buildBlock([Scope scope]) { + return new Block( + $openCurly, + buildStatements(scope), + $closeCurly, + ); + } + + /// Returns a [List] of all built [Statement]s. + List buildStatements([Scope scope]) { + return _statements + .map/**/((e) => e.buildStatement(scope)) + .toList(); + } + + /// Clones all expressions to [clone]. + void cloneStatementsTo(HasStatements clone) { + clone.addStatements(_statements); + } + + /// Whether at least one statement was added. + bool get hasStatements => _statements.isNotEmpty; +} + +/// Lazily builds an [Statement] AST when [buildStatement] is invoked. +abstract class StatementBuilder + implements + AstBuilder, + ValidIfStatementMember, + ValidConstructorMember, + ValidMethodMember { + /// Returns an [Statement] AST representing the builder. + Statement buildStatement([Scope scope]); +} diff --git a/pkgs/code_builder/lib/src/builders/statement/block.dart b/pkgs/code_builder/lib/src/builders/statement/block.dart new file mode 100644 index 000000000..57ef9ebef --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/statement/block.dart @@ -0,0 +1,27 @@ +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:code_builder/src/tokens.dart'; + +/// Represents a series of [StatementBuilder]s as a block statement AST. +abstract class BlockStatementBuilder + implements HasStatements, StatementBuilder { + /// Creates a new [BlockStatementBuilder]. + factory BlockStatementBuilder() = _BlockStatementBuilder; +} + +class _BlockStatementBuilder extends Object + with HasStatementsMixin + implements BlockStatementBuilder { + @override + AstNode buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) { + return new Block( + $openCurly, + buildStatements(scope), + $closeCurly, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/statement/if.dart b/pkgs/code_builder/lib/src/builders/statement/if.dart new file mode 100644 index 000000000..ad3b9a9f7 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/statement/if.dart @@ -0,0 +1,95 @@ +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:code_builder/src/builders/expression.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:code_builder/src/builders/statement/block.dart'; +import 'package:code_builder/src/tokens.dart'; + +/// Denotes an [ifStmt] that should be added as an `else if` in [ifThen]. +_IfStatementBuilderWrapper elseIf(IfStatementBuilder ifStmt) { + return new _IfStatementBuilderWrapper(ifStmt, null); +} + +/// Denotes a series of [statements] added to a final `else` in [ifThen]. +_IfStatementBuilderWrapper elseThen(Iterable statements) { + return new _IfStatementBuilderWrapper(null, statements); +} + +/// Short-hand syntax for `new IfStatementBuilder(...)`. +IfStatementBuilder ifThen( + ExpressionBuilder condition, [ + Iterable members = const [], +]) { + final ifStmt = new IfStatementBuilder(condition); + IfStatementBuilder current = ifStmt; + for (final member in members) { + if (member is _IfStatementBuilderWrapper) { + if (member._ifStmt != null) { + current.setElse(member._ifStmt); + current = member._ifStmt; + } else { + current.setElse( + new BlockStatementBuilder()..addStatements(member._elseStmts)); + current = null; + } + } else if (member is StatementBuilder) { + ifStmt.addStatement(member); + } else { + throw new UnsupportedError('Invalid type: ${member.runtimeType}'); + } + } + return ifStmt; +} + +/// Builds an [IfStatement] AST. +abstract class IfStatementBuilder implements HasStatements, StatementBuilder { + /// Returns a new [IfStatementBuilder] where `if (condition) {`. + factory IfStatementBuilder(ExpressionBuilder condition) { + return new _BlockIfStatementBuilder(condition); + } + + /// Adds an `else` block that evaluates [statements]. + void setElse(StatementBuilder statements); +} + +/// Marker interface for builders valid for use with [ifThen]. +abstract class ValidIfStatementMember implements AstBuilder {} + +class _BlockIfStatementBuilder extends HasStatementsMixin + implements IfStatementBuilder { + final ExpressionBuilder _condition; + StatementBuilder _elseBlock; + + _BlockIfStatementBuilder(this._condition); + + @override + AstNode buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) { + return new IfStatement( + $if, + $openParen, + _condition.buildExpression(scope), + $closeParen, + buildBlock(scope), + _elseBlock != null ? $else : null, + _elseBlock?.buildStatement(scope), + ); + } + + @override + void setElse(StatementBuilder statements) { + _elseBlock = statements; + } +} + +class _IfStatementBuilderWrapper implements ValidIfStatementMember { + final IfStatementBuilder _ifStmt; + final Iterable _elseStmts; + + _IfStatementBuilderWrapper(this._ifStmt, this._elseStmts); + + @override + AstNode buildAst([_]) => throw new UnsupportedError('Use within ifThen.'); +} diff --git a/pkgs/code_builder/lib/src/builders/statement_builder.dart b/pkgs/code_builder/lib/src/builders/statement_builder.dart deleted file mode 100644 index 683753d5d..000000000 --- a/pkgs/code_builder/lib/src/builders/statement_builder.dart +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -part of code_builder; - -/// Builds a [Statement] AST. -abstract class StatementBuilder implements CodeBuilder { - StatementBuilder._sealed(); -} - -class _ExpressionStatementBuilder implements StatementBuilder { - final ExpressionBuilder _expression; - - _ExpressionStatementBuilder(this._expression); - - @override - Statement toAst([Scope scope = const Scope.identity()]) { - return new ExpressionStatement( - _expression.toAst(scope), - $semicolon, - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/type.dart b/pkgs/code_builder/lib/src/builders/type.dart new file mode 100644 index 000000000..c4eae10c0 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/type.dart @@ -0,0 +1,99 @@ +// 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. + +library code_builder.src.builders.type; + +import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/src/dart/ast/token.dart'; +import 'package:code_builder/src/builders/annotation.dart'; +import 'package:code_builder/src/builders/expression.dart'; +import 'package:code_builder/src/builders/method.dart'; +import 'package:code_builder/src/builders/parameter.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/tokens.dart'; + +part 'type/new_instance.dart'; + +/// Implements the `new` and `const` constructor calls. +abstract class AbstractTypeBuilderMixin { + /// Invokes `const` on this type. + NewInstanceBuilder constInstance( + Iterable positional, [ + Map named = const {}, + ]) { + final builder = new NewInstanceBuilder._const(this); + _addArguments(builder, positional, named); + return builder; + } + + /// Invokes `const` on this type with a [name]d constructor. + NewInstanceBuilder namedConstInstance( + String name, + Iterable positional, [ + Map named = const {}, + ]) { + final builder = new NewInstanceBuilder._const(this, name); + _addArguments(builder, positional, named); + return builder; + } + + /// Invokes `new` on this type. + NewInstanceBuilder newInstance( + Iterable positional, [ + Map named = const {}, + ]) { + final builder = new NewInstanceBuilder._new(this); + _addArguments(builder, positional, named); + return builder; + } + + /// Invokes `new` on this type with a [name]d constructor. + NewInstanceBuilder namedNewInstance( + String name, + Iterable positional, [ + Map named = const {}, + ]) { + final builder = new NewInstanceBuilder._new(this, name); + _addArguments(builder, positional, named); + return builder; + } + + static void _addArguments( + NewInstanceBuilder builder, + Iterable positional, + Map named, + ) { + positional.forEach(builder.addPositionalArgument); + named.forEach(builder.addNamedArgument); + } +} + +/// Lazily builds an [TypeName] AST when [buildType] is invoked. +class TypeBuilder extends Object + with AbstractTypeBuilderMixin + implements AstBuilder, ValidMethodMember, ValidParameterMember { + final String _importFrom; + final String _name; + + /// Creates a new [TypeBuilder]. + factory TypeBuilder(String name, [String importFrom]) = TypeBuilder._; + + TypeBuilder._(this._name, [this._importFrom]); + + @override + AstNode buildAst([Scope scope]) => buildType(scope); + + /// Returns an [TypeName] AST representing the builder. + TypeName buildType([Scope scope]) { + return new TypeName( + identifier( + scope, + _name, + _importFrom, + ), + null, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/type/new_instance.dart b/pkgs/code_builder/lib/src/builders/type/new_instance.dart new file mode 100644 index 000000000..c2d9b6887 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/type/new_instance.dart @@ -0,0 +1,53 @@ +part of code_builder.src.builders.type; + +/// Lazily builds an [InstanceCreationExpression] AST when built. +/// +/// See [TypeBuilder]: +/// - [TypeBuilder.constInstance] +/// - [TypeBuilder.namedConstInstance] +/// - [TypeBuilder.newInstance] +/// - [TypeBuilder.namedNewInstance] +abstract class NewInstanceBuilder + implements AnnotationBuilder, InvocationBuilder { + factory NewInstanceBuilder._const(TypeBuilder type, [String name]) { + return new _NewInvocationBuilderImpl(Keyword.CONST, type, name); + } + + factory NewInstanceBuilder._new(TypeBuilder type, [String name]) { + return new _NewInvocationBuilderImpl(Keyword.NEW, type, name); + } +} + +class _NewInvocationBuilderImpl extends Object + with AbstractExpressionMixin, AbstractInvocationBuilderMixin + implements NewInstanceBuilder { + final String _name; + final Keyword _keyword; + final TypeBuilder _type; + + _NewInvocationBuilderImpl(this._keyword, this._type, [this._name]); + + @override + Annotation buildAnnotation([Scope scope]) { + return new Annotation( + $at, + _type.buildType(scope).name, + $period, + _name != null ? stringIdentifier(_name) : null, + buildArgumentList(scope), + ); + } + + @override + Expression buildExpression([Scope scope]) { + return new InstanceCreationExpression( + new KeywordToken(_keyword, 0), + new ConstructorName( + _type.buildType(scope), + _name != null ? $period : null, + _name != null ? stringIdentifier(_name) : null, + ), + buildArgumentList(scope), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/type_builder.dart b/pkgs/code_builder/lib/src/builders/type_builder.dart deleted file mode 100644 index cff6f2f43..000000000 --- a/pkgs/code_builder/lib/src/builders/type_builder.dart +++ /dev/null @@ -1,25 +0,0 @@ -// 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. - -part of code_builder; - -/// Build a [TypeName] AST. -class TypeBuilder implements CodeBuilder { - final String _identifier; - final String _importFrom; - - /// Create a builder for emitting a [TypeName] AST. - /// - /// Optionally specify what must be imported for this type to resolve. - /// - /// __Example use__: - /// const TypeBuilder('String', importFrom: 'dart:core') - const TypeBuilder(this._identifier, {String importFrom}) - : _importFrom = importFrom; - - @override - TypeName toAst([Scope scope = const Scope.identity()]) { - return new TypeName(scope.getIdentifier(_identifier, _importFrom), null); - } -} diff --git a/pkgs/code_builder/lib/src/pretty_printer.dart b/pkgs/code_builder/lib/src/pretty_printer.dart index e1036e0b7..53d332420 100644 --- a/pkgs/code_builder/lib/src/pretty_printer.dart +++ b/pkgs/code_builder/lib/src/pretty_printer.dart @@ -2,7 +2,22 @@ // 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. -part of code_builder; +import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/token.dart'; +import 'package:dart_style/dart_style.dart'; + +import 'analyzer_patch.dart'; + +final _dartFmt = new DartFormatter(); + +/// Returns [source] formatted by `dartfmt`. +String dartfmt(String source) { + try { + return _dartFmt.format(source); + } on FormatterException catch (_) { + return _dartFmt.formatStatement(source); + } +} /// Augments [AstNode.toSource] by adding some whitespace/line breaks. /// @@ -14,13 +29,16 @@ String prettyToSource(AstNode astNode) { var buffer = new PrintBuffer(); var visitor = new _PrettyToSourceVisitor(buffer); astNode.accept(visitor); - return dartfmt(buffer.toString()); + var source = buffer.toString(); + try { + return dartfmt(source); + } on FormatterException catch (_) { + return source; + } } -// TODO(matanl): Remove copied-pasted methods when API becomes available. -// https://github.com/dart-lang/sdk/issues/27169 +// https://github.com/dart-lang/code_builder/issues/16 class _PrettyToSourceVisitor extends ToSourceVisitor { - // https://github.com/dart-lang/sdk/issues/27301 final StringBuffer _buffer; _PrettyToSourceVisitor(PrintBuffer buffer) diff --git a/pkgs/code_builder/lib/src/scope.dart b/pkgs/code_builder/lib/src/scope.dart index f852b0fac..f6f6ec48f 100644 --- a/pkgs/code_builder/lib/src/scope.dart +++ b/pkgs/code_builder/lib/src/scope.dart @@ -2,81 +2,115 @@ // 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. -part of code_builder; +import 'package:analyzer/analyzer.dart'; -/// Determines an [Identifier] deppending on where it appears. +import 'builders/file.dart'; +import 'tokens.dart'; + +/// Returns an identifier for [name], using [scope] to enforce prefixing. +/// +/// It is _required_ within `code_builder` to use this API instead of creating +/// identifeirs manually in places where an obvious API collision could occur +/// (i.e. imported references). +/// +/// If [scope] is null, no prefixing is applied. +/// +/// ## Example +/// // May output `hello.Hello`. +/// identifier(scope, 'Hello', 'pacakge:hello/hello.dart') +Identifier identifier(Scope scope, String name, [String importFrom]) { + return (scope ?? Scope.identity).identifier(name, importFrom); +} + +/// Maintains an imported reference scope to avoid conflicts in generated code. /// -/// __Example use__: +/// ## Example /// void useContext(Scope scope) { -/// // Prints Identifier "i1.Foo" -/// print(scope.getIdentifier('Foo', 'package:foo/foo.dart'); +/// // May print 'i1.Foo'. +/// print(scope.identifier('Foo', 'package:foo/foo.dart')); /// -/// // Prints Identifier "i1.Bar" -/// print(scope.getIdentifier('Bar', 'package:foo/foo.dart'); +/// // May print 'i1.Bar'. +/// print(scope.identifier('Bar', 'package:foo/foo.dart')); /// -/// // Prints Identifier "i2.Baz" -/// print(scope.getIdentifier('Baz', 'package:bar/bar.dart'); +/// // May print 'i2.Bar'. +/// print(scope.getIdentifier('Baz', 'package:bar/bar.dart')); /// } abstract class Scope { - /// Create a default scope context. + /// A no-op [Scope]. Ideal for use for tests or example cases. /// - /// Actual implementation is _not_ guaranteed, only that all import prefixes - /// will be unique in a given scope (actual implementation may be naive). - factory Scope() = _IncrementingScope; + /// **WARNING**: Does not collect import statements. This is only really + /// advisable for use in tests but not production code. To use import + /// collection but not prefixing, see [Scope.dedupe]. + static const Scope identity = const _IdentityScope(); - /// Create a context that just de-duplicates imports (no scoping). - factory Scope.dedupe() = _DeduplicatingScope; + /// Create a new scoping context. + /// + /// Actual implementation of [Scope] is _not_ guaranteed, only that all + /// import prefixes will be unique in a given scope. + factory Scope() = _IncrementingScope; - /// Create a context that does nothing. - const factory Scope.identity() = _IdentityScope; + /// Create a context that just collects and de-duplicates imports. + /// + /// Prefixing is _not_ applied. + factory Scope.dedupe() => new _DeduplicatingScope(); - /// Given a [symbol] and its known [importUri], return an [Identifier]. - Identifier getIdentifier(String symbol, String importUri); + /// Given a [name] and and import path, returns an [Identifier]. + Identifier identifier(String name, String importFrom); - /// Returns a list of all imports needed to resolve identifiers. - Iterable getImports(); + /// Return a list of import statements. + List toImports(); } -class _DeduplicatingScope implements Scope { +class _DeduplicatingScope extends _IdentityScope { final Set _imports = new Set(); @override - Identifier getIdentifier(String symbol, String import) { - _imports.add(import); - return _stringIdentifier(symbol); + Identifier identifier(String name, [String importFrom]) { + if (importFrom != null) { + _imports.add(importFrom); + } + return super.identifier(name); } @override - Iterable getImports() { - return _imports.map/* new ImportBuilder(i)); - } + List toImports() => + _imports.map((uri) => new ImportBuilder(uri)).toList(); } class _IdentityScope implements Scope { const _IdentityScope(); @override - Identifier getIdentifier(String symbol, _) => _stringIdentifier(symbol); + Identifier identifier(String name, [_]) { + return new SimpleIdentifier(stringToken(name)); + } @override - Iterable getImports() => const []; + List toImports() => const []; } -class _IncrementingScope implements Scope { +class _IncrementingScope extends _IdentityScope { final Map _imports = {}; - int _counter = 0; + int _counter = 1; @override - Identifier getIdentifier(String symbol, String import) { - var newId = _imports.putIfAbsent(import, () => ++_counter); + Identifier identifier(String name, [String importFrom]) { + if (importFrom == null) { + return super.identifier(name); + } + var newId = _imports.putIfAbsent(importFrom, () => _counter++); return new PrefixedIdentifier( - _stringIdentifier('_i$newId'), $period, _stringIdentifier(symbol)); + super.identifier('_i$newId'), + $period, + super.identifier(name), + ); } @override - Iterable getImports() { - return _imports.keys.map/* new ImportBuilder(i, prefix: '_i${_imports[i]}')); + List toImports() { + return _imports.keys.map((uri) { + return new ImportBuilder(uri, prefix: '_i${_imports[uri]}'); + }).toList(); } } diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index 2ca6c83b9..17e70b5be 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -5,85 +5,139 @@ import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/src/dart/ast/token.dart'; -// Keywords /// The `abstract` token. final Token $abstract = new KeywordToken(Keyword.ABSTRACT, 0); -/// The `extends` token. -final Token $extends = new KeywordToken(Keyword.EXTENDS, 0); +/// The `as` token. +final Token $as = new KeywordToken(Keyword.AS, 0); -/// The `implements` token. -final Token $implements = new KeywordToken(Keyword.IMPLEMENTS, 0); +/// The `assert` token. +final Token $assert = new KeywordToken(Keyword.ASSERT, 0); -/// The `with` token. -final Token $with = new KeywordToken(Keyword.WITH, 0); +/// The `@` token. +final Token $at = new Token(TokenType.AT, 0); -/// The `static` token. -final Token $static = new KeywordToken(Keyword.STATIC, 0); +/// The `class` token. +final Token $class = new KeywordToken(Keyword.CLASS, 0); -/// The `final` token. -final Token $final = new KeywordToken(Keyword.FINAL, 0); +/// The `]` token. +final Token $closeBracket = new Token(TokenType.CLOSE_SQUARE_BRACKET, 0); + +/// The '}' token. +final Token $closeCurly = new Token(TokenType.CLOSE_CURLY_BRACKET, 0); + +/// The ')' token. +final Token $closeParen = new Token(TokenType.CLOSE_PAREN, 0); + +/// The ':' token. +final Token $colon = new Token(TokenType.COLON, 0); /// The `const` token. final Token $const = new KeywordToken(Keyword.CONST, 0); -/// The `var` token. -final Token $var = new KeywordToken(Keyword.VAR, 0); +/// The `/` token. +final Token $divide = new Token(TokenType.SLASH, 0); -/// The `this` token. -final Token $this = new KeywordToken(Keyword.THIS, 0); +/// The `else` token. +final Token $else = new KeywordToken(Keyword.ELSE, 0); + +/// The '=' token. +final Token $equals = new Token(TokenType.EQ, 0); + +/// The `==` token. +final Token $equalsEquals = new Token(TokenType.EQ_EQ, 0); + +/// The `extends` token. +final Token $extends = new KeywordToken(Keyword.EXTENDS, 0); + +/// The `false` token. +final Token $false = new KeywordToken(Keyword.FALSE, 0); + +/// The `final` token. +final Token $final = new KeywordToken(Keyword.FINAL, 0); + +/// The `>` token. +final Token $gt = new Token(TokenType.GT, 0); + +/// The `if` token. +final Token $if = new KeywordToken(Keyword.IF, 0); + +// Simple tokens + +/// The `implements` token. +final Token $implements = new KeywordToken(Keyword.IMPLEMENTS, 0); /// The `library` token. final Token $library = new KeywordToken(Keyword.LIBRARY, 0); -/// The `part` token. -final Token $part = new KeywordToken(Keyword.PART, 0); +/// The `<` token. +final Token $lt = new Token(TokenType.LT, 0); -/// The `of` token. -final Token $of = new StringToken(TokenType.KEYWORD, 'of', 0); +/// The `-` token. +final Token $minus = new Token(TokenType.MINUS, 0); -/// The `true` token. -final Token $true = new KeywordToken(Keyword.TRUE, 0); +/// The `*` token. +final Token $multiply = new Token(TokenType.STAR, 0); -/// The `false` token. -final Token $false = new KeywordToken(Keyword.FALSE, 0); +/// The `new` token. +final Token $new = new KeywordToken(Keyword.NEW, 0); + +/// The `!` token. +final Token $not = new Token(TokenType.BANG, 0); + +/// The `!=` token. +final Token $notEquals = new Token(TokenType.BANG_EQ, 0); /// The `null` token. final Token $null = new KeywordToken(Keyword.NULL, 0); -/// The `new` token. -final Token $new = new KeywordToken(Keyword.NEW, 0); +/// The '??=' token. +final Token $nullAwareEquals = new Token(TokenType.QUESTION_QUESTION_EQ, 0); -// Simple tokens -/// The '(' token. -final Token $openParen = new Token(TokenType.OPEN_PAREN, 0); +/// The `of` token. +final Token $of = new StringToken(TokenType.KEYWORD, 'of', 0); -/// The ')' token. -final Token $closeParen = new Token(TokenType.CLOSE_PAREN, 0); +/// The '[` token. +final Token $openBracket = new Token(TokenType.OPEN_SQUARE_BRACKET, 0); /// The '{' token. final Token $openCurly = new Token(TokenType.OPEN_CURLY_BRACKET, 0); -/// The '}' token. -final Token $closeCurly = new Token(TokenType.CLOSE_CURLY_BRACKET, 0); +/// The '(' token. +final Token $openParen = new Token(TokenType.OPEN_PAREN, 0); -/// The ':' token. -final Token $colon = new Token(TokenType.COLON, 0); +/// The `part` token. +final Token $part = new KeywordToken(Keyword.PART, 0); + +/// The '.' token. +final Token $period = new Token(TokenType.PERIOD, 0); + +/// The `+` token. +final Token $plus = new Token(TokenType.PLUS, 0); + +/// The `return` token. +final Token $return = new KeywordToken(Keyword.RETURN, 0); /// The ';' token. final Token $semicolon = new Token(TokenType.SEMICOLON, 0); -/// The '=' token. -final Token $equals = new Token(TokenType.EQ, 0); +/// The `static` token. +final Token $static = new KeywordToken(Keyword.STATIC, 0); -/// The '??=' token. -final Token $nullAwareEquals = new Token(TokenType.QUESTION_QUESTION_EQ, 0); +/// The `this` token. +final Token $this = new KeywordToken(Keyword.THIS, 0); -/// The '.' token. -final Token $period = new Token(TokenType.PERIOD, 0); +/// The `true` token. +final Token $true = new KeywordToken(Keyword.TRUE, 0); -/// Returns a string token for the given string [s]. -StringToken stringToken(String s) => new StringToken(TokenType.STRING, s, 0); +/// The `var` token. +final Token $var = new KeywordToken(Keyword.VAR, 0); + +/// The `with` token. +final Token $with = new KeywordToken(Keyword.WITH, 0); /// Returns an int token for the given int [value]. StringToken intToken(int value) => new StringToken(TokenType.INT, '$value', 0); + +/// Returns a string token for the given string [s]. +StringToken stringToken(String s) => new StringToken(TokenType.STRING, s, 0); diff --git a/pkgs/code_builder/lib/testing.dart b/pkgs/code_builder/lib/testing.dart new file mode 100644 index 000000000..ef6ae980c --- /dev/null +++ b/pkgs/code_builder/lib/testing.dart @@ -0,0 +1,100 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/src/pretty_printer.dart'; +import 'package:dart_style/dart_style.dart'; +import 'package:matcher/matcher.dart'; + +/// Returns a [Matcher] that checks an [AstBuilder] versus [source]. +/// +/// On failure, uses the default string matcher to show a detailed diff between +/// the expected and actual source code results. +/// +/// If [pretty] is set, uses another `toSource` method that adds additional +/// line breaks to make the output more readable and idiomatic. +Matcher equalsSource( + String source, { + bool pretty: false, + Scope scope: Scope.identity, +}) { + var canParse = false; + try { + source = dartfmt(source); + canParse = true; + } on FormatterException catch (_) {} + return new _EqualsSource( + scope, + source, + canParse, + pretty, + ); +} + +class _EqualsSource extends Matcher { + final Scope _scope; + final String _source; + final bool _canParse; + final bool _pretty; + + _EqualsSource(this._scope, this._source, this._canParse, this._pretty); + + @override + Description describe(Description description) { + if (_canParse) { + return equals(_source).describe(description); + } else { + return equalsIgnoringWhitespace(_source).describe(description); + } + } + + @override + Description describeMismatch( + item, + Description mismatchDescription, + Map matchState, + bool verbose, + ) { + if (item is AstBuilder) { + var origin = _formatAst(item); + if (_canParse) { + return equals(_source).describeMismatch( + origin, + mismatchDescription.addDescriptionOf(origin), + matchState, + verbose, + ); + } else { + return equalsIgnoringWhitespace(_source).describeMismatch( + origin, + mismatchDescription.addDescriptionOf(origin), + matchState, + verbose, + ); + } + } else { + return mismatchDescription.add('$item is not a CodeBuilder'); + } + } + + @override + bool matches(item, _) { + if (item is AstBuilder) { + if (_canParse) { + return equals(_formatAst(item)).matches(_source, {}); + } else { + return equalsIgnoringWhitespace(_formatAst(item)).matches(_source, {}); + } + } + return false; + } + + String _formatAst(AstBuilder builder) { + var astNode = builder.buildAst(_scope); + if (_canParse) { + return dartfmt(_pretty ? prettyToSource(astNode) : astNode.toSource()); + } + return astNode.toSource(); + } +} diff --git a/pkgs/code_builder/lib/testing/equals_source.dart b/pkgs/code_builder/lib/testing/equals_source.dart deleted file mode 100644 index e79036c19..000000000 --- a/pkgs/code_builder/lib/testing/equals_source.dart +++ /dev/null @@ -1,113 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/src/tokens.dart'; -import 'package:matcher/matcher.dart'; - -/// Returns identifiers that are just the file name. -/// -/// For example `getIdentifier('Foo', 'package:foo/foo.dart')` would return -/// the identifier "foo.Foo". This isn't safe enough for use in a actual -/// code-gen but makes it easy to debug issues in our tests. -const Scope simpleNameScope = const _SimpleNameScope(); - -/// Returns a [Matcher] that checks a [CodeBuilder] versus [source]. -/// -/// On failure, uses the default string matcher to show a detailed diff between -/// the expected and actual source code results. -/// -/// **NOTE**: By default it both runs `dartfmt` _and_ prints the source with -/// additional formatting over the default `Ast.toSource` implementation (i.e. -/// adds new lines between methods in classes, and more). -/// -/// If you have code that is not consider a valid compilation unit (like an -/// expression, you should flip [format] to `false`). -Matcher equalsSource( - String source, { - bool format: true, - Scope scope: const Scope.identity(), -}) { - return new _EqualsSource( - scope, - format ? dartfmt(source) : source, - format, - ); -} - -Identifier _stringId(String s) => new SimpleIdentifier(stringToken(s)); - -class _EqualsSource extends Matcher { - final Scope _scope; - final String _source; - final bool _isFormatted; - - _EqualsSource(this._scope, this._source, this._isFormatted); - - @override - Description describe(Description description) { - return equals(_source).describe(description); - } - - @override - Description describeMismatch( - item, - Description mismatchDescription, - Map matchState, - bool verbose, - ) { - if (item is CodeBuilder) { - var origin = _formatAst(item); - print(origin); - return equals(_source).describeMismatch( - origin, - mismatchDescription.addDescriptionOf(origin), - matchState, - verbose, - ); - } else { - return mismatchDescription.add('$item is not a CodeBuilder'); - } - } - - @override - bool matches(item, _) { - if (item is CodeBuilder) { - return _formatAst(item) == _source; - } - return false; - } - - String _formatAst(CodeBuilder builder) { - var astNode = builder.toAst(_scope); - if (_isFormatted) { - return prettyToSource(astNode); - } else { - return astNode.toSource(); - } - } -} - -// Delegates to the default matcher (which delegates further). -// -// Would be nice to just use more of package:matcher directly: -// https://github.com/dart-lang/matcher/issues/36 -class _SimpleNameScope implements Scope { - const _SimpleNameScope(); - - @override - Identifier getIdentifier(String symbol, String importUri) { - var fileWithoutExt = - Uri.parse(importUri).pathSegments.last.split('.').first; - return new PrefixedIdentifier( - _stringId(fileWithoutExt), - $period, - _stringId(symbol), - ); - } - - @override - Iterable getImports() => const []; -} diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 483ee3a68..84f1bd955 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 0.1.3 +version: 1.0.0-alpha description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/class_builder_test.dart b/pkgs/code_builder/test/builders/class_builder_test.dart deleted file mode 100644 index e20cb54d9..000000000 --- a/pkgs/code_builder/test/builders/class_builder_test.dart +++ /dev/null @@ -1,167 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing/equals_source.dart'; -import 'package:test/test.dart'; - -void main() { - test('should emit an empty class', () { - expect(new ClassBuilder('Animal'), equalsSource('class Animal {}')); - }); - - test('should emit an abstract class', () { - expect( - new ClassBuilder.asAbstract('Animal'), - equalsSource('abstract class Animal {}'), - ); - }); - - test('should emit a class extending another class', () { - expect( - new ClassBuilder('Animal', extend: new TypeBuilder('Organism')), - equalsSource('class Animal extends Organism {}'), - ); - }); - - test('should emit a class implementing another class', () { - expect( - new ClassBuilder('Animal', implement: [new TypeBuilder('Delicious')]), - equalsSource('class Animal implements Delicious {}'), - ); - }); - - test('should emit a class extending and mixing in another class', () { - expect( - new ClassBuilder( - 'Animal', - extend: new TypeBuilder('Organism'), - mixin: [new TypeBuilder('Breathing')], - ), - equalsSource('class Animal extends Organism with Breathing {}'), - ); - }); - - test('should emit a class with a method', () { - expect( - new ClassBuilder('Animal') - ..addMethod(new MethodBuilder( - name: 'toString', - returns: typeString, - )..setExpression(const LiteralString('Delicious'))), - equalsSource(r''' - class Animal { - String toString() => 'Delicious'; - } - '''), - ); - }); - - test('should emit an abstract class with an abstract method', () { - expect( - new ClassBuilder.asAbstract('Animal') - ..addMethod( - new MethodBuilder.returnVoid(name: 'eat', abstract: true), - ), - equalsSource(r''' - abstract class Animal { - void eat(); - } - '''), - ); - }); - - test('should emit a class with a static method', () { - expect( - new ClassBuilder('Animal') - ..addMethod( - new MethodBuilder( - name: 'create', - static: true, - returns: new TypeBuilder('Animal'), - )..setExpression(literalNull), - ), - equalsSource(r''' - class Animal { - static Animal create() => null; - } - '''), - ); - }); - - test('should emit a class with a metadata annotation', () { - expect( - new ClassBuilder('Animal')..addAnnotation(atDeprecated()), - equalsSource(r''' - @deprecated - class Animal {} - '''), - ); - }); - - test('should emit a class with an invoking metadata annotation', () { - expect( - new ClassBuilder('Animal') - ..addAnnotation(atDeprecated('We ate them all')), - equalsSource(r''' - @Deprecated('We ate them all') - class Animal {} - '''), - ); - }); - - group('constructors', () { - ClassBuilder clazz; - - setUp(() { - clazz = new ClassBuilder('Animal'); - }); - - test('default constructor', () { - clazz.addConstructor(new ConstructorBuilder()); - expect( - clazz, - equalsSource( - r''' - class Animal { - Animal(); - } - ''', - )); - }); - - test('default const constructor', () { - clazz.addConstructor(new ConstructorBuilder.isConst()); - expect( - clazz, - equalsSource( - r''' - class Animal { - const Animal(); - } - ''', - )); - }); - - test('initializing fields', () { - clazz.addConstructor(new ConstructorBuilder() - ..addParameter( - new ParameterBuilder('a', field: true), - ) - ..addParameter( - new ParameterBuilder.optional('b', field: true), - )); - expect( - clazz, - equalsSource( - r''' - class Animal { - Animal(this.a, [this.b]); - } - ''', - )); - }); - }); -} diff --git a/pkgs/code_builder/test/builders/class_test.dart b/pkgs/code_builder/test/builders/class_test.dart new file mode 100644 index 000000000..40fe307dc --- /dev/null +++ b/pkgs/code_builder/test/builders/class_test.dart @@ -0,0 +1,163 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/src/builders/method.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit an empty class', () { + expect( + clazz('Animal'), + equalsSource(r''' + class Animal {} + '''), + ); + }); + + test('should emit a class with an annotation', () { + expect( + clazz('Animal', [reference('deprecated')]), + equalsSource(r''' + @deprecated + class Animal {} + '''), + ); + }); + + test('should emit a class that extends another', () { + expect( + clazz('Animal', [extend(reference('Life'))]), + equalsSource(r''' + class Animal extends Life {} + '''), + ); + }); + + test('should emit a class that implements another', () { + expect( + clazz('Animal', [implement(reference('Living'))]), + equalsSource(r''' + class Animal implements Living {} + '''), + ); + }); + + test('should emit a class that mixes in another', () { + expect( + clazz('Animal', [mixin(reference('Living'))]), + equalsSource(r''' + class Animal extends Object with Living {} + '''), + ); + }); + + test('should emit a class with a constructor', () { + expect( + clazz('Animal', [ + constructor(), + ]), + equalsSource(r''' + class Animal { + Animal(); + } + '''), + ); + }); + + test('should emit a class with a named constructor', () { + expect( + clazz('Animal', [ + constructorNamed('internal'), + ]), + equalsSource(r''' + class Animal { + Animal.internal(); + } + '''), + ); + }); + + test('should emit a class with a constructor with parameters', () { + expect( + clazz('Animal', [ + constructor([ + parameter('name', [lib$core.String]), + thisField( + named( + parameter('age').asOptional(literal(0)), + ), + ) + ]) + ]), + equalsSource(r''' + class Animal { + Animal(String name, {this.age: 0}); + } + '''), + ); + }); + + test('should emit a class with fields', () { + expect( + clazz('Animal', [ + asStatic( + varField('static1', type: lib$core.String, value: literal('Hello')), + ), + asStatic( + varFinal('static2', type: lib$core.List, value: literal([])), + ), + asStatic( + varConst('static3', type: lib$core.bool, value: literal(true)), + ), + varField('var1', type: lib$core.String, value: literal('Hello')), + varFinal('var2', type: lib$core.List, value: literal([])), + varConst('var3', type: lib$core.bool, value: literal(true)), + ]), + equalsSource(r''' + class Animal { + static String static1 = 'Hello'; + static final List static2 = []; + static const bool static3 = true; + String var1 = 'Hello'; + final List var2 = []; + const bool var3 = true; + } + '''), + ); + }); + + test('should emit a class with methods', () { + expect( + clazz('Animal', [ + asStatic(method('staticMethod', [ + lib$core.$void, + lib$core.print.call([literal('Called staticMethod')]), + ])), + method('instanceMethod', [ + lib$core.$void, + lib$core.print.call([literal('Called instanceMethod')]), + ]), + constructor([ + lib$core.print.call([literal('Called constructor')]), + ]), + ]), + equalsSource(r''' + class Animal { + Animal() { + print('Called constructor'); + } + static void staticMethod() { + print('Called staticMethod'); + } + void instanceMethod() { + print('Called instanceMethod'); + } + } + '''), + ); + }); +} diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart new file mode 100644 index 000000000..5d6b453df --- /dev/null +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -0,0 +1,247 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +void main() { + group('literal', () { + test('should emit a null', () { + expect(literal(null), equalsSource(r'null')); + }); + + test('should emit true', () { + expect(literal(true), equalsSource(r'true')); + }); + + test('should emit false', () { + expect(literal(false), equalsSource(r'false')); + }); + + test('should emit an int', () { + expect(literal(5), equalsSource(r'5')); + }); + + test('should emit a double', () { + expect(literal(5.5), equalsSource(r'5.5')); + }); + + test('should emit a string', () { + expect(literal('Hello'), equalsSource(r"'Hello'")); + }); + + test('should emit a list', () { + expect(literal([1, 2, 3]), equalsSource(r'[1, 2, 3]')); + }); + + test('should emit a map', () { + expect(literal({1: 2, 2: 3}), equalsSource(r'{1 : 2, 2 : 3}')); + }); + }); + + test('should emit an assert statemnet', () { + expect( + literal(true).asAssert(), + equalsSource(r''' + assert(true); + '''), + ); + }); + + test('should emit an assign expression', () { + expect( + literal(true).asAssign('flag'), + equalsSource(r''' + flag = true + '''), + ); + }); + + test('should emit an assign expression with a null aware', () { + expect( + literal(true).asAssign('flag', nullAware: true), + equalsSource(r''' + flag ??= true + '''), + ); + }); + + test('should emit a const variable assignment statement', () { + expect( + literal(true).asConst('flag'), + equalsSource(r''' + const flag = true; + '''), + ); + }); + + test('should emit a final variable assignment statement', () { + expect( + literal(true).asFinal('flag'), + equalsSource(r''' + final flag = true; + '''), + ); + }); + + test('should emit a simple var assignment statement', () { + expect( + literal(true).asVar('flag'), + equalsSource(r''' + var flag = true; + '''), + ); + }); + + test('should emit a typed assignemnt statement', () { + expect( + literal(true).asVar('flag', lib$core.bool), + equalsSource(r''' + bool flag = true; + '''), + ); + }); + + test('should emit a return statement', () { + expect( + literal(true).asReturn(), + equalsSource(r''' + return true; + '''), + ); + }); + + test('should emit an expression as a statement', () { + expect( + literal(true).asStatement(), + equalsSource(r''' + true; + '''), + ); + }); + + test('should call an expression as a function', () { + expect( + lib$core.identical.call([literal(true), literal(true)]), + equalsSource(r''' + identical(true, true) + '''), + ); + }); + + test('should call an expression with named arguments', () { + expect( + reference('doThing').call( + [literal(true)], + { + 'otherFlag': literal(false), + }, + ), + equalsSource(r''' + doThing(true, otherFlag: false) + '''), + ); + }); + + test('should call a method on an expression', () { + expect( + explicitThis.invoke('doThing', [literal(true)]), + equalsSource(r''' + this.doThing(true) + '''), + ); + }); + + test('should emit an identical() expression', () { + expect( + literal(true).identical(literal(false)), + equalsSource(r''' + identical(true, false) + '''), + ); + }); + + test('should emit an equality (==) expression', () { + expect( + literal(true).equals(literal(false)), + equalsSource(r''' + true == false + '''), + ); + }); + + test('should emit a not equals (!=) expression', () { + expect( + literal(true).notEquals(literal(false)), + equalsSource(r''' + true != false + '''), + ); + }); + + test('should emit a negated expression', () { + expect( + reference('foo').negate(), + equalsSource(r''' + !(foo) + '''), + ); + }); + + test('should add two expressions', () { + expect( + literal(1) + literal(2), + equalsSource(r''' + 1 + 2 + '''), + ); + }); + + test('should subtract two expressions', () { + expect( + literal(2) - literal(1), + equalsSource(r''' + 2 - 1 + '''), + ); + }); + + test('should multiply two expressions', () { + expect( + literal(2) * literal(3), + equalsSource(r''' + 2 * 3 + '''), + ); + }); + + test('should divide two expressions', () { + expect( + literal(3) / literal(2), + equalsSource(r''' + 3 / 2 + '''), + ); + }); + + test('should wrap an expressions in ()', () { + expect( + literal(true).parentheses(), + equalsSource(r''' + (true) + '''), + ); + }); + + test('should return as a negative expression', () { + expect( + literal(1).negative(), + equalsSource(r''' + -(1) + '''), + ); + }); +} diff --git a/pkgs/code_builder/test/builders/field_builder_test.dart b/pkgs/code_builder/test/builders/field_builder_test.dart deleted file mode 100644 index 95954b4c2..000000000 --- a/pkgs/code_builder/test/builders/field_builder_test.dart +++ /dev/null @@ -1,49 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing/equals_source.dart'; -import 'package:test/test.dart'; - -void main() { - test('should emit an unitialized simple variable', () { - expect( - new FieldBuilder('name'), - equalsSource(r'var name;'), - ); - }); - - test('should emit a typed variable', () { - expect( - new FieldBuilder('name', type: typeString), - equalsSource(r'String name;'), - ); - }); - - test('should emit an initialized variable', () { - expect( - new FieldBuilder( - 'name', - type: typeString, - initialize: const LiteralString('Jill User'), - ), - equalsSource(r"String name = 'Jill User';"), - ); - }); - - test('should emit a final variable', () { - expect( - new FieldBuilder.isFinal('name'), - equalsSource(r'final name;'), - ); - }); - - test('should emit a const variable', () { - expect( - new FieldBuilder.isConst('name'), - equalsSource(r'const name;'), - ); - }); -} diff --git a/pkgs/code_builder/test/builders/field_test.dart b/pkgs/code_builder/test/builders/field_test.dart new file mode 100644 index 000000000..fcadb6690 --- /dev/null +++ b/pkgs/code_builder/test/builders/field_test.dart @@ -0,0 +1,33 @@ +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +void main() { + test('emit a var', () { + expect( + varField('a', type: lib$core.String, value: literal('Hello')), + equalsSource(r''' + String a = 'Hello'; + '''), + ); + }); + + test('emit a final', () { + expect( + varFinal('a', type: lib$core.String, value: literal('Hello')), + equalsSource(r''' + final String a = 'Hello'; + '''), + ); + }); + + test('emit a const', () { + expect( + varConst('a', type: lib$core.String, value: literal('Hello')), + equalsSource(r''' + const String a = 'Hello'; + '''), + ); + }); +} diff --git a/pkgs/code_builder/test/builders/file_builder_test.dart b/pkgs/code_builder/test/builders/file_builder_test.dart deleted file mode 100644 index 8329b979e..000000000 --- a/pkgs/code_builder/test/builders/file_builder_test.dart +++ /dev/null @@ -1,46 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/testing/equals_source.dart'; -import 'package:test/test.dart'; - -void main() { - test('should emit a blank file', () { - expect(new LibraryBuilder(), equalsSource('')); - }); - - test('should emit a file with a library directive', () { - expect(new LibraryBuilder('code_builder'), - equalsSource('library code_builder;')); - }); - - test('should emit a file with a part of directive', () { - expect( - new PartBuilder('code_builder'), - equalsSource('part of code_builder;'), - ); - }); - - test('should emit an import directive', () { - expect( - new ImportBuilder('package:foo/foo.dart'), - equalsSource("import 'package:foo/foo.dart';"), - ); - }); - - test('should emit an import directive and a prefix', () { - expect( - new ImportBuilder('package:foo/foo.dart', prefix: 'foo'), - equalsSource("import 'package:foo/foo.dart' as foo;"), - ); - }); - - test('should emit an export directive', () { - expect( - new ExportBuilder('package:foo/foo.dart'), - equalsSource("export 'package:foo/foo.dart';"), - ); - }); -} diff --git a/pkgs/code_builder/test/builders/method_builder_test.dart b/pkgs/code_builder/test/builders/method_builder_test.dart deleted file mode 100644 index 3b0c70e6b..000000000 --- a/pkgs/code_builder/test/builders/method_builder_test.dart +++ /dev/null @@ -1,343 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing/equals_source.dart'; -import 'package:test/test.dart'; - -void main() { - test('should emit a simple "void" method', () { - expect( - new MethodBuilder.returnVoid(name: 'main'), - equalsSource('void main() {}'), - ); - }); - - test('should emit a method returning a String', () { - expect( - new MethodBuilder(name: 'toString', returns: typeString), - equalsSource('String toString() {}'), - ); - }); - - test('should emit a method returning a scoped Type', () { - expect( - new MethodBuilder( - name: 'toFoo', - returns: new TypeBuilder('Foo', importFrom: 'package:foo/foo.dart'), - ) - ..addParameter(new ParameterBuilder( - 'context', - type: - new TypeBuilder('Context', importFrom: 'package:bar/bar.dart'), - )), - equalsSource( - r''' - foo.Foo toFoo(bar.Context context) {} - ''', - scope: simpleNameScope, - )); - }); - - test('should emit a method returning a scoped Type and scoped Param', () { - expect( - new MethodBuilder( - name: 'toFoo', - returns: new TypeBuilder('Foo', importFrom: 'package:foo/foo.dart'), - ), - equalsSource( - r''' - foo.Foo toFoo() {} - ''', - scope: simpleNameScope, - )); - }); - - test('should emit a method annotated', () { - expect( - new MethodBuilder(name: 'oldMethod')..addAnnotation(atDeprecated()), - equalsSource( - r''' - @deprecated - oldMethod() {} - ''', - )); - }); - - group('with an expression', () { - test('should return true', () { - expect( - new MethodBuilder(name: 'isSupported', returns: typeBool) - ..setExpression(literalTrue), - equalsSource( - r''' - bool isSupported() => true; - ''', - ), - ); - }); - - test('should return false', () { - expect( - new MethodBuilder(name: 'isSupported', returns: typeBool) - ..setExpression(literalFalse), - equalsSource( - r''' - bool isSupported() => false; - ''', - ), - ); - }); - - test('should return null', () { - expect( - new MethodBuilder(name: 'isSupported')..setExpression(literalNull), - equalsSource( - r''' - isSupported() => null; - ''', - ), - ); - }); - - test('should return "Hello World"', () { - expect( - new MethodBuilder(name: 'sayHello', returns: typeString) - ..setExpression( - const LiteralString('Hello World'), - ), - equalsSource( - r''' - String sayHello() => 'Hello World'; - ''', - ), - ); - }); - - group('with statements', () { - test('should work with an expression', () { - expect( - new MethodBuilder.returnVoid(name: 'main') - ..addStatement(const LiteralString('Hello World').toStatement()), - equalsSource(r''' - void main() { - 'Hello World'; - } - '''), - ); - }); - - test('should work with an assignment', () { - expect( - new MethodBuilder.returnVoid(name: 'main') - ..addStatement(new ExpressionBuilder.assignment( - 'foo', - const LiteralString('Hello World'), - ) - .toStatement()), - equalsSource(r''' - void main() { - foo = 'Hello World'; - } - '''), - ); - }); - - test('should work with a null-aware assignment', () { - expect( - new MethodBuilder.returnVoid(name: 'main') - ..addStatement(new ExpressionBuilder.assignment( - 'foo', - const LiteralString('Hello World'), - nullAware: true, - ) - .toStatement()), - equalsSource(r''' - void main() { - foo ??= 'Hello World'; - } - '''), - ); - }); - - test('should work invoking an expression', () { - expect( - new MethodBuilder.returnVoid(name: 'main') - ..addStatement( - new ExpressionBuilder.invoke('print', positional: [ - const LiteralString('Hello World').invokeSelf( - 'substring', - positional: [const LiteralInt(1)], - ) - ]).toStatement(), - ), - equalsSource(r''' - void main() { - print('Hello World'.substring(1)); - } - '''), - ); - }); - }); - - group('with parameters:', () { - MethodBuilder method; - - setUp(() { - method = new MethodBuilder.returnVoid(name: 'main'); - }); - - test('single required parameter', () { - method.addParameter(new ParameterBuilder('name', type: typeString)); - expect( - method, - equalsSource( - r''' - void main(String name) {} - ''', - ), - ); - }); - - test('two required parameters', () { - method - ..addParameter(new ParameterBuilder('a', type: typeInt)) - ..addParameter(new ParameterBuilder('b', type: typeInt)); - expect( - method, - equalsSource( - r''' - void main(int a, int b) {} - ''', - ), - ); - }); - - test('one optional parameter', () { - method.addParameter(new ParameterBuilder.optional( - 'name', - type: typeString, - )); - expect( - method, - equalsSource( - r''' - void main([String name]) {} - ''', - ), - ); - }); - - test('one optional parameter with a default value', () { - method.addParameter(new ParameterBuilder.optional( - 'enabled', - type: typeBool, - defaultTo: literalTrue, - )); - expect( - method, - equalsSource( - r''' - void main([bool enabled = true]) {} - ''', - ), - ); - }); - - test('one optional named parameter with a default value', () { - method.addParameter(new ParameterBuilder.named( - 'enabled', - type: typeBool, - defaultTo: literalTrue, - )); - expect( - method, - equalsSource( - r''' - void main({bool enabled: true}) {} - ''', - ), - ); - }); - - test('one optional named parameter with an annotation', () { - method.addParameter(new ParameterBuilder.named( - 'enabled', - type: typeBool, - defaultTo: literalTrue, - )..addAnnotation(atDeprecated())); - expect( - method, - equalsSource( - r''' - void main({@deprecated bool enabled: true}) {} - ''', - ), - ); - }); - }); - - group('invoking method', () { - MethodBuilder method; - - setUp(() { - method = new MethodBuilder(name: 'forward', returns: typeInt); - }); - - test('should call another method with one argument', () { - method.setExpression(new ExpressionBuilder.invoke( - 'forwardImpl', - positional: [const LiteralInt(666)], - )); - expect( - method, - equalsSource(r''' - int forward() => forwardImpl(666); - '''), - ); - }); - - test('should call another method with two arguments', () { - method.setExpression(new ExpressionBuilder.invoke( - 'sum', - positional: [const LiteralInt(1), const LiteralInt(2)], - )); - expect( - method, - equalsSource(r''' - int forward() => sum(1, 2); - '''), - ); - }); - - test('should call another method with a named arguments', () { - method.setExpression(new ExpressionBuilder.invoke( - 'forwardImpl', - named: {'value': const LiteralInt(666)}, - )); - expect( - method, - equalsSource(r''' - int forward() => forwardImpl(value: 666); - '''), - ); - }); - - test('should call another method with many arguments', () { - method.setExpression(new ExpressionBuilder.invoke( - 'forwardImpl', - positional: const [const LiteralInt(3), const LiteralInt(4)], - named: {'a': const LiteralInt(1), 'b': const LiteralInt(2)}, - )); - expect( - method, - equalsSource(r''' - int forward() => forwardImpl(3, 4, a: 1, b: 2); - '''), - ); - }); - }); - }); -} diff --git a/pkgs/code_builder/test/builders/method_test.dart b/pkgs/code_builder/test/builders/method_test.dart new file mode 100644 index 000000000..e532e622f --- /dev/null +++ b/pkgs/code_builder/test/builders/method_test.dart @@ -0,0 +1,172 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit a top-level main() function', () { + expect( + method('main'), + equalsSource(r''' + main(); + '''), + ); + }); + + test('should emit a top-level void main() function', () { + expect( + method('main', [ + lib$core.$void, + ]).buildMethod(false).toSource(), + equalsIgnoringWhitespace(r''' + void main(); + '''), + ); + }); + + test('should emit a function with a parameter', () { + expect( + method('main', [ + parameter('args', [lib$core.List]), + ]).buildMethod(false).toSource(), + equalsIgnoringWhitespace(r''' + main(List args); + '''), + ); + }); + + test('should emit a function with multiple parameters', () { + expect( + method('main', [ + parameter('a'), + parameter('b'), + parameter('c').asOptional(), + ]), + equalsSource(r''' + main(a, b, [c]); + '''), + ); + }); + + test('should emit a function with multiple parameters', () { + expect( + method('main', [ + parameter('a'), + parameter('b'), + parameter('c').asOptional(literal(true)), + ]), + equalsSource(r''' + main(a, b, [c = true]); + '''), + ); + }); + + test('should emit a function with named parameters', () { + expect( + method('main', [ + named(parameter('a')), + named(parameter('b').asOptional(literal(true))), + ]).buildMethod(false).toSource(), + equalsIgnoringWhitespace(r''' + main({a, b : true}); + '''), + ); + }); + + group('constructors', () { + test('should emit a simple constructor', () { + expect( + new ConstructorBuilder() + .buildConstructor( + reference('Animal'), + ) + .toSource(), + equalsIgnoringWhitespace(r''' + Animal(); + '''), + ); + }); + + test('should emit a simple constructor with parameters', () { + expect( + (new ConstructorBuilder()..addPositional(parameter('name'))) + .buildConstructor( + reference('Animal'), + ) + .toSource(), + equalsIgnoringWhitespace(r''' + Animal(name); + '''), + ); + }); + + test('should emit a simple constructor with field-formal parameters', () { + expect( + (new ConstructorBuilder() + ..addPositional( + parameter('name'), + asField: true, + )) + .buildConstructor( + reference('Animal'), + ) + .toSource(), + equalsIgnoringWhitespace(r''' + Animal(this.name); + '''), + ); + }); + + test('should a method with a lambda value', () { + expect( + lambda('supported', literal(true), returnType: lib$core.bool), + equalsSource(r''' + bool supported() => true; + '''), + ); + }); + }); + + test('should emit a getter with a lambda value', () { + expect( + getter('unsupported', returns: literal(true)), + equalsSource(r''' + get unsupported => true; + '''), + ); + }); + + test('should emit a getter with statements', () { + expect( + getter( + 'values', + returnType: lib$core.Iterable, + statements: [ + literal([]).asReturn(), + ], + ), + equalsSource(r''' + Iterable get values { + return []; + } + '''), + ); + }); + + test('should emit a setter', () { + expect( + setter('name', parameter('name', [lib$core.String]), [ + (reference('name') + literal('!')).asAssign('_name'), + ]), + equalsSource(r''' + set name(String name) { + _name = name + '!'; + } + '''), + ); + }); +} diff --git a/pkgs/code_builder/test/builders/parameter_builder.dart b/pkgs/code_builder/test/builders/parameter_builder.dart new file mode 100644 index 000000000..8ac2d81dc --- /dev/null +++ b/pkgs/code_builder/test/builders/parameter_builder.dart @@ -0,0 +1,50 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit a simple parameter', () { + expect( + parameter('foo'), + equalsSource(r''' + foo + '''), + ); + }); + + test('should emit a typed parameter', () { + expect( + parameter('foo', [reference('String')]), + equalsSource(r''' + String foo + '''), + ); + }); + + test('should emit an optional parameter with a default value', () { + expect( + parameter('foo').asOptional(literal(true)), + equalsSource(r''' + foo = true + '''), + ); + }); + + test('should emit a named parameter with a default value', () { + expect( + parameter('foo').asOptional(literal(true)).buildNamed(false).toSource(), + equalsIgnoringCase(r'foo : true'), + ); + }); + + test('should emit a field formal parameter', () { + expect( + parameter('foo').buildPositional(true).toSource(), + equalsIgnoringCase(r'this.foo'), + ); + }); +} diff --git a/pkgs/code_builder/test/builders/reference_test.dart b/pkgs/code_builder/test/builders/reference_test.dart new file mode 100644 index 000000000..f25ae74e0 --- /dev/null +++ b/pkgs/code_builder/test/builders/reference_test.dart @@ -0,0 +1,9 @@ +// 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. + +import 'package:test/test.dart'; + +void main() { + group('reference', () {}); +} diff --git a/pkgs/code_builder/test/builders/shared_test.dart b/pkgs/code_builder/test/builders/shared_test.dart new file mode 100644 index 000000000..a38a06223 --- /dev/null +++ b/pkgs/code_builder/test/builders/shared_test.dart @@ -0,0 +1,17 @@ +// 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. + +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/tokens.dart'; +import 'package:test/test.dart'; + +void main() { + test('stringIdentifier should return a string identifier', () { + expect(stringIdentifier('Coffee').toSource(), 'Coffee'); + }); + + test('stringToken should return a string token', () { + expect(stringToken('Coffee').value().toString(), 'Coffee'); + }); +} diff --git a/pkgs/code_builder/test/builders/statement_test.dart b/pkgs/code_builder/test/builders/statement_test.dart new file mode 100644 index 000000000..b899c8531 --- /dev/null +++ b/pkgs/code_builder/test/builders/statement_test.dart @@ -0,0 +1,85 @@ +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +void main() { + group('if statements', () { + test('should emit a simple if statement', () { + expect( + ifThen(literal(true), [ + lib$core.print.call([literal('Hello World')]), + ]), + equalsSource(r''' + if (true) { + print('Hello World'); + } + '''), + ); + }); + + test('should emit an if then else statement', () { + expect( + ifThen(literal(true), [ + lib$core.print.call([literal('TRUE')]), + elseThen([ + lib$core.print.call([literal('FALSE')]), + ]), + ]), + equalsSource(r''' + if (true) { + print('TRUE'); + } else { + print('FALSE'); + } + '''), + ); + }); + + test('should emit an if else then statement', () { + final a = reference('a'); + expect( + ifThen(a.equals(literal(1)), [ + lib$core.print.call([literal('Was 1')]), + elseIf(ifThen(a.equals(literal(2)), [ + lib$core.print.call([literal('Was 2')]), + ])), + ]), + equalsSource(r''' + if (a == 1) { + print('Was 1'); + } else if (a == 2) { + print('Was 2'); + } + '''), + ); + }); + + test('should emit an if else if else statement', () { + final a = reference('a'); + expect( + ifThen( + a.equals(literal(1)), + [ + lib$core.print.call([literal('Was 1')]), + elseIf(ifThen(a.equals(literal(2)), [ + lib$core.print.call([literal('Was 2')]), + elseThen([ + lib$core.print.call([literal('Was ') + a]), + ]), + ])), + ], + ), + equalsSource(r''' + if (a == 1) { + print('Was 1'); + } else if (a == 2) { + print('Was 2'); + } else { + print('Was ' + a); + } + '''), + ); + }); + }); +} diff --git a/pkgs/code_builder/test/builders/type_test.dart b/pkgs/code_builder/test/builders/type_test.dart new file mode 100644 index 000000000..b9ac7b8ea --- /dev/null +++ b/pkgs/code_builder/test/builders/type_test.dart @@ -0,0 +1,71 @@ +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +void main() { + group('new instance', () { + test('emits a new List', () { + expect( + lib$core.List.newInstance([]), + equalsSource(r''' + new List() + '''), + ); + }); + + test('emits a new List.from', () { + expect( + lib$core.List.namedNewInstance('from', [ + literal([1, 2, 3]), + ]), + equalsSource(r''' + new List.from([1, 2, 3]) + '''), + ); + }); + + test('emits a new const Point', () { + expect( + reference('Point').constInstance([ + literal(1), + literal(2), + ]), + equalsSource(r''' + const Point(1, 2) + '''), + ); + }); + + test('emits a const constructor as an annotation', () { + expect( + clazz('Animal', [ + lib$core.Deprecated + .constInstance([literal('Animals are out of style')]), + ]), + equalsSource(r''' + @Deprecated('Animals are out of style') + class Animal {} + '''), + ); + }); + + test('emits a named const constructor as an annotation', () { + expect( + clazz('Animal', [ + reference('Component').namedConstInstance( + 'stateful', + [], + { + 'selector': literal('animal'), + }, + ), + ]), + equalsSource(r''' + @Component.stateful(selector: 'animal') + class Animal {} + '''), + ); + }); + }); +} diff --git a/pkgs/code_builder/test/e2e_test.dart b/pkgs/code_builder/test/e2e_test.dart new file mode 100644 index 000000000..1c887808c --- /dev/null +++ b/pkgs/code_builder/test/e2e_test.dart @@ -0,0 +1,108 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +// Closely mirrors the API you'd need to generate dependency injection :) +void main() { + test('Should emit a complex generated file', () { + // Imports from an existing Dart library. + var appRef = reference('App', 'package:app/app.dart'); + var moduleRef = reference('Module', 'package:app/app.dart'); + var thingRef = reference('Thing', 'package:app/app.dart'); + + var clazz = new ClassBuilder('Injector', asImplements: [appRef]); + clazz + ..addField( + new FieldBuilder.asFinal('_module', type: moduleRef), + ) + ..addConstructor(new ConstructorBuilder() + ..addPositional( + new ParameterBuilder('_module'), + asField: true, + )) + ..addMethod(new MethodBuilder( + 'getThing', + returns: thingRef.newInstance([ + reference('_module').invoke('getDep1', []), + reference('_module').invoke('getDep2', []), + ]), + returnType: thingRef, + )..addAnnotation(lib$core.override)); + var lib = new LibraryBuilder() + ..addDirective( + new ImportBuilder('app.dart'), + ) + ..addMember( + clazz, + ); + expect( + lib, + equalsSource( + r''' + import 'app.dart'; + + class Injector implements App { + final Module _module; + + Injector(this._module); + + @override + Thing getThing() => new Thing(_module.getDep1(), _module.getDep2()); + } + ''', + pretty: true, + ), + ); + }); + + test('Should emit a complex generated file with scoping applied', () { + var appRef = reference('App', 'package:app/app.dart'); + var moduleRef = reference('Module', 'package:app/app.dart'); + var thingRef = reference('Thing', 'package:app/thing.dart'); + var lib = new LibraryBuilder.scope() + ..addMember(new ClassBuilder('Injector', asImplements: [appRef]) + ..addField( + new FieldBuilder.asFinal( + '_module', + type: moduleRef, + ), + ) + ..addConstructor(new ConstructorBuilder() + ..addPositional( + new ParameterBuilder('_module'), + asField: true, + )) + ..addMethod(new MethodBuilder( + 'getThing', + returnType: thingRef, + returns: thingRef.newInstance([ + reference('_module').invoke('getDep1', []), + reference('_module').invoke('getDep2', []), + ]), + )..addAnnotation(lib$core.override))); + expect( + lib, + equalsSource( + r''' + import 'package:app/app.dart' as _i1; + import 'package:app/thing.dart' as _i2; + + class Injector implements _i1.App { + final _i1.Module _module; + + Injector(this._module); + + @override + _i2.Thing getThing() => new _i2.Thing(_module.getDep1(), _module.getDep2()); + } + ''', + pretty: true, + ), + ); + }); +} diff --git a/pkgs/code_builder/test/integration_test.dart b/pkgs/code_builder/test/integration_test.dart deleted file mode 100644 index f7565a861..000000000 --- a/pkgs/code_builder/test/integration_test.dart +++ /dev/null @@ -1,151 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing/equals_source.dart'; -import 'package:test/test.dart'; - -// Closely mirrors the API you would need to do dependency injection :) -void main() { - test('Emits a complex generated file', () { - var clazz = - new ClassBuilder(r'Injector', implement: [new TypeBuilder('App')]) - ..addField(new FieldBuilder.isFinal( - '_module', - type: const TypeBuilder('Module'), - )) - ..addConstructor(new ConstructorBuilder() - ..addParameter(new ParameterBuilder('_module', field: true))) - ..addMethod( - new MethodBuilder( - name: 'getThing', - returns: const TypeBuilder('Thing'), - ) - ..addAnnotation(atOverride) - ..setExpression(new ExpressionBuilder.invokeNew( - const TypeBuilder('Thing'), - positional: [ - new ExpressionBuilder.invoke('_module.getDep1'), - new ExpressionBuilder.invoke('_module.getDep2'), - ], - )), - ); - var lib = new LibraryBuilder() - ..addDirective( - new ImportBuilder('app.dart'), - ) - ..addDeclaration(clazz); - expect( - lib, - equalsSource( - r''' - import 'app.dart'; - - class Injector implements App { - final Module _module; - - Injector(this._module); - - @override - Thing getThing() => new Thing(_module.getDep1(), _module.getDep2()); - } - ''', - ), - ); - }); - - test('Emits a complex generated file with scoping applied', () { - var clazz = new ClassBuilder( - r'Injector', - implement: [new TypeBuilder('App', importFrom: 'package:app/app.dart')], - ) - ..addField(new FieldBuilder.isFinal( - '_module', - type: const TypeBuilder( - 'Module', - importFrom: 'package:app/app.dart', - ), - )) - ..addConstructor(new ConstructorBuilder() - ..addParameter(new ParameterBuilder('_module', field: true))) - ..addMethod( - new MethodBuilder( - name: 'getThing', - returns: const TypeBuilder( - 'Thing', - importFrom: 'package:app/thing.dart', - ), - ) - ..addAnnotation(atOverride) - ..setExpression(new ExpressionBuilder.invokeNew( - const TypeBuilder( - 'Thing', - importFrom: 'package:app/thing.dart', - ), - positional: [ - new ExpressionBuilder.invoke('_module.getDep1'), - new ExpressionBuilder.invoke('_module.getDep2'), - ], - )), - ); - var lib = new LibraryBuilder.scope()..addDeclaration(clazz); - expect( - lib, - equalsSource( - r''' - import 'package:app/app.dart' as _i1; - import 'dart:core' as _i2; - import 'package:app/thing.dart' as _i3; - - - class Injector implements _i1.App { - final _i1.Module _module; - - Injector(this._module); - - @_i2.override - _i3.Thing getThing() => new _i3.Thing(_module.getDep1(), _module.getDep2()); - } - ''', - ), - ); - }); - - test('Emits a complex generated file with conflicting imports scoped', () { - 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', - ), - ))); - expect( - lib, - equalsSource( - r''' - import 'package:thing/thing.dart' as _i1; - import 'package:thing/alternative.dart' as _i2; - - _i1.Thing doThing() {} - _i2.Thing doOtherThing(_i1.Thing thing) {} - ''', - ), - ); - }); -} diff --git a/pkgs/code_builder/test/scope_test.dart b/pkgs/code_builder/test/scope_test.dart index a75532a89..64b41d5d3 100644 --- a/pkgs/code_builder/test/scope_test.dart +++ b/pkgs/code_builder/test/scope_test.dart @@ -1,96 +1,84 @@ -// 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. - import 'package:analyzer/analyzer.dart'; -import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/src/scope.dart'; import 'package:test/test.dart'; void main() { - group('Identity scope', () { - Scope scope; - - setUp(() => scope = const Scope.identity()); - - test('should do nothing', () { - var identifiers = [ - scope.getIdentifier('Foo', 'package:foo/foo.dart'), - scope.getIdentifier('Bar', 'package:foo/foo.dart'), - scope.getIdentifier('Baz', 'package:baz/baz.dart'), - ].map/**/((i) => i.toSource()); - - expect( - identifiers, - [ - 'Foo', - 'Bar', - 'Baz', - ], - ); - - expect(scope.getImports(), isEmpty); - }); - }); + Scope scope; - group('Deduplicating scope', () { - Scope scope; + tearDown(() => scope = null); - setUp(() => scope = new Scope.dedupe()); + test('Identity scope should do nothing', () { + scope = Scope.identity; - test('should just output non-prefixed and de-duplicate imports', () { - var identifiers = [ - scope.getIdentifier('Foo', 'package:foo/foo.dart'), - scope.getIdentifier('Bar', 'package:foo/foo.dart'), - scope.getIdentifier('Baz', 'package:baz/baz.dart'), - ].map/**/((i) => i.toSource()); + var identifiers = [ + scope.identifier('Foo', 'package:foo/foo.dart'), + scope.identifier('Bar', 'package:foo/foo.dart'), + scope.identifier('Baz', 'package:baz/baz.dart'), + ].map((i) => i.toSource()); - expect( - identifiers, - [ - 'Foo', - 'Bar', - 'Baz', - ], - ); + expect( + identifiers, + [ + 'Foo', + 'Bar', + 'Baz', + ], + ); - expect( - scope.getImports().map/**/((i) => i.toAst().toSource()), - [ - r"import 'package:foo/foo.dart';", - r"import 'package:baz/baz.dart';", - ], - ); - }); + expect(scope.toImports(), isEmpty); }); - group('Incrementing scope', () { - Scope scope; - - setUp(() => scope = new Scope()); - - test('should out prefixed with a counter', () { - var identifiers = [ - scope.getIdentifier('Foo', 'package:foo/foo.dart'), - scope.getIdentifier('Bar', 'package:foo/foo.dart'), - scope.getIdentifier('Baz', 'package:baz/baz.dart'), - ].map/**/((i) => i.toSource()); - - expect( - identifiers, - [ - '_i1.Foo', - '_i1.Bar', - '_i2.Baz', - ], - ); + test('Deduplicating scope should deduplicate imports', () { + scope = new Scope.dedupe(); + + var identifiers = [ + scope.identifier('Foo', 'package:foo/foo.dart'), + scope.identifier('Bar', 'package:foo/foo.dart'), + scope.identifier('Baz', 'package:baz/baz.dart'), + ].map((i) => i.toSource()); + + expect( + identifiers, + [ + 'Foo', + 'Bar', + 'Baz', + ], + ); + + expect( + scope.toImports().map((i) => i.buildAst().toSource()), + [ + r"import 'package:foo/foo.dart';", + r"import 'package:baz/baz.dart';", + ], + ); + }); - expect( - scope.getImports().map/**/((i) => i.toAst().toSource()), - [ - r"import 'package:foo/foo.dart' as _i1;", - r"import 'package:baz/baz.dart' as _i2;", - ], - ); - }); + test('Default scope should auto-prefix', () { + scope = new Scope(); + + var identifiers = [ + scope.identifier('Foo', 'package:foo/foo.dart'), + scope.identifier('Bar', 'package:foo/foo.dart'), + scope.identifier('Baz', 'package:baz/baz.dart'), + ].map((i) => i.toSource()); + + expect( + identifiers, + [ + '_i1.Foo', + '_i1.Bar', + '_i2.Baz', + ], + ); + + expect( + scope.toImports().map((i) => i.buildAst().toSource()), + [ + r"import 'package:foo/foo.dart' as _i1;", + r"import 'package:baz/baz.dart' as _i2;", + ], + ); }); } diff --git a/pkgs/code_builder/tool/presubmit.sh b/pkgs/code_builder/tool/presubmit.sh new file mode 100755 index 000000000..035e29e64 --- /dev/null +++ b/pkgs/code_builder/tool/presubmit.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Make sure dartfmt is run on everything +# This assumes you have dart_style as a dev_dependency +echo "Checking dartfmt..." +NEEDS_DARTFMT="$(find lib test -name "*.dart" | xargs pub run dart_style:format -n)" +if [[ ${NEEDS_DARTFMT} != "" ]] +then + echo "FAILED" + echo "${NEEDS_DARTFMT}" + exit 1 +fi +echo "PASSED" + +# Make sure we pass the analyzer +echo "Checking dartanalyzer..." +FAILS_ANALYZER="$(find lib test -name "*.dart" | xargs dartanalyzer --options analysis_options.yaml)" +if [[ $FAILS_ANALYZER == *"[error]"* ]] +then + echo "FAILED" + echo "${FAILS_ANALYZER}" + exit 1 +fi +echo "PASSED" + +# Fail on anything that fails going forward. +set -e + +pub run test diff --git a/pkgs/code_builder/tool/travis.sh b/pkgs/code_builder/tool/travis.sh deleted file mode 100755 index cab493d2b..000000000 --- a/pkgs/code_builder/tool/travis.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# 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. - -# Fast fail the script on failures. -set -e - -# Verify that the libraries are error free. -dartanalyzer --fatal-warnings \ - lib/code_builder.dart \ - lib/dart/core.dart \ - lib/testing/equals_source.dart - -# Run the tests. -pub run test - -# Install dart_coveralls; gather and send coverage data. -if [ "$COVERALLS_TOKEN" ] && [ "$TRAVIS_DART_VERSION" = "stable" ]; then - dart tool/create_test_all.dart - pub global activate dart_coveralls - pub global run dart_coveralls report \ - --retry 2 \ - --exclude-test-files \ - tool/test_all.dart - rm tool/test_all.dart -fi From 86f9c0ffa5fbfd3d4c01202c797ae47258c2ed27 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 14 Nov 2016 16:59:44 -0800 Subject: [PATCH 015/271] Various changes to close a bunch of open issues (dart-lang/code_builder#21) * Various changes. * Update presubmit. --- ...nalysis_options.yaml => .analysis_options} | 19 +-- pkgs/code_builder/CHANGELOG.md | 9 ++ pkgs/code_builder/lib/code_builder.dart | 5 +- pkgs/code_builder/lib/dart/async.dart | 6 + pkgs/code_builder/lib/dart/core.dart | 5 + .../lib/src/builders/expression.dart | 153 +++++++++++++++--- .../lib/src/builders/expression/assert.dart | 4 + .../lib/src/builders/expression/assign.dart | 4 + .../src/builders/expression/invocation.dart | 4 + .../lib/src/builders/expression/negate.dart | 4 + .../src/builders/expression/operators.dart | 4 + .../lib/src/builders/expression/return.dart | 4 + pkgs/code_builder/lib/src/builders/field.dart | 4 + pkgs/code_builder/lib/src/builders/file.dart | 103 +++++++++++- .../lib/src/builders/statement/block.dart | 4 + .../lib/src/builders/statement/if.dart | 4 + .../lib/src/builders/type/new_instance.dart | 4 + pkgs/code_builder/lib/src/tokens.dart | 9 ++ .../test/builders/expression_test.dart | 23 +++ .../test/builders/field_test.dart | 4 + .../code_builder/test/builders/file_test.dart | 62 +++++++ .../test/builders/reference_test.dart | 9 -- .../test/builders/shared_test.dart | 4 + .../test/builders/statement_test.dart | 4 + .../code_builder/test/builders/type_test.dart | 4 + pkgs/code_builder/test/scope_test.dart | 4 + pkgs/code_builder/tool/presubmit.sh | 2 +- 27 files changed, 416 insertions(+), 49 deletions(-) rename pkgs/code_builder/{analysis_options.yaml => .analysis_options} (67%) create mode 100644 pkgs/code_builder/test/builders/file_test.dart delete mode 100644 pkgs/code_builder/test/builders/reference_test.dart diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/.analysis_options similarity index 67% rename from pkgs/code_builder/analysis_options.yaml rename to pkgs/code_builder/.analysis_options index b256a69bb..6f0443276 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/.analysis_options @@ -2,32 +2,27 @@ analyzer: strong-mode: true linter: rules: + # Errors - avoid_empty_else - - comment_references - control_flow_in_finally - empty_statements - - hash_and_equals - - iterable_contains_unrelated_type - - list_remove_unrelated_type - test_types_in_equals - throw_in_finally - - unrelated_type_equality_checks - valid_regexps - - always_declare_return_types + + # Style - annotate_overrides - avoid_init_to_null - avoid_return_types_on_setters - await_only_futures - camel_case_types - - constant_identifier_names + - comment_references - empty_catches - empty_constructor_bodies - - library_names + - hash_and_equals - library_prefixes - - only_throw_errors - - overridden_fields - - package_prefixed_library_names + - non_constant_identifier_names - prefer_is_not_empty - slash_for_doc_comments - type_init_formals - - unnecessary_getters_setters + - unrelated_type_equality_checks diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index ffc86f365..c2ed69bef 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 1.0.0-alpha+1 + +- Slight updates to confusing documentation. +- Added support for null-aware assignments. +- Added `show` and `hide` support to `ImportBuilder` +- Added `deferred` support to `ImportBuilder` +- Added `ExportBuilder` +- Added `list` and `map` literals that support generic types + ## 1.0.0-alpha - Large refactor that makes the library more feature complete. diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 950646846..abc143044 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -6,10 +6,11 @@ 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; + show literal, list, map, ExpressionBuilder, InvocationBuilder; export 'src/builders/field.dart' show varConst, varField, varFinal, FieldBuilder; -export 'src/builders/file.dart' show ImportBuilder, LibraryBuilder, PartBuilder; +export 'src/builders/file.dart' + show ExportBuilder, ImportBuilder, LibraryBuilder, PartBuilder; export 'src/builders/method.dart' show constructor, diff --git a/pkgs/code_builder/lib/dart/async.dart b/pkgs/code_builder/lib/dart/async.dart index 6025c39db..68d0b27db 100644 --- a/pkgs/code_builder/lib/dart/async.dart +++ b/pkgs/code_builder/lib/dart/async.dart @@ -35,6 +35,12 @@ class DartAsync { /// References [dart_async.Future]. final ReferenceBuilder Future = _ref('Future'); + /// References [dart_async.Stream]. + final ReferenceBuilder Stream = _ref('Stream'); + + /// References [dart_async.StreamSubscription]. + final ReferenceBuilder StreamSubscription = _ref('StreamSubscription'); + DartAsync._(); static ReferenceBuilder _ref(String name) => reference(name, 'dart:async'); diff --git a/pkgs/code_builder/lib/dart/core.dart b/pkgs/code_builder/lib/dart/core.dart index 9a5a0d7f0..fbbe89f03 100644 --- a/pkgs/code_builder/lib/dart/core.dart +++ b/pkgs/code_builder/lib/dart/core.dart @@ -213,6 +213,11 @@ class DartCore { /// References [dart_core.UriData]. final ReferenceBuilder UriData = _ref('UriData'); + /// References `dynamic` type for returning any in a method. + /// + /// **NOTE**: As a language limitation, this cannot be named `dynamic`. + final TypeBuilder $dynamic = new TypeBuilder('dynamic'); + /// References `void` type for returning nothing in a method. /// /// **NOTE**: As a language limitation, this cannot be named `void`. diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index faa78c738..4bd6439f1 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -1,8 +1,7 @@ -library code_builder.src.builders.expression; - // 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. +library code_builder.src.builders.expression; import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/token.dart'; @@ -32,7 +31,37 @@ final _true = new BooleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); /// Returns a pre-defined literal expression of [value]. /// /// Only primitive values are allowed. -ExpressionBuilder literal(value) => new _LiteralExpression(_literal(value)); +ExpressionBuilder literal(value) { + if (value is List) { + return list(value); + } + if (value is Map) { + return map(value); + } + return new _LiteralExpression(_literal(value)); +} + +/// Returns a literal `List` expression from [values]. +/// +/// Optionally specify [asConst] or with a generic [type]. +ExpressionBuilder list( + Iterable values, { + bool asConst: false, + TypeBuilder type, +}) => + new _TypedListExpression(values, asConst: asConst, type: type); + +/// Returns a literal `Map` expression from [values]. +/// +/// Optionally specify [asConst] or with a generic [keyType] or [valueType]. +ExpressionBuilder map( + Map values, { + bool asConst: false, + TypeBuilder keyType, + TypeBuilder valueType, +}) => + new _TypedMapExpression(values, + asConst: asConst, keyType: keyType, valueType: valueType); Literal _literal(value) { if (value == null) { @@ -45,24 +74,6 @@ Literal _literal(value) { return new IntegerLiteral(stringToken('$value'), value); } else if (value is double) { return new DoubleLiteral(stringToken('$value'), value); - } else if (value is List) { - return new ListLiteral( - null, - null, - $openBracket, - value.map/**/(_literal).toList(), - $closeBracket, - ); - } else if (value is Map) { - return new MapLiteral( - null, - null, - $openBracket, - value.keys.map/**/((k) { - return new MapLiteralEntry(_literal(k), $colon, _literal(value[k])); - }).toList(), - $closeBracket, - ); } throw new ArgumentError.value(value, 'Unsupported'); } @@ -357,3 +368,103 @@ class _ParenthesesExpression extends Object with AbstractExpressionMixin { ); } } + +ExpressionBuilder _expressionify(v) { + if (v == null || v is bool || v is String || v is int || v is double) { + return new _LiteralExpression(_literal(v)); + } + if (v is ExpressionBuilder) { + return v; + } + throw new ArgumentError('Could not expressionify $v'); +} + +class _TypedListExpression extends Object with AbstractExpressionMixin { + static List _toExpression(Iterable values) { + return values.map(_expressionify).toList(); + } + + final bool _asConst; + final TypeBuilder _type; + final List _values; + + _TypedListExpression(Iterable values, {bool asConst, TypeBuilder type}) + : _values = _toExpression(values), + _asConst = asConst, + _type = type; + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return new ListLiteral( + _asConst ? $const : null, + _type != null + ? new TypeArgumentList( + $openBracket, + [_type.buildType(scope)], + $closeBracket, + ) + : null, + $openBracket, + _values.map((v) => v.buildExpression(scope)).toList(), + $closeBracket, + ); + } +} + +class _TypedMapExpression extends Object with AbstractExpressionMixin { + static Map _toExpression(Map values) { + return new Map.fromIterable( + values.keys, + key: (k) => _expressionify(k), + value: (k) => _expressionify(values[k]), + ); + } + + final bool _asConst; + final TypeBuilder _keyType; + final TypeBuilder _valueType; + final Map _values; + + _TypedMapExpression(Map values, + {bool asConst, TypeBuilder keyType, TypeBuilder valueType}) + : _values = _toExpression(values), + _asConst = asConst, + _keyType = keyType != null + ? keyType + : valueType != null ? lib$core.$dynamic : null, + _valueType = valueType != null + ? valueType + : keyType != null ? lib$core.$dynamic : null; + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return new MapLiteral( + _asConst ? $const : null, + _keyType != null + ? new TypeArgumentList( + $openBracket, + [ + _keyType.buildType(scope), + _valueType.buildType(scope), + ], + $closeBracket, + ) + : null, + $openBracket, + _values.keys.map((k) { + return new MapLiteralEntry( + k.buildExpression(scope), + $colon, + _values[k].buildExpression(scope), + ); + }).toList(), + $closeBracket, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/assert.dart b/pkgs/code_builder/lib/src/builders/expression/assert.dart index 3313feec4..3030235ad 100644 --- a/pkgs/code_builder/lib/src/builders/expression/assert.dart +++ b/pkgs/code_builder/lib/src/builders/expression/assert.dart @@ -1,3 +1,7 @@ +// 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. + part of code_builder.src.builders.expression; class _AsAssert implements StatementBuilder { diff --git a/pkgs/code_builder/lib/src/builders/expression/assign.dart b/pkgs/code_builder/lib/src/builders/expression/assign.dart index 5c6b19167..00bf01773 100644 --- a/pkgs/code_builder/lib/src/builders/expression/assign.dart +++ b/pkgs/code_builder/lib/src/builders/expression/assign.dart @@ -1,3 +1,7 @@ +// 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. + part of code_builder.src.builders.expression; class _AsAssign extends AbstractExpressionMixin { diff --git a/pkgs/code_builder/lib/src/builders/expression/invocation.dart b/pkgs/code_builder/lib/src/builders/expression/invocation.dart index 1c015e6e2..cef1e323a 100644 --- a/pkgs/code_builder/lib/src/builders/expression/invocation.dart +++ b/pkgs/code_builder/lib/src/builders/expression/invocation.dart @@ -1,3 +1,7 @@ +// 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. + part of code_builder.src.builders.expression; /// Partial implementation of [InvocationBuilder]. diff --git a/pkgs/code_builder/lib/src/builders/expression/negate.dart b/pkgs/code_builder/lib/src/builders/expression/negate.dart index d1d58d3dc..e5fa83495 100644 --- a/pkgs/code_builder/lib/src/builders/expression/negate.dart +++ b/pkgs/code_builder/lib/src/builders/expression/negate.dart @@ -1,3 +1,7 @@ +// 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. + part of code_builder.src.builders.expression; class _NegateExpression extends AbstractExpressionMixin { diff --git a/pkgs/code_builder/lib/src/builders/expression/operators.dart b/pkgs/code_builder/lib/src/builders/expression/operators.dart index f36140a26..cebc85296 100644 --- a/pkgs/code_builder/lib/src/builders/expression/operators.dart +++ b/pkgs/code_builder/lib/src/builders/expression/operators.dart @@ -1,3 +1,7 @@ +// 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. + part of code_builder.src.builders.expression; class _AsBinaryExpression extends Object with AbstractExpressionMixin { diff --git a/pkgs/code_builder/lib/src/builders/expression/return.dart b/pkgs/code_builder/lib/src/builders/expression/return.dart index d57c7deff..0778b0f87 100644 --- a/pkgs/code_builder/lib/src/builders/expression/return.dart +++ b/pkgs/code_builder/lib/src/builders/expression/return.dart @@ -1,3 +1,7 @@ +// 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. + part of code_builder.src.builders.expression; class _AsReturn implements StatementBuilder { diff --git a/pkgs/code_builder/lib/src/builders/field.dart b/pkgs/code_builder/lib/src/builders/field.dart index 51b5d978f..16e10fcb9 100644 --- a/pkgs/code_builder/lib/src/builders/field.dart +++ b/pkgs/code_builder/lib/src/builders/field.dart @@ -1,3 +1,7 @@ +// 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. + import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/src/dart/ast/token.dart'; diff --git a/pkgs/code_builder/lib/src/builders/file.dart b/pkgs/code_builder/lib/src/builders/file.dart index fc6e71be6..ce580f4dc 100644 --- a/pkgs/code_builder/lib/src/builders/file.dart +++ b/pkgs/code_builder/lib/src/builders/file.dart @@ -131,25 +131,120 @@ class _LibraryDirectiveBuilder implements AstBuilder { class ImportBuilder implements AstBuilder { final String _prefix; final String _uri; + final bool _deferred; - factory ImportBuilder(String path, {String prefix}) { - return new ImportBuilder._(path, prefix); + final Set _show = new Set(); + final Set _hide = new Set(); + + factory ImportBuilder(String path, {bool deferred: false, String prefix}) { + return new ImportBuilder._(path, prefix, deferred); + } + + ImportBuilder._(this._uri, this._prefix, this._deferred); + + void hide(String identifier) { + _hide.add(identifier); } - ImportBuilder._(this._uri, this._prefix); + void hideAll(Iterable identifiers) { + _hide.addAll(identifiers); + } + + void show(String identifier) { + _show.add(identifier); + } + + void showAll(Iterable identifier) { + _show.addAll(identifier); + } @override ImportDirective buildAst([_]) { + var combinators = []; + if (_show.isNotEmpty) { + combinators.add( + new ShowCombinator( + $show, + _show.map(stringIdentifier).toList(), + ), + ); + } + if (_hide.isNotEmpty) { + combinators.add( + new HideCombinator( + $hide, + _hide.map(stringIdentifier).toList(), + ), + ); + } return new ImportDirective( null, null, null, new SimpleStringLiteral(stringToken("'$_uri'"), _uri), null, - null, + _deferred ? $deferred : null, _prefix != null ? $as : null, _prefix != null ? stringIdentifier(_prefix) : null, + combinators, + $semicolon, + ); + } +} + +/// Lazily builds an [ExportDirective] AST when built. +class ExportBuilder implements AstBuilder { + final String _uri; + + final Set _show = new Set(); + final Set _hide = new Set(); + + factory ExportBuilder(String path) = ExportBuilder._; + + ExportBuilder._(this._uri); + + void hide(String identifier) { + _hide.add(identifier); + } + + void hideAll(Iterable identifiers) { + _hide.addAll(identifiers); + } + + void show(String identifier) { + _show.add(identifier); + } + + void showAll(Iterable identifier) { + _show.addAll(identifier); + } + + @override + ExportDirective buildAst([_]) { + var combinators = []; + if (_show.isNotEmpty) { + combinators.add( + new ShowCombinator( + $show, + _show.map(stringIdentifier).toList(), + ), + ); + } + if (_hide.isNotEmpty) { + combinators.add( + new HideCombinator( + $hide, + _hide.map(stringIdentifier).toList(), + ), + ); + } + return new ExportDirective( + null, + null, + null, + new SimpleStringLiteral(stringToken("'$_uri'"), _uri), null, + combinators, $semicolon, ); } diff --git a/pkgs/code_builder/lib/src/builders/statement/block.dart b/pkgs/code_builder/lib/src/builders/statement/block.dart index 57ef9ebef..f3f8e69b5 100644 --- a/pkgs/code_builder/lib/src/builders/statement/block.dart +++ b/pkgs/code_builder/lib/src/builders/statement/block.dart @@ -1,3 +1,7 @@ +// 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. + import 'package:analyzer/analyzer.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement.dart'; diff --git a/pkgs/code_builder/lib/src/builders/statement/if.dart b/pkgs/code_builder/lib/src/builders/statement/if.dart index ad3b9a9f7..768c8d27a 100644 --- a/pkgs/code_builder/lib/src/builders/statement/if.dart +++ b/pkgs/code_builder/lib/src/builders/statement/if.dart @@ -1,3 +1,7 @@ +// 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. + import 'package:analyzer/dart/ast/ast.dart'; import 'package:code_builder/src/builders/expression.dart'; import 'package:code_builder/src/builders/shared.dart'; diff --git a/pkgs/code_builder/lib/src/builders/type/new_instance.dart b/pkgs/code_builder/lib/src/builders/type/new_instance.dart index c2d9b6887..05b9b9d6c 100644 --- a/pkgs/code_builder/lib/src/builders/type/new_instance.dart +++ b/pkgs/code_builder/lib/src/builders/type/new_instance.dart @@ -1,3 +1,7 @@ +// 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. + part of code_builder.src.builders.type; /// Lazily builds an [InstanceCreationExpression] AST when built. diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index 17e70b5be..9b97264e2 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -35,6 +35,9 @@ final Token $colon = new Token(TokenType.COLON, 0); /// The `const` token. final Token $const = new KeywordToken(Keyword.CONST, 0); +/// The `deferred` token. +final Token $deferred = new KeywordToken(Keyword.DEFERRED, 0); + /// The `/` token. final Token $divide = new Token(TokenType.SLASH, 0); @@ -64,6 +67,9 @@ final Token $if = new KeywordToken(Keyword.IF, 0); // Simple tokens +/// The `hide` token. +final Token $hide = new StringToken(TokenType.KEYWORD, 'hide', 0); + /// The `implements` token. final Token $implements = new KeywordToken(Keyword.IMPLEMENTS, 0); @@ -121,6 +127,9 @@ final Token $return = new KeywordToken(Keyword.RETURN, 0); /// The ';' token. final Token $semicolon = new Token(TokenType.SEMICOLON, 0); +/// The `show` token. +final Token $show = new StringToken(TokenType.KEYWORD, 'show', 0); + /// The `static` token. final Token $static = new KeywordToken(Keyword.STATIC, 0); diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 5d6b453df..78f5198c7 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -37,9 +37,32 @@ void main() { expect(literal([1, 2, 3]), equalsSource(r'[1, 2, 3]')); }); + test('should emit a typed list', () { + expect( + list([1, 2, 3], type: lib$core.int), + equalsSource(r' [1, 2, 3]'), + ); + }); + test('should emit a map', () { expect(literal({1: 2, 2: 3}), equalsSource(r'{1 : 2, 2 : 3}')); }); + + test('should emit a typed map', () { + expect( + map( + { + 1: '2', + 2: '3', + }, + keyType: lib$core.int, + valueType: lib$core.String, + ), + equalsSource(r''' + {1 : '2', 2 : '3'} + '''), + ); + }); }); test('should emit an assert statemnet', () { diff --git a/pkgs/code_builder/test/builders/field_test.dart b/pkgs/code_builder/test/builders/field_test.dart index fcadb6690..739e7a726 100644 --- a/pkgs/code_builder/test/builders/field_test.dart +++ b/pkgs/code_builder/test/builders/field_test.dart @@ -1,3 +1,7 @@ +// 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. + import 'package:code_builder/code_builder.dart'; import 'package:code_builder/dart/core.dart'; import 'package:code_builder/testing.dart'; diff --git a/pkgs/code_builder/test/builders/file_test.dart b/pkgs/code_builder/test/builders/file_test.dart new file mode 100644 index 000000000..f9f258c2a --- /dev/null +++ b/pkgs/code_builder/test/builders/file_test.dart @@ -0,0 +1,62 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +void main() { + group('$ImportBuilder', () { + test('should support "show"', () { + expect( + new ImportBuilder('package:foo/foo.dart')..show('Foo'), + equalsSource(r''' + import 'package:foo/foo.dart' show Foo; + '''), + ); + }); + + test('should support "show"', () { + expect( + new ImportBuilder('package:foo/foo.dart')..hide('Bar'), + equalsSource(r''' + import 'package:foo/foo.dart' hide Bar; + '''), + ); + }); + + test('should support "deferred as"', () { + expect( + new ImportBuilder( + 'package:foo/foo.dart', + deferred: true, + prefix: 'foo', + ), + equalsSource(r''' + import 'package:foo/foo.dart' deferred as foo; + '''), + ); + }); + }); + + group('$ExportBuilder', () { + test('should support "show"', () { + expect( + new ExportBuilder('package:foo/foo.dart')..show('Foo'), + equalsSource(r''' + export 'package:foo/foo.dart' show Foo; + '''), + ); + }); + + test('should support "show"', () { + expect( + new ExportBuilder('package:foo/foo.dart')..hide('Bar'), + equalsSource(r''' + export 'package:foo/foo.dart' hide Bar; + '''), + ); + }); + }); +} diff --git a/pkgs/code_builder/test/builders/reference_test.dart b/pkgs/code_builder/test/builders/reference_test.dart deleted file mode 100644 index f25ae74e0..000000000 --- a/pkgs/code_builder/test/builders/reference_test.dart +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -import 'package:test/test.dart'; - -void main() { - group('reference', () {}); -} diff --git a/pkgs/code_builder/test/builders/shared_test.dart b/pkgs/code_builder/test/builders/shared_test.dart index a38a06223..12a314f65 100644 --- a/pkgs/code_builder/test/builders/shared_test.dart +++ b/pkgs/code_builder/test/builders/shared_test.dart @@ -2,6 +2,10 @@ // 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. +// 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. + import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/tokens.dart'; import 'package:test/test.dart'; diff --git a/pkgs/code_builder/test/builders/statement_test.dart b/pkgs/code_builder/test/builders/statement_test.dart index b899c8531..5833a7e5a 100644 --- a/pkgs/code_builder/test/builders/statement_test.dart +++ b/pkgs/code_builder/test/builders/statement_test.dart @@ -1,3 +1,7 @@ +// 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. + import 'package:code_builder/code_builder.dart'; import 'package:code_builder/dart/core.dart'; import 'package:code_builder/testing.dart'; diff --git a/pkgs/code_builder/test/builders/type_test.dart b/pkgs/code_builder/test/builders/type_test.dart index b9ac7b8ea..323f9722c 100644 --- a/pkgs/code_builder/test/builders/type_test.dart +++ b/pkgs/code_builder/test/builders/type_test.dart @@ -1,3 +1,7 @@ +// 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. + import 'package:code_builder/code_builder.dart'; import 'package:code_builder/dart/core.dart'; import 'package:code_builder/testing.dart'; diff --git a/pkgs/code_builder/test/scope_test.dart b/pkgs/code_builder/test/scope_test.dart index 64b41d5d3..084d7affc 100644 --- a/pkgs/code_builder/test/scope_test.dart +++ b/pkgs/code_builder/test/scope_test.dart @@ -1,3 +1,7 @@ +// 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. + import 'package:analyzer/analyzer.dart'; import 'package:code_builder/src/scope.dart'; import 'package:test/test.dart'; diff --git a/pkgs/code_builder/tool/presubmit.sh b/pkgs/code_builder/tool/presubmit.sh index 035e29e64..364bee71d 100755 --- a/pkgs/code_builder/tool/presubmit.sh +++ b/pkgs/code_builder/tool/presubmit.sh @@ -14,7 +14,7 @@ echo "PASSED" # Make sure we pass the analyzer echo "Checking dartanalyzer..." -FAILS_ANALYZER="$(find lib test -name "*.dart" | xargs dartanalyzer --options analysis_options.yaml)" +FAILS_ANALYZER="$(find lib test -name "*.dart" | xargs dartanalyzer --options .analysis_options)" if [[ $FAILS_ANALYZER == *"[error]"* ]] then echo "FAILED" From e6b7849e1a3fd5bd38b3359b4326b72837751834 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 16 Nov 2016 12:20:30 -0800 Subject: [PATCH 016/271] More parity support with the Angular Dart output AST (dart-lang/code_builder#25) * Various changes. * Update presubmit. * More changes to get NG2-output parity --- pkgs/code_builder/.analysis_options | 3 +- pkgs/code_builder/CHANGELOG.md | 33 ++++++++++ pkgs/code_builder/lib/code_builder.dart | 2 +- .../lib/src/builders/expression.dart | 61 ++++++++++++++++--- .../lib/src/builders/expression/assert.dart | 4 +- .../lib/src/builders/expression/assign.dart | 31 ++++++++-- .../lib/src/builders/expression/cascade.dart | 23 +++++++ .../src/builders/expression/invocation.dart | 4 +- .../src/builders/expression/operators.dart | 2 +- .../lib/src/builders/expression/return.dart | 2 +- pkgs/code_builder/lib/src/builders/field.dart | 2 +- pkgs/code_builder/lib/src/builders/file.dart | 24 ++++++-- .../lib/src/builders/reference.dart | 3 +- .../lib/src/builders/statement.dart | 31 ++++++++++ .../lib/src/builders/statement/block.dart | 2 +- .../lib/src/builders/statement/if.dart | 2 +- pkgs/code_builder/lib/src/builders/type.dart | 1 + .../lib/src/builders/type/new_instance.dart | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/expression_test.dart | 25 ++++++++ .../test/builders/statement_test.dart | 9 +++ 21 files changed, 235 insertions(+), 33 deletions(-) create mode 100644 pkgs/code_builder/lib/src/builders/expression/cascade.dart diff --git a/pkgs/code_builder/.analysis_options b/pkgs/code_builder/.analysis_options index 6f0443276..1196b5dfa 100644 --- a/pkgs/code_builder/.analysis_options +++ b/pkgs/code_builder/.analysis_options @@ -21,7 +21,8 @@ linter: - empty_constructor_bodies - hash_and_equals - library_prefixes - - non_constant_identifier_names + # This convention is broken on purpose in parts of the code. + # - non_constant_identifier_names - prefer_is_not_empty - slash_for_doc_comments - type_init_formals diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index c2ed69bef..8d18774ef 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,38 @@ # Changelog +## 1.0.0-alpha+2 + +- Added `returnVoid` to well, `return;` +- Added support for top-level field assignments: + +```dart +new LibraryBuilder()..addMember(literal(false).asConst('foo')) +``` + +- Added support for specifying a `target` when using `asAssign`: + +```dart +// Outputs bank.bar = goldBar +reference('goldBar').asAssign('bar', target: reference('bank')) +``` + +- Added support for the cascade operator: + +```dart +// Outputs foo..doThis()..doThat() +reference('foo').cascade((c) => [ + c.invoke('doThis', []), + c.invoke('doThat', []), +]); +``` + +- Added support for accessing a property + +```dart +// foo.bar +reference('foo').property('bar'); +``` + ## 1.0.0-alpha+1 - Slight updates to confusing documentation. diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index abc143044..62644494c 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -30,5 +30,5 @@ 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; + show ifThen, elseIf, elseThen, returnVoid, IfStatementBuilder, StatementBuilder; export 'src/builders/type.dart' show NewInstanceBuilder, TypeBuilder; diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index 4bd6439f1..55d979144 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -9,6 +9,7 @@ import 'package:analyzer/src/dart/ast/token.dart'; import 'package:code_builder/dart/core.dart'; import 'package:code_builder/src/builders/method.dart'; import 'package:code_builder/src/builders/parameter.dart'; +import 'package:code_builder/src/builders/reference.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/builders/statement/if.dart'; @@ -17,6 +18,7 @@ import 'package:code_builder/src/tokens.dart'; part 'expression/assert.dart'; part 'expression/assign.dart'; +part 'expression/cascade.dart'; part 'expression/invocation.dart'; part 'expression/negate.dart'; part 'expression/operators.dart'; @@ -79,7 +81,7 @@ Literal _literal(value) { } /// Implements much of [ExpressionBuilder]. -abstract class AbstractExpressionMixin implements ExpressionBuilder { +abstract class AbstractExpressionMixin extends TopLevelMixin implements ExpressionBuilder { @override ExpressionBuilder operator *(ExpressionBuilder other) { return new _AsBinaryExpression( @@ -122,9 +124,10 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { @override StatementBuilder asAssign( String variable, { + ExpressionBuilder target, bool nullAware: false, }) => - new _AsAssign(this, variable, nullAware); + new _AsAssign(this, variable, nullAware, target); @override StatementBuilder asConst(String variable, [TypeBuilder type]) { @@ -166,6 +169,14 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { return invocation; } + @override + ExpressionBuilder cascade( + Iterable create(ExpressionBuilder self), + ) { + // Sorry for the huge hack. Need to think more clearly about this in future. + return new _CascadeExpression(this, create(reference('.'))); + } + @override ExpressionBuilder equals(ExpressionBuilder other) { return new _AsBinaryExpression( @@ -212,6 +223,9 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { @override ExpressionBuilder parentheses() => new _ParenthesesExpression(this); + + @override + ExpressionBuilder property(String name) => new _MemberExpression(this, name); } /// Builds an [Expression] AST when [buildExpression] is invoked. @@ -233,7 +247,9 @@ abstract class ExpressionBuilder StatementBuilder asAssert(); /// Returns as a [StatementBuilder] that assigns to an existing [variable]. - StatementBuilder asAssign(String variable, {bool nullAware}); + /// + /// If [target] is specified, determined to be `{target}.{variable}`. + StatementBuilder asAssign(String variable, {ExpressionBuilder target, bool nullAware}); /// Returns as a [StatementBuilder] that assigns to a new `const` [variable]. StatementBuilder asConst(String variable, [TypeBuilder type]); @@ -268,6 +284,11 @@ abstract class ExpressionBuilder Map namedArguments, ]); + /// Return as an [ExpressionBuilder] with `..` appended. + ExpressionBuilder cascade( + Iterable create(ExpressionBuilder self), + ); + /// Returns as an [ExpressionBuilder] comparing using `==` against [other]. ExpressionBuilder equals(ExpressionBuilder other); @@ -292,6 +313,9 @@ abstract class ExpressionBuilder /// Returns as an [ExpressionBuilder] wrapped in parentheses. ExpressionBuilder parentheses(); + + /// Returns {{this}}.{{name}}. + ExpressionBuilder property(String name); } /// An [AstBuilder] that can add [ExpressionBuilder]. @@ -322,13 +346,13 @@ abstract class HasExpressionsMixin extends HasExpressions { } } -class _AsStatement implements StatementBuilder { +class _AsStatement extends TopLevelMixin implements StatementBuilder { final ExpressionBuilder _expression; _AsStatement(this._expression); @override - AstNode buildAst([Scope scope]) => buildStatement(scope); + Statement buildAst([Scope scope]) => buildStatement(scope); @override Statement buildStatement([Scope scope]) { @@ -339,7 +363,26 @@ class _AsStatement implements StatementBuilder { } } -class _LiteralExpression extends Object with AbstractExpressionMixin { +class _MemberExpression extends Object with AbstractExpressionMixin, TopLevelMixin { + final String _name; + final ExpressionBuilder _target; + + _MemberExpression(this._target, this._name); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return new PropertyAccess( + _target.buildExpression(scope), + $period, + stringIdentifier(_name), + ); + } +} + +class _LiteralExpression extends Object with AbstractExpressionMixin, TopLevelMixin { final Literal _literal; _LiteralExpression(this._literal); @@ -351,7 +394,7 @@ class _LiteralExpression extends Object with AbstractExpressionMixin { Expression buildExpression([_]) => _literal; } -class _ParenthesesExpression extends Object with AbstractExpressionMixin { +class _ParenthesesExpression extends Object with AbstractExpressionMixin, TopLevelMixin { final ExpressionBuilder _expression; _ParenthesesExpression(this._expression); @@ -379,7 +422,7 @@ ExpressionBuilder _expressionify(v) { throw new ArgumentError('Could not expressionify $v'); } -class _TypedListExpression extends Object with AbstractExpressionMixin { +class _TypedListExpression extends Object with AbstractExpressionMixin, TopLevelMixin { static List _toExpression(Iterable values) { return values.map(_expressionify).toList(); } @@ -414,7 +457,7 @@ class _TypedListExpression extends Object with AbstractExpressionMixin { } } -class _TypedMapExpression extends Object with AbstractExpressionMixin { +class _TypedMapExpression extends Object with AbstractExpressionMixin, TopLevelMixin { static Map _toExpression(Map values) { return new Map.fromIterable( values.keys, diff --git a/pkgs/code_builder/lib/src/builders/expression/assert.dart b/pkgs/code_builder/lib/src/builders/expression/assert.dart index 3030235ad..f3ed0c2e8 100644 --- a/pkgs/code_builder/lib/src/builders/expression/assert.dart +++ b/pkgs/code_builder/lib/src/builders/expression/assert.dart @@ -4,13 +4,13 @@ part of code_builder.src.builders.expression; -class _AsAssert implements StatementBuilder { +class _AsAssert extends TopLevelMixin implements StatementBuilder { final ExpressionBuilder _expression; _AsAssert(this._expression); @override - AstNode buildAst([Scope scope]) => buildStatement(scope); + Statement buildAst([Scope scope]) => buildStatement(scope); @override Statement buildStatement([Scope scope]) { diff --git a/pkgs/code_builder/lib/src/builders/expression/assign.dart b/pkgs/code_builder/lib/src/builders/expression/assign.dart index 00bf01773..f60768327 100644 --- a/pkgs/code_builder/lib/src/builders/expression/assign.dart +++ b/pkgs/code_builder/lib/src/builders/expression/assign.dart @@ -8,8 +8,9 @@ class _AsAssign extends AbstractExpressionMixin { final String _name; final bool _nullAware; final ExpressionBuilder _value; + final ExpressionBuilder _target; - _AsAssign(this._value, this._name, this._nullAware); + _AsAssign(this._value, this._name, this._nullAware, this._target); @override AstNode buildAst([Scope scope]) => buildExpression(scope); @@ -17,14 +18,14 @@ class _AsAssign extends AbstractExpressionMixin { @override Expression buildExpression([Scope scope]) { return new AssignmentExpression( - stringIdentifier(_name), + _target != null ? _target.property(_name).buildExpression(scope) : stringIdentifier(_name), _nullAware ? $nullAwareEquals : $equals, _value.buildExpression(scope), ); } } -class _AsAssignNew implements StatementBuilder { +class _AsAssignNew extends TopLevelMixin implements StatementBuilder { final ExpressionBuilder _value; final String _name; final TypeBuilder _type; @@ -33,7 +34,7 @@ class _AsAssignNew implements StatementBuilder { _AsAssignNew(this._value, this._name, this._type, this._modifier); @override - AstNode buildAst([Scope scope]) => buildStatement(scope); + Statement buildAst([Scope scope]) => buildStatement(scope); @override Statement buildStatement([Scope scope]) { @@ -54,4 +55,26 @@ class _AsAssignNew implements StatementBuilder { $semicolon, ); } + + @override + CompilationUnitMember buildTopLevelAst([Scope scope]) { + return new TopLevelVariableDeclaration( + null, + null, + new VariableDeclarationList( + null, + null, + _type == null || _modifier != $var ? _modifier : null, + _type?.buildType(scope), + [ + new VariableDeclaration( + stringIdentifier(_name), + $equals, + _value.buildExpression(scope), + ), + ], + ), + $semicolon, + ); + } } diff --git a/pkgs/code_builder/lib/src/builders/expression/cascade.dart b/pkgs/code_builder/lib/src/builders/expression/cascade.dart new file mode 100644 index 000000000..d90ff5641 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/cascade.dart @@ -0,0 +1,23 @@ +// 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. + +part of code_builder.src.builders.expression; + +class _CascadeExpression extends TopLevelMixin with AbstractExpressionMixin { + final List _cascades; + final ExpressionBuilder _target; + + _CascadeExpression(this._target, this._cascades); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return new CascadeExpression( + _target.buildExpression(scope), + _cascades.map((e) => e.buildExpression(scope)).toList(), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/invocation.dart b/pkgs/code_builder/lib/src/builders/expression/invocation.dart index cef1e323a..80cd1bf71 100644 --- a/pkgs/code_builder/lib/src/builders/expression/invocation.dart +++ b/pkgs/code_builder/lib/src/builders/expression/invocation.dart @@ -63,7 +63,7 @@ abstract class InvocationBuilder } class _FunctionInvocationBuilder extends Object - with AbstractInvocationBuilderMixin, AbstractExpressionMixin + with AbstractInvocationBuilderMixin, AbstractExpressionMixin, TopLevelMixin implements InvocationBuilder { final ExpressionBuilder _target; @@ -80,7 +80,7 @@ class _FunctionInvocationBuilder extends Object } class _MethodInvocationBuilder extends Object - with AbstractInvocationBuilderMixin, AbstractExpressionMixin + with AbstractInvocationBuilderMixin, AbstractExpressionMixin, TopLevelMixin implements InvocationBuilder { final String _method; final ExpressionBuilder _target; diff --git a/pkgs/code_builder/lib/src/builders/expression/operators.dart b/pkgs/code_builder/lib/src/builders/expression/operators.dart index cebc85296..9687056b2 100644 --- a/pkgs/code_builder/lib/src/builders/expression/operators.dart +++ b/pkgs/code_builder/lib/src/builders/expression/operators.dart @@ -4,7 +4,7 @@ part of code_builder.src.builders.expression; -class _AsBinaryExpression extends Object with AbstractExpressionMixin { +class _AsBinaryExpression extends Object with AbstractExpressionMixin, TopLevelMixin { final ExpressionBuilder _left; final ExpressionBuilder _right; final Token _operator; diff --git a/pkgs/code_builder/lib/src/builders/expression/return.dart b/pkgs/code_builder/lib/src/builders/expression/return.dart index 0778b0f87..ade5cea31 100644 --- a/pkgs/code_builder/lib/src/builders/expression/return.dart +++ b/pkgs/code_builder/lib/src/builders/expression/return.dart @@ -4,7 +4,7 @@ part of code_builder.src.builders.expression; -class _AsReturn implements StatementBuilder { +class _AsReturn extends TopLevelMixin implements StatementBuilder { final ExpressionBuilder _value; _AsReturn(this._value); diff --git a/pkgs/code_builder/lib/src/builders/field.dart b/pkgs/code_builder/lib/src/builders/field.dart index 16e10fcb9..da5f83572 100644 --- a/pkgs/code_builder/lib/src/builders/field.dart +++ b/pkgs/code_builder/lib/src/builders/field.dart @@ -105,7 +105,7 @@ abstract class FieldBuilder TopLevelVariableDeclaration buildTopLevel([Scope scope]); } -class _FieldBuilderImpl extends Object +class _FieldBuilderImpl extends TopLevelMixin with HasAnnotationsMixin implements FieldBuilder { final Keyword _keyword; diff --git a/pkgs/code_builder/lib/src/builders/file.dart b/pkgs/code_builder/lib/src/builders/file.dart index ce580f4dc..e6e8f186b 100644 --- a/pkgs/code_builder/lib/src/builders/file.dart +++ b/pkgs/code_builder/lib/src/builders/file.dart @@ -4,24 +4,24 @@ import 'package:analyzer/analyzer.dart'; import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/tokens.dart'; /// Builds a file of Dart source code. /// /// See [LibraryBuilder] and [PartBuilder] for concrete implementations. abstract class FileBuilder implements AstBuilder { - final List> _members = - >[]; + final List _members = []; FileBuilder._(); /// Adds a top-level field or class [member]. - void addMember(AstBuilder member) { + void addMember(AstBuilder member) { _members.add(member); } /// Adds top-level field or class [members]. - void addMembers(Iterable> members) { + void addMembers(Iterable members) { _members.addAll(members); } } @@ -60,7 +60,14 @@ class LibraryBuilder extends FileBuilder { @override CompilationUnit buildAst([_]) { - var members = _members.map((m) => m.buildAst(_scope)).toList(); + var members = _members + .map((m) { + if (m is TopLevelMixin) { + return (m as TopLevelMixin).buildTopLevelAst(_scope); + } + return m.buildAst(_scope); + }) + .toList(); var directives = [] ..addAll(_scope.toImports().map((d) => d.buildAst())) ..addAll(_directives.map((d) => d.buildAst())); @@ -100,7 +107,12 @@ class PartBuilder extends FileBuilder { $semicolon, ) ], - _members.map((m) => m.buildAst()).toList(), + _members.map((m) { + if (m is TopLevelMixin) { + return (m as TopLevelMixin).buildTopLevelAst(); + } + return m.buildAst(); + }).toList(), null, ); } diff --git a/pkgs/code_builder/lib/src/builders/reference.dart b/pkgs/code_builder/lib/src/builders/reference.dart index 31be042ec..87c6271fc 100644 --- a/pkgs/code_builder/lib/src/builders/reference.dart +++ b/pkgs/code_builder/lib/src/builders/reference.dart @@ -6,6 +6,7 @@ import 'package:analyzer/analyzer.dart'; import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/expression.dart'; import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/builders/type.dart'; import 'package:code_builder/src/tokens.dart'; @@ -19,7 +20,7 @@ ReferenceBuilder reference(String name, [String importUri]) { /// An abstract way of representing other types of [AstBuilder]. class ReferenceBuilder extends Object - with AbstractExpressionMixin, AbstractTypeBuilderMixin + with AbstractExpressionMixin, AbstractTypeBuilderMixin, TopLevelMixin implements AnnotationBuilder, ExpressionBuilder, TypeBuilder { final String _importFrom; final String _name; diff --git a/pkgs/code_builder/lib/src/builders/statement.dart b/pkgs/code_builder/lib/src/builders/statement.dart index d12b048c4..d19d7ae26 100644 --- a/pkgs/code_builder/lib/src/builders/statement.dart +++ b/pkgs/code_builder/lib/src/builders/statement.dart @@ -63,9 +63,40 @@ abstract class HasStatementsMixin implements HasStatements { abstract class StatementBuilder implements AstBuilder, + TopLevelMixin, ValidIfStatementMember, ValidConstructorMember, ValidMethodMember { /// Returns an [Statement] AST representing the builder. Statement buildStatement([Scope scope]); } + +/// Implements [buildTopLevelAst]. +abstract class TopLevelMixin { + /// Returns a [Statement] suitable for a top-level expression. + /// + /// May throw [UnsupportedError]. + CompilationUnitMember buildTopLevelAst([Scope scope]) { + throw new UnsupportedError('$runtimeType does not work in the top-level'); + } +} + +/// Just the `return;` statement, for `void` methods. +const StatementBuilder returnVoid = const _ReturnStatementBuilder(); + +class _ReturnStatementBuilder extends Object implements StatementBuilder { + const _ReturnStatementBuilder(); + + @override + Statement buildAst([_]) => buildStatement(); + + @override + Statement buildStatement([_]) { + return new ReturnStatement($return, null, $semicolon); + } + + @override + CompilationUnitMember buildTopLevelAst([Scope scope]) { + throw new UnsupportedError('$runtimeType does not work in the top-level'); + } +} diff --git a/pkgs/code_builder/lib/src/builders/statement/block.dart b/pkgs/code_builder/lib/src/builders/statement/block.dart index f3f8e69b5..d39cf0ece 100644 --- a/pkgs/code_builder/lib/src/builders/statement/block.dart +++ b/pkgs/code_builder/lib/src/builders/statement/block.dart @@ -15,7 +15,7 @@ abstract class BlockStatementBuilder } class _BlockStatementBuilder extends Object - with HasStatementsMixin + with HasStatementsMixin, TopLevelMixin implements BlockStatementBuilder { @override AstNode buildAst([Scope scope]) => buildStatement(scope); diff --git a/pkgs/code_builder/lib/src/builders/statement/if.dart b/pkgs/code_builder/lib/src/builders/statement/if.dart index 768c8d27a..b778010d2 100644 --- a/pkgs/code_builder/lib/src/builders/statement/if.dart +++ b/pkgs/code_builder/lib/src/builders/statement/if.dart @@ -59,7 +59,7 @@ abstract class IfStatementBuilder implements HasStatements, StatementBuilder { /// Marker interface for builders valid for use with [ifThen]. abstract class ValidIfStatementMember implements AstBuilder {} -class _BlockIfStatementBuilder extends HasStatementsMixin +class _BlockIfStatementBuilder extends Object with HasStatementsMixin, TopLevelMixin implements IfStatementBuilder { final ExpressionBuilder _condition; StatementBuilder _elseBlock; diff --git a/pkgs/code_builder/lib/src/builders/type.dart b/pkgs/code_builder/lib/src/builders/type.dart index c4eae10c0..8c96fe5df 100644 --- a/pkgs/code_builder/lib/src/builders/type.dart +++ b/pkgs/code_builder/lib/src/builders/type.dart @@ -12,6 +12,7 @@ import 'package:code_builder/src/builders/expression.dart'; import 'package:code_builder/src/builders/method.dart'; import 'package:code_builder/src/builders/parameter.dart'; import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/tokens.dart'; part 'type/new_instance.dart'; diff --git a/pkgs/code_builder/lib/src/builders/type/new_instance.dart b/pkgs/code_builder/lib/src/builders/type/new_instance.dart index 05b9b9d6c..6129d876b 100644 --- a/pkgs/code_builder/lib/src/builders/type/new_instance.dart +++ b/pkgs/code_builder/lib/src/builders/type/new_instance.dart @@ -23,7 +23,7 @@ abstract class NewInstanceBuilder } class _NewInvocationBuilderImpl extends Object - with AbstractExpressionMixin, AbstractInvocationBuilderMixin + with AbstractExpressionMixin, AbstractInvocationBuilderMixin, TopLevelMixin implements NewInstanceBuilder { final String _name; final Keyword _keyword; diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 84f1bd955..05c0aedcb 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-alpha +version: 1.0.0-alpha+2 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 78f5198c7..123186aea 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -267,4 +267,29 @@ void main() { '''), ); }); + + test('should emit a top-level field declaration', () { + expect( + new LibraryBuilder()..addMember(literal(false).asConst('foo')), + equalsSource(r''' + const foo = false; + '''), + ); + }); + + test('should emit cascaded expressions', () { + expect( + reference('foo').cascade((c) => [ + c.invoke('doThis', []), + c.invoke('doThat', []), + reference('Bar').newInstance([]).asAssign('bar', target: c), + ]).asStatement(), + equalsSource(r''' + foo + ..doThis() + ..doThat() + ..bar = new Bar(); + '''), + ); + }); } diff --git a/pkgs/code_builder/test/builders/statement_test.dart b/pkgs/code_builder/test/builders/statement_test.dart index 5833a7e5a..f76680892 100644 --- a/pkgs/code_builder/test/builders/statement_test.dart +++ b/pkgs/code_builder/test/builders/statement_test.dart @@ -85,5 +85,14 @@ void main() { '''), ); }); + + test('should emit a return statement', () { + expect( + returnVoid, + equalsSource(r''' + return; + '''), + ); + }); }); } From 721c909cc5ce9b6bd7b76957c8742ed1a8b2df6e Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 16 Nov 2016 17:39:20 -0800 Subject: [PATCH 017/271] Add additional features for NG2 output AST parity (dart-lang/code_builder#29) * Various changes. * Update presubmit. * Add more features required for ng2 parity. --- pkgs/code_builder/CHANGELOG.md | 40 ++++++ pkgs/code_builder/lib/code_builder.dart | 8 +- .../lib/src/builders/expression.dart | 44 +++++-- .../lib/src/builders/expression/assign.dart | 6 +- .../lib/src/builders/expression/negate.dart | 4 +- .../src/builders/expression/operators.dart | 3 +- pkgs/code_builder/lib/src/builders/file.dart | 14 +-- .../code_builder/lib/src/builders/method.dart | 118 +++++++++++++----- .../lib/src/builders/reference.dart | 41 +++++- .../lib/src/builders/statement/if.dart | 3 +- pkgs/code_builder/lib/src/builders/type.dart | 31 ++++- pkgs/code_builder/lib/src/tokens.dart | 6 + pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/expression_test.dart | 12 +- .../test/builders/method_test.dart | 15 +++ .../code_builder/test/builders/type_test.dart | 23 ++++ 16 files changed, 307 insertions(+), 63 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 8d18774ef..a9b2311c3 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,45 @@ # Changelog +## 1.0.0-alpha+3 + +- BREAKING CHANGE: Added generics support to `TypeBuilder`: + +`importFrom` becomes a _named_, not positional argument, and the named +argument `genericTypes` is added (`Iterable`). + +```dart +// List +new TypeBuilder('List', genericTypes: [reference('String')]) +``` + +- Added generic support to `ReferenceBuilder`: + +```dart +// List +reference('List').toTyped([reference('String')]) +``` + +- Fixed a bug where `ReferenceBuilder.buildAst` was not implemented +- Added `and` and `or` methods to `ExpressionBuilder`: + +```dart +// true || false +literal(true).or(literal(false)); + +// true && false +literal(true).and(literal(false)); +``` + +- Added support for creating closures - `MethodBuilder.closure`: + +```dart +// () => true +new MethodBuilder.closure( + returns: literal(true), + returnType: lib$core.bool, +) +``` + ## 1.0.0-alpha+2 - Added `returnVoid` to well, `return;` diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 62644494c..283898c7f 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -30,5 +30,11 @@ 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, returnVoid, IfStatementBuilder, StatementBuilder; + show + ifThen, + elseIf, + elseThen, + returnVoid, + IfStatementBuilder, + StatementBuilder; export 'src/builders/type.dart' show NewInstanceBuilder, TypeBuilder; diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index 55d979144..f5fda5f08 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -81,7 +81,7 @@ Literal _literal(value) { } /// Implements much of [ExpressionBuilder]. -abstract class AbstractExpressionMixin extends TopLevelMixin implements ExpressionBuilder { +abstract class AbstractExpressionMixin implements ExpressionBuilder { @override ExpressionBuilder operator *(ExpressionBuilder other) { return new _AsBinaryExpression( @@ -118,6 +118,15 @@ abstract class AbstractExpressionMixin extends TopLevelMixin implements Expressi ); } + @override + ExpressionBuilder and(ExpressionBuilder other) { + return new _AsBinaryExpression( + this, + other, + $and, + ); + } + @override StatementBuilder asAssert() => new _AsAssert(this); @@ -221,6 +230,15 @@ abstract class AbstractExpressionMixin extends TopLevelMixin implements Expressi ); } + @override + ExpressionBuilder or(ExpressionBuilder other) { + return new _AsBinaryExpression( + this, + other, + $or, + ); + } + @override ExpressionBuilder parentheses() => new _ParenthesesExpression(this); @@ -243,13 +261,17 @@ abstract class ExpressionBuilder /// Returns as an [ExpressionBuilder] dividing by [other]. ExpressionBuilder operator /(ExpressionBuilder other); + /// Returns as an [ExpressionBuilder] `&&` [other]. + ExpressionBuilder and(ExpressionBuilder other); + /// Return as a [StatementBuilder] that `assert`s this expression. StatementBuilder asAssert(); /// Returns as a [StatementBuilder] that assigns to an existing [variable]. /// /// If [target] is specified, determined to be `{target}.{variable}`. - StatementBuilder asAssign(String variable, {ExpressionBuilder target, bool nullAware}); + StatementBuilder asAssign(String variable, + {ExpressionBuilder target, bool nullAware}); /// Returns as a [StatementBuilder] that assigns to a new `const` [variable]. StatementBuilder asConst(String variable, [TypeBuilder type]); @@ -311,6 +333,9 @@ abstract class ExpressionBuilder /// Returns as an [ExpressionBuilder] comparing using `!=` against [other]. ExpressionBuilder notEquals(ExpressionBuilder other); + /// Returns as an [ExpressionBuilder] `||` [other]. + ExpressionBuilder or(ExpressionBuilder other); + /// Returns as an [ExpressionBuilder] wrapped in parentheses. ExpressionBuilder parentheses(); @@ -363,7 +388,8 @@ class _AsStatement extends TopLevelMixin implements StatementBuilder { } } -class _MemberExpression extends Object with AbstractExpressionMixin, TopLevelMixin { +class _MemberExpression extends Object + with AbstractExpressionMixin, TopLevelMixin { final String _name; final ExpressionBuilder _target; @@ -382,7 +408,8 @@ class _MemberExpression extends Object with AbstractExpressionMixin, TopLevelMix } } -class _LiteralExpression extends Object with AbstractExpressionMixin, TopLevelMixin { +class _LiteralExpression extends Object + with AbstractExpressionMixin, TopLevelMixin { final Literal _literal; _LiteralExpression(this._literal); @@ -394,7 +421,8 @@ class _LiteralExpression extends Object with AbstractExpressionMixin, TopLevelMi Expression buildExpression([_]) => _literal; } -class _ParenthesesExpression extends Object with AbstractExpressionMixin, TopLevelMixin { +class _ParenthesesExpression extends Object + with AbstractExpressionMixin, TopLevelMixin { final ExpressionBuilder _expression; _ParenthesesExpression(this._expression); @@ -422,7 +450,8 @@ ExpressionBuilder _expressionify(v) { throw new ArgumentError('Could not expressionify $v'); } -class _TypedListExpression extends Object with AbstractExpressionMixin, TopLevelMixin { +class _TypedListExpression extends Object + with AbstractExpressionMixin, TopLevelMixin { static List _toExpression(Iterable values) { return values.map(_expressionify).toList(); } @@ -457,7 +486,8 @@ class _TypedListExpression extends Object with AbstractExpressionMixin, TopLevel } } -class _TypedMapExpression extends Object with AbstractExpressionMixin, TopLevelMixin { +class _TypedMapExpression extends Object + with AbstractExpressionMixin, TopLevelMixin { static Map _toExpression(Map values) { return new Map.fromIterable( values.keys, diff --git a/pkgs/code_builder/lib/src/builders/expression/assign.dart b/pkgs/code_builder/lib/src/builders/expression/assign.dart index f60768327..a1558b85b 100644 --- a/pkgs/code_builder/lib/src/builders/expression/assign.dart +++ b/pkgs/code_builder/lib/src/builders/expression/assign.dart @@ -4,7 +4,7 @@ part of code_builder.src.builders.expression; -class _AsAssign extends AbstractExpressionMixin { +class _AsAssign extends AbstractExpressionMixin with TopLevelMixin { final String _name; final bool _nullAware; final ExpressionBuilder _value; @@ -18,7 +18,9 @@ class _AsAssign extends AbstractExpressionMixin { @override Expression buildExpression([Scope scope]) { return new AssignmentExpression( - _target != null ? _target.property(_name).buildExpression(scope) : stringIdentifier(_name), + _target != null + ? _target.property(_name).buildExpression(scope) + : stringIdentifier(_name), _nullAware ? $nullAwareEquals : $equals, _value.buildExpression(scope), ); diff --git a/pkgs/code_builder/lib/src/builders/expression/negate.dart b/pkgs/code_builder/lib/src/builders/expression/negate.dart index e5fa83495..2e18f4833 100644 --- a/pkgs/code_builder/lib/src/builders/expression/negate.dart +++ b/pkgs/code_builder/lib/src/builders/expression/negate.dart @@ -4,7 +4,7 @@ part of code_builder.src.builders.expression; -class _NegateExpression extends AbstractExpressionMixin { +class _NegateExpression extends AbstractExpressionMixin with TopLevelMixin { final ExpressionBuilder _expression; _NegateExpression(this._expression); @@ -21,7 +21,7 @@ class _NegateExpression extends AbstractExpressionMixin { } } -class _NegativeExpression extends AbstractExpressionMixin { +class _NegativeExpression extends AbstractExpressionMixin with TopLevelMixin { final ExpressionBuilder _expression; _NegativeExpression(this._expression); diff --git a/pkgs/code_builder/lib/src/builders/expression/operators.dart b/pkgs/code_builder/lib/src/builders/expression/operators.dart index 9687056b2..0d4ee0f53 100644 --- a/pkgs/code_builder/lib/src/builders/expression/operators.dart +++ b/pkgs/code_builder/lib/src/builders/expression/operators.dart @@ -4,7 +4,8 @@ part of code_builder.src.builders.expression; -class _AsBinaryExpression extends Object with AbstractExpressionMixin, TopLevelMixin { +class _AsBinaryExpression extends Object + with AbstractExpressionMixin, TopLevelMixin { final ExpressionBuilder _left; final ExpressionBuilder _right; final Token _operator; diff --git a/pkgs/code_builder/lib/src/builders/file.dart b/pkgs/code_builder/lib/src/builders/file.dart index e6e8f186b..59042bd73 100644 --- a/pkgs/code_builder/lib/src/builders/file.dart +++ b/pkgs/code_builder/lib/src/builders/file.dart @@ -60,14 +60,12 @@ class LibraryBuilder extends FileBuilder { @override CompilationUnit buildAst([_]) { - var members = _members - .map((m) { - if (m is TopLevelMixin) { - return (m as TopLevelMixin).buildTopLevelAst(_scope); - } - return m.buildAst(_scope); - }) - .toList(); + var members = _members.map((m) { + if (m is TopLevelMixin) { + return (m as TopLevelMixin).buildTopLevelAst(_scope); + } + return m.buildAst(_scope); + }).toList(); var directives = [] ..addAll(_scope.toImports().map((d) => d.buildAst())) ..addAll(_directives.map((d) => d.buildAst())); diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index 2228d2f7d..af0f4a5e4 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -9,6 +9,7 @@ import 'package:code_builder/code_builder.dart'; import 'package:code_builder/dart/core.dart'; import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/class.dart'; +import 'package:code_builder/src/builders/expression.dart'; import 'package:code_builder/src/builders/parameter.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement.dart'; @@ -165,10 +166,18 @@ abstract class ConstructorBuilder /// Lazily builds a method/function AST when the builder is invoked. abstract class MethodBuilder - implements HasAnnotations, HasParameters, HasStatements, ValidClassMember { + implements + ExpressionBuilder, + HasAnnotations, + HasParameters, + HasStatements, + ValidClassMember { /// Creates a new [MethodBuilder]. - factory MethodBuilder(String name, - {ExpressionBuilder returns, TypeBuilder returnType}) { + factory MethodBuilder( + String name, { + ExpressionBuilder returns, + TypeBuilder returnType, + }) { if (returns != null) { return new _LambdaMethodBuilder( name, @@ -184,6 +193,26 @@ abstract class MethodBuilder } } + /// Creates a new [MethodBuilder] that returns an anonymous closure. + factory MethodBuilder.closure({ + ExpressionBuilder returns, + TypeBuilder returnType, + }) { + if (returns != null) { + return new _LambdaMethodBuilder( + null, + returns, + returnType, + null, + ); + } else { + return new _MethodBuilderImpl( + null, + returns: returnType, + ); + } + } + /// Creates a getter. factory MethodBuilder.getter( String name, { @@ -263,7 +292,11 @@ class _FieldParameterWrapper } class _LambdaMethodBuilder extends Object - with HasAnnotationsMixin, HasParametersMixin + with + AbstractExpressionMixin, + HasAnnotationsMixin, + HasParametersMixin, + TopLevelMixin implements MethodBuilder { final ExpressionBuilder _expression; final String _name; @@ -284,7 +317,26 @@ class _LambdaMethodBuilder extends Object } @override - AstNode buildAst([Scope scope]) => buildFunction(scope); + AstNode buildAst([Scope scope]) { + if (_name != null) { + return buildFunction(scope); + } + return buildExpression(scope); + } + + @override + Expression buildExpression([Scope scope]) { + return new FunctionExpression( + null, + _property != Keyword.GET ? buildParameterList(scope) : null, + new ExpressionFunctionBody( + null, + null, + _expression.buildExpression(scope), + $semicolon, + ), + ); + } @override FunctionDeclaration buildFunction([Scope scope]) { @@ -294,17 +346,8 @@ class _LambdaMethodBuilder extends Object null, _returnType?.buildType(scope), _property != null ? new KeywordToken(_property, 0) : null, - identifier(scope, _name), - new FunctionExpression( - null, - _property != Keyword.GET ? buildParameterList(scope) : null, - new ExpressionFunctionBody( - null, - null, - _expression.buildExpression(scope), - $semicolon, - ), - ), + stringIdentifier(_name), + buildExpression(scope), ); } @@ -332,7 +375,12 @@ class _LambdaMethodBuilder extends Object } class _MethodBuilderImpl extends Object - with HasAnnotationsMixin, HasParametersMixin, HasStatementsMixin + with + AbstractExpressionMixin, + HasAnnotationsMixin, + HasParametersMixin, + HasStatementsMixin, + TopLevelMixin implements MethodBuilder { final String _name; final TypeBuilder _returnType; @@ -347,7 +395,27 @@ class _MethodBuilderImpl extends Object _property = property; @override - AstNode buildAst([Scope scope]) => buildFunction(scope); + AstNode buildAst([Scope scope]) { + if (_name != null) { + return buildFunction(scope); + } + return buildExpression(scope); + } + + @override + Expression buildExpression([Scope scope]) { + return new FunctionExpression( + null, + _property != Keyword.GET ? buildParameterList(scope) : null, + !hasStatements + ? new EmptyFunctionBody($semicolon) + : new BlockFunctionBody( + null, + null, + buildBlock(scope), + ), + ); + } @override FunctionDeclaration buildFunction([Scope scope]) { @@ -357,18 +425,8 @@ class _MethodBuilderImpl extends Object null, _returnType?.buildType(scope), _property != null ? new KeywordToken(_property, 0) : null, - identifier(scope, _name), - new FunctionExpression( - null, - _property != Keyword.GET ? buildParameterList(scope) : null, - !hasStatements - ? new EmptyFunctionBody($semicolon) - : new BlockFunctionBody( - null, - null, - buildBlock(scope), - ), - ), + stringIdentifier(_name), + buildExpression(scope), ); } diff --git a/pkgs/code_builder/lib/src/builders/reference.dart b/pkgs/code_builder/lib/src/builders/reference.dart index 87c6271fc..292ae4fbd 100644 --- a/pkgs/code_builder/lib/src/builders/reference.dart +++ b/pkgs/code_builder/lib/src/builders/reference.dart @@ -14,6 +14,13 @@ import 'package:code_builder/src/tokens.dart'; final ReferenceBuilder explicitThis = reference('this'); /// Creates a reference called [name]. +/// +/// **NOTE**: To refer to a _generic_ type, use [TypeBuilder] instead: +/// // Refer to `List` +/// new TypeBuilder( +/// 'List', +/// genericTypes: [reference('String')], +/// ) ReferenceBuilder reference(String name, [String importUri]) { return new ReferenceBuilder._(name, importUri); } @@ -39,7 +46,7 @@ class ReferenceBuilder extends Object } @override - AstNode buildAst([Scope scope]) => throw new UnimplementedError(); + AstNode buildAst([Scope scope]) => buildType(scope); @override Expression buildExpression([Scope scope]) { @@ -52,6 +59,36 @@ class ReferenceBuilder extends Object @override TypeName buildType([Scope scope]) { - return new TypeBuilder(_name, _importFrom).buildType(scope); + return new TypeBuilder(_name, importFrom: _importFrom).buildType(scope); + } + + /// Returns a new [ReferenceBuilder] with [genericTypes]. + /// + /// Example use: + /// // List + /// reference('List').toTyped([reference('String')]) + ReferenceBuilder toTyped(Iterable genericTypes) { + return new _TypedReferenceBuilder(genericTypes, _name, _importFrom); + } +} + +class _TypedReferenceBuilder extends ReferenceBuilder { + final List _genericTypes; + + _TypedReferenceBuilder( + this._genericTypes, + String name, + String importFrom, + ) + : super._(name, importFrom); + + @override + TypeName buildType([Scope scope]) { + return new TypeBuilder( + _name, + importFrom: _importFrom, + genericTypes: _genericTypes, + ) + .buildType(scope); } } diff --git a/pkgs/code_builder/lib/src/builders/statement/if.dart b/pkgs/code_builder/lib/src/builders/statement/if.dart index b778010d2..31fd59bd4 100644 --- a/pkgs/code_builder/lib/src/builders/statement/if.dart +++ b/pkgs/code_builder/lib/src/builders/statement/if.dart @@ -59,7 +59,8 @@ abstract class IfStatementBuilder implements HasStatements, StatementBuilder { /// Marker interface for builders valid for use with [ifThen]. abstract class ValidIfStatementMember implements AstBuilder {} -class _BlockIfStatementBuilder extends Object with HasStatementsMixin, TopLevelMixin +class _BlockIfStatementBuilder extends Object + with HasStatementsMixin, TopLevelMixin implements IfStatementBuilder { final ExpressionBuilder _condition; StatementBuilder _elseBlock; diff --git a/pkgs/code_builder/lib/src/builders/type.dart b/pkgs/code_builder/lib/src/builders/type.dart index 8c96fe5df..540d66252 100644 --- a/pkgs/code_builder/lib/src/builders/type.dart +++ b/pkgs/code_builder/lib/src/builders/type.dart @@ -75,13 +75,32 @@ abstract class AbstractTypeBuilderMixin { class TypeBuilder extends Object with AbstractTypeBuilderMixin implements AstBuilder, ValidMethodMember, ValidParameterMember { + final List _generics; final String _importFrom; final String _name; /// Creates a new [TypeBuilder]. - factory TypeBuilder(String name, [String importFrom]) = TypeBuilder._; + /// + /// Can be made generic by passing one or more [genericTypes]. + /// + /// Optionally specify the source to [importFrom] to resolve this type. + factory TypeBuilder( + String name, { + Iterable genericTypes: const [], + String importFrom, + }) { + return new TypeBuilder._( + name, + importFrom, + genericTypes.toList(growable: false), + ); + } - TypeBuilder._(this._name, [this._importFrom]); + TypeBuilder._( + this._name, + this._importFrom, + this._generics, + ); @override AstNode buildAst([Scope scope]) => buildType(scope); @@ -94,7 +113,13 @@ class TypeBuilder extends Object _name, _importFrom, ), - null, + _generics.isEmpty + ? null + : new TypeArgumentList( + $openBracket, + _generics.map((t) => t.buildType(scope)).toList(), + $closeBracket, + ), ); } } diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index 9b97264e2..883e2c26c 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -67,6 +67,9 @@ final Token $if = new KeywordToken(Keyword.IF, 0); // Simple tokens +/// The `&&` token. +final Token $and = new Token(TokenType.AMPERSAND_AMPERSAND, 0); + /// The `hide` token. final Token $hide = new StringToken(TokenType.KEYWORD, 'hide', 0); @@ -103,6 +106,9 @@ final Token $nullAwareEquals = new Token(TokenType.QUESTION_QUESTION_EQ, 0); /// The `of` token. final Token $of = new StringToken(TokenType.KEYWORD, 'of', 0); +/// The `||` token. +final Token $or = new Token(TokenType.BAR_BAR, 0); + /// The '[` token. final Token $openBracket = new Token(TokenType.OPEN_SQUARE_BRACKET, 0); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 05c0aedcb..ec45b09c4 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-alpha+2 +version: 1.0.0-alpha+3 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 123186aea..2fa687bb9 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -279,11 +279,13 @@ void main() { test('should emit cascaded expressions', () { expect( - reference('foo').cascade((c) => [ - c.invoke('doThis', []), - c.invoke('doThat', []), - reference('Bar').newInstance([]).asAssign('bar', target: c), - ]).asStatement(), + reference('foo') + .cascade((c) => [ + c.invoke('doThis', []), + c.invoke('doThat', []), + reference('Bar').newInstance([]).asAssign('bar', target: c), + ]) + .asStatement(), equalsSource(r''' foo ..doThis() diff --git a/pkgs/code_builder/test/builders/method_test.dart b/pkgs/code_builder/test/builders/method_test.dart index e532e622f..a25baa3f5 100644 --- a/pkgs/code_builder/test/builders/method_test.dart +++ b/pkgs/code_builder/test/builders/method_test.dart @@ -169,4 +169,19 @@ void main() { '''), ); }); + + test('should emit a closure', () { + final closure = new MethodBuilder.closure( + returns: literal(false).or(reference('defaultTo')), + returnType: lib$core.bool, + )..addPositional(parameter('defaultTo', [lib$core.bool])); + // Should be usable as an expression/parameter itself. + expect(closure, const isInstanceOf()); + expect( + closure, + equalsSource(r''' + (bool defaultTo) => false || defaultTo; + '''), + ); + }); } diff --git a/pkgs/code_builder/test/builders/type_test.dart b/pkgs/code_builder/test/builders/type_test.dart index 323f9722c..bd82af37b 100644 --- a/pkgs/code_builder/test/builders/type_test.dart +++ b/pkgs/code_builder/test/builders/type_test.dart @@ -8,6 +8,29 @@ import 'package:code_builder/testing.dart'; import 'package:test/test.dart'; void main() { + test('TypeBuilder emits a generic type reference', () { + expect( + new TypeBuilder('List', genericTypes: [reference('String')]), + equalsSource(r''' + List + '''), + ); + }); + + test('ReferenceBuilder.toTyped emits a generic type reference', () { + expect( + lib$core.Map.toTyped([ + lib$core.String, + lib$core.List.toTyped([ + lib$core.int, + ]), + ]), + equalsSource(r''' + Map> + '''), + ); + }); + group('new instance', () { test('emits a new List', () { expect( From 291cdc001ea0c2575644d3bea0ba5803d130c799 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sat, 19 Nov 2016 12:13:01 -0800 Subject: [PATCH 018/271] Support latest analyzer (dart-lang/code_builder#30) --- pkgs/code_builder/CHANGELOG.md | 4 +++- pkgs/code_builder/pubspec.yaml | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index a9b2311c3..5246af5e6 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,6 @@ -# Changelog +## 1.0.0-alpha+4 + +- Add support for latest `pkg/analyzer`. ## 1.0.0-alpha+3 diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index ec45b09c4..ea79d3e24 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-alpha+3 +version: 1.0.0-alpha+4 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -8,7 +8,7 @@ environment: sdk: '>=1.9.1 <2.0.0' dependencies: - analyzer: '>=0.28.1 <0.29.0' + analyzer: '>=0.28.1 <0.30.0' dart_style: ^0.2.10 matcher: ^0.12.0+2 meta: ^1.0.2 From c11da41fa00b4dce00598161131411ab4e350621 Mon Sep 17 00:00:00 2001 From: Andrew Lorenzen Date: Mon, 21 Nov 2016 14:23:41 -0800 Subject: [PATCH 019/271] Remove semicolons from where they don't belong. (dart-lang/code_builder#33) * Remove semicolons from where they don't belong. * Update changelog * Cleanup Changelog --- pkgs/code_builder/CHANGELOG.md | 18 ++++++ .../code_builder/lib/src/builders/method.dart | 27 +++++---- pkgs/code_builder/pubspec.yaml | 2 +- .../code_builder/test/builders/file_test.dart | 9 +++ .../test/builders/method_test.dart | 56 +++++++++++++------ 5 files changed, 81 insertions(+), 31 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 5246af5e6..e8e881d40 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,21 @@ +## 1.0.0-alpha+5 + +- MethodBuilder with no statements will create an empty block instead of a +semicolon. + +```dart +// main() {} +method('main') +``` + +- Fix lambdas and closures to not include a trailing semicolon when used as an +expression. + +```dart + // () => false + new MethodBuilder.closure(returns: literal(false)); +``` + ## 1.0.0-alpha+4 - Add support for latest `pkg/analyzer`. diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index af0f4a5e4..f7bc7de44 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -326,6 +326,10 @@ class _LambdaMethodBuilder extends Object @override Expression buildExpression([Scope scope]) { + return _buildExpression(scope, isStatement: false); + } + + FunctionExpression _buildExpression(Scope scope, {bool isStatement}) { return new FunctionExpression( null, _property != Keyword.GET ? buildParameterList(scope) : null, @@ -333,7 +337,7 @@ class _LambdaMethodBuilder extends Object null, null, _expression.buildExpression(scope), - $semicolon, + isStatement ? $semicolon : null, ), ); } @@ -347,7 +351,7 @@ class _LambdaMethodBuilder extends Object _returnType?.buildType(scope), _property != null ? new KeywordToken(_property, 0) : null, stringIdentifier(_name), - buildExpression(scope), + _buildExpression(scope, isStatement: true), ); } @@ -407,9 +411,7 @@ class _MethodBuilderImpl extends Object return new FunctionExpression( null, _property != Keyword.GET ? buildParameterList(scope) : null, - !hasStatements - ? new EmptyFunctionBody($semicolon) - : new BlockFunctionBody( + new BlockFunctionBody( null, null, buildBlock(scope), @@ -443,15 +445,16 @@ class _MethodBuilderImpl extends Object identifier(scope, _name), null, _property != Keyword.GET ? buildParameterList(scope) : null, - !hasStatements - ? new EmptyFunctionBody($semicolon) - : new BlockFunctionBody( - null, - null, - buildBlock(scope), - ), + new BlockFunctionBody( + null, + null, + buildBlock(scope), + ), ); } + + @override + CompilationUnitMember buildTopLevelAst([Scope scope]) => buildFunction(scope); } class _NamedParameterWrapper diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index ea79d3e24..1341716a2 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-alpha+4 +version: 1.0.0-alpha+5 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/file_test.dart b/pkgs/code_builder/test/builders/file_test.dart index f9f258c2a..be486fe89 100644 --- a/pkgs/code_builder/test/builders/file_test.dart +++ b/pkgs/code_builder/test/builders/file_test.dart @@ -58,5 +58,14 @@ void main() { '''), ); }); + + group('$LibraryBuilder', () { + test('should handle empty methods', () { + expect( + new LibraryBuilder() + ..addMember(new MethodBuilder.returnVoid('main')), + equalsSource('void main() {}')); + }); + }); }); } diff --git a/pkgs/code_builder/test/builders/method_test.dart b/pkgs/code_builder/test/builders/method_test.dart index a25baa3f5..332cdf913 100644 --- a/pkgs/code_builder/test/builders/method_test.dart +++ b/pkgs/code_builder/test/builders/method_test.dart @@ -12,7 +12,7 @@ void main() { expect( method('main'), equalsSource(r''' - main(); + main() {} '''), ); }); @@ -23,7 +23,7 @@ void main() { lib$core.$void, ]).buildMethod(false).toSource(), equalsIgnoringWhitespace(r''' - void main(); + void main() {} '''), ); }); @@ -34,7 +34,7 @@ void main() { parameter('args', [lib$core.List]), ]).buildMethod(false).toSource(), equalsIgnoringWhitespace(r''' - main(List args); + main(List args) {} '''), ); }); @@ -47,7 +47,7 @@ void main() { parameter('c').asOptional(), ]), equalsSource(r''' - main(a, b, [c]); + main(a, b, [c]) {} '''), ); }); @@ -60,7 +60,7 @@ void main() { parameter('c').asOptional(literal(true)), ]), equalsSource(r''' - main(a, b, [c = true]); + main(a, b, [c = true]) {} '''), ); }); @@ -72,7 +72,7 @@ void main() { named(parameter('b').asOptional(literal(true))), ]).buildMethod(false).toSource(), equalsIgnoringWhitespace(r''' - main({a, b : true}); + main({a, b : true}) {} '''), ); }); @@ -170,18 +170,38 @@ void main() { ); }); - test('should emit a closure', () { - final closure = new MethodBuilder.closure( - returns: literal(false).or(reference('defaultTo')), - returnType: lib$core.bool, - )..addPositional(parameter('defaultTo', [lib$core.bool])); - // Should be usable as an expression/parameter itself. - expect(closure, const isInstanceOf()); - expect( - closure, - equalsSource(r''' - (bool defaultTo) => false || defaultTo; + group('closure', () { + MethodBuilder closure; + setUp(() { + closure = new MethodBuilder.closure( + returns: literal(false).or(reference('defaultTo')), + returnType: lib$core.bool, + )..addPositional(parameter('defaultTo', [lib$core.bool])); + }); + + test('should emit a closure', () { + // Should be usable as an expression/parameter itself. + expect(closure, const isInstanceOf()); + expect( + closure, + equalsSource(r''' + (bool defaultTo) => false || defaultTo '''), - ); + ); + + test('should treat closure as expression', () { + expect( + list([true, false]).invoke('where', [closure]), + equalsSource( + '[true, false].where((bool defaultTo) => false || defaultTo)')); + }); + + test('should emit a closure as a function in a library', () { + final library = new LibraryBuilder(); + library.addMember(closure); + expect( + library, equalsSource('(bool defaultTo) => false || defaultTo;')); + }); + }); }); } From 2d461e3a465316bfec01aef7f31778a30f4ad283 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 21 Nov 2016 22:40:53 -0800 Subject: [PATCH 020/271] Fix the travis build by running dartfmt (dart-lang/code_builder#34) * Various changes. * Update presubmit. * Dartfmt to fix travis build. * And bug fix. --- pkgs/code_builder/CHANGELOG.md | 12 ++++++++---- pkgs/code_builder/lib/src/builders/method.dart | 11 +++++++---- pkgs/code_builder/pubspec.yaml | 2 +- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index e8e881d40..72803f7a6 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,15 +1,19 @@ +## 1.0.0-alpha+6 + +- `MethodBuilder.closure` emits properly as a top-level function + ## 1.0.0-alpha+5 -- MethodBuilder with no statements will create an empty block instead of a -semicolon. +- MethodBuilder with no statements will create an empty block instead of + a semicolon. ```dart // main() {} method('main') ``` -- Fix lambdas and closures to not include a trailing semicolon when used as an -expression. +- Fix lambdas and closures to not include a trailing semicolon when used + as an expression. ```dart // () => false diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index f7bc7de44..e4660ee53 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -376,6 +376,9 @@ class _LambdaMethodBuilder extends Object ), ); } + + @override + CompilationUnitMember buildTopLevelAst([Scope scope]) => buildFunction(scope); } class _MethodBuilderImpl extends Object @@ -412,10 +415,10 @@ class _MethodBuilderImpl extends Object null, _property != Keyword.GET ? buildParameterList(scope) : null, new BlockFunctionBody( - null, - null, - buildBlock(scope), - ), + null, + null, + buildBlock(scope), + ), ); } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 1341716a2..e06ebe341 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-alpha+5 +version: 1.0.0-alpha+6 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From 7cacbc5fcf20e4f26d40f326f6e09d9d1e96700a Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Tue, 29 Nov 2016 14:23:45 -0800 Subject: [PATCH 021/271] Begin taking advantage of analyzer's new AstFactory class. (dart-lang/code_builder#36) * Begin taking advantage of analyzer's new AstFactory class. The old mechanism for creating analyzer ASTs (factory constructors on the interface classes) will be going away in analyzer 0.30. * dartfmt * Fix arguments to astFactory.partOfDirective --- pkgs/code_builder/lib/src/builders/class.dart | 9 ++--- .../lib/src/builders/expression.dart | 31 +++++++++-------- .../lib/src/builders/expression/assert.dart | 2 +- .../lib/src/builders/expression/assign.dart | 14 ++++---- .../lib/src/builders/expression/cascade.dart | 2 +- .../src/builders/expression/invocation.dart | 10 +++--- .../lib/src/builders/expression/negate.dart | 4 +-- .../src/builders/expression/operators.dart | 2 +- .../lib/src/builders/expression/return.dart | 2 +- pkgs/code_builder/lib/src/builders/field.dart | 11 +++--- pkgs/code_builder/lib/src/builders/file.dart | 34 ++++++++++--------- .../code_builder/lib/src/builders/method.dart | 27 ++++++++------- .../lib/src/builders/parameter.dart | 11 +++--- .../lib/src/builders/reference.dart | 3 +- .../code_builder/lib/src/builders/shared.dart | 3 +- .../lib/src/builders/statement.dart | 5 +-- .../lib/src/builders/statement/block.dart | 3 +- .../lib/src/builders/statement/if.dart | 3 +- pkgs/code_builder/lib/src/builders/type.dart | 5 +-- .../lib/src/builders/type/new_instance.dart | 6 ++-- pkgs/code_builder/lib/src/scope.dart | 5 +-- pkgs/code_builder/pubspec.yaml | 2 +- 22 files changed, 105 insertions(+), 89 deletions(-) diff --git a/pkgs/code_builder/lib/src/builders/class.dart b/pkgs/code_builder/lib/src/builders/class.dart index 333d3e4a3..88830e8e4 100644 --- a/pkgs/code_builder/lib/src/builders/class.dart +++ b/pkgs/code_builder/lib/src/builders/class.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/dart/core.dart'; import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/field.dart'; @@ -200,7 +201,7 @@ class _ClassBuilderImpl extends Object if (extend == null && _with.isNotEmpty) { extend = lib$core.Object; } - final clazz = new ClassDeclaration( + final clazz = astFactory.classDeclaration( null, buildAnnotations(scope), _asAbstract ? $abstract : null, @@ -208,19 +209,19 @@ class _ClassBuilderImpl extends Object stringIdentifier(_name), null, extend != null - ? new ExtendsClause( + ? astFactory.extendsClause( $extends, extend.buildType(scope), ) : null, _with.isNotEmpty - ? new WithClause( + ? astFactory.withClause( $with, _with.map/**/((w) => w.buildType(scope)).toList(), ) : null, _implements.isNotEmpty - ? new ImplementsClause( + ? astFactory.implementsClause( $implements, _implements.map/**/((i) => i.buildType(scope)).toList(), ) diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index f5fda5f08..56a04a304 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -5,6 +5,7 @@ library code_builder.src.builders.expression; import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:analyzer/src/dart/ast/token.dart'; import 'package:code_builder/dart/core.dart'; import 'package:code_builder/src/builders/method.dart'; @@ -24,11 +25,13 @@ part 'expression/negate.dart'; part 'expression/operators.dart'; part 'expression/return.dart'; -final _false = new BooleanLiteral(new KeywordToken(Keyword.FALSE, 0), true); +final _false = + astFactory.booleanLiteral(new KeywordToken(Keyword.FALSE, 0), true); -final _null = new NullLiteral(new KeywordToken(Keyword.NULL, 0)); +final _null = astFactory.nullLiteral(new KeywordToken(Keyword.NULL, 0)); -final _true = new BooleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); +final _true = + astFactory.booleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); /// Returns a pre-defined literal expression of [value]. /// @@ -71,11 +74,11 @@ Literal _literal(value) { } else if (value is bool) { return value ? _true : _false; } else if (value is String) { - return new SimpleStringLiteral(stringToken("'$value'"), value); + return astFactory.simpleStringLiteral(stringToken("'$value'"), value); } else if (value is int) { - return new IntegerLiteral(stringToken('$value'), value); + return astFactory.integerLiteral(stringToken('$value'), value); } else if (value is double) { - return new DoubleLiteral(stringToken('$value'), value); + return astFactory.doubleLiteral(stringToken('$value'), value); } throw new ArgumentError.value(value, 'Unsupported'); } @@ -381,7 +384,7 @@ class _AsStatement extends TopLevelMixin implements StatementBuilder { @override Statement buildStatement([Scope scope]) { - return new ExpressionStatement( + return astFactory.expressionStatement( _expression.buildExpression(scope), $semicolon, ); @@ -400,7 +403,7 @@ class _MemberExpression extends Object @override Expression buildExpression([Scope scope]) { - return new PropertyAccess( + return astFactory.propertyAccess( _target.buildExpression(scope), $period, stringIdentifier(_name), @@ -432,7 +435,7 @@ class _ParenthesesExpression extends Object @override Expression buildExpression([Scope scope]) { - return new ParenthesizedExpression( + return astFactory.parenthesizedExpression( $openParen, _expression.buildExpression(scope), $closeParen, @@ -470,10 +473,10 @@ class _TypedListExpression extends Object @override Expression buildExpression([Scope scope]) { - return new ListLiteral( + return astFactory.listLiteral( _asConst ? $const : null, _type != null - ? new TypeArgumentList( + ? astFactory.typeArgumentList( $openBracket, [_type.buildType(scope)], $closeBracket, @@ -517,10 +520,10 @@ class _TypedMapExpression extends Object @override Expression buildExpression([Scope scope]) { - return new MapLiteral( + return astFactory.mapLiteral( _asConst ? $const : null, _keyType != null - ? new TypeArgumentList( + ? astFactory.typeArgumentList( $openBracket, [ _keyType.buildType(scope), @@ -531,7 +534,7 @@ class _TypedMapExpression extends Object : null, $openBracket, _values.keys.map((k) { - return new MapLiteralEntry( + return astFactory.mapLiteralEntry( k.buildExpression(scope), $colon, _values[k].buildExpression(scope), diff --git a/pkgs/code_builder/lib/src/builders/expression/assert.dart b/pkgs/code_builder/lib/src/builders/expression/assert.dart index f3ed0c2e8..0428b6f85 100644 --- a/pkgs/code_builder/lib/src/builders/expression/assert.dart +++ b/pkgs/code_builder/lib/src/builders/expression/assert.dart @@ -14,7 +14,7 @@ class _AsAssert extends TopLevelMixin implements StatementBuilder { @override Statement buildStatement([Scope scope]) { - return new AssertStatement( + return astFactory.assertStatement( $assert, $openParen, _expression.buildExpression(scope), diff --git a/pkgs/code_builder/lib/src/builders/expression/assign.dart b/pkgs/code_builder/lib/src/builders/expression/assign.dart index a1558b85b..2f9c72aa1 100644 --- a/pkgs/code_builder/lib/src/builders/expression/assign.dart +++ b/pkgs/code_builder/lib/src/builders/expression/assign.dart @@ -17,7 +17,7 @@ class _AsAssign extends AbstractExpressionMixin with TopLevelMixin { @override Expression buildExpression([Scope scope]) { - return new AssignmentExpression( + return astFactory.assignmentExpression( _target != null ? _target.property(_name).buildExpression(scope) : stringIdentifier(_name), @@ -40,14 +40,14 @@ class _AsAssignNew extends TopLevelMixin implements StatementBuilder { @override Statement buildStatement([Scope scope]) { - return new VariableDeclarationStatement( - new VariableDeclarationList( + return astFactory.variableDeclarationStatement( + astFactory.variableDeclarationList( null, null, _type == null || _modifier != $var ? _modifier : null, _type?.buildType(scope), [ - new VariableDeclaration( + astFactory.variableDeclaration( stringIdentifier(_name), $equals, _value.buildExpression(scope), @@ -60,16 +60,16 @@ class _AsAssignNew extends TopLevelMixin implements StatementBuilder { @override CompilationUnitMember buildTopLevelAst([Scope scope]) { - return new TopLevelVariableDeclaration( + return astFactory.topLevelVariableDeclaration( null, null, - new VariableDeclarationList( + astFactory.variableDeclarationList( null, null, _type == null || _modifier != $var ? _modifier : null, _type?.buildType(scope), [ - new VariableDeclaration( + astFactory.variableDeclaration( stringIdentifier(_name), $equals, _value.buildExpression(scope), diff --git a/pkgs/code_builder/lib/src/builders/expression/cascade.dart b/pkgs/code_builder/lib/src/builders/expression/cascade.dart index d90ff5641..d99e15f77 100644 --- a/pkgs/code_builder/lib/src/builders/expression/cascade.dart +++ b/pkgs/code_builder/lib/src/builders/expression/cascade.dart @@ -15,7 +15,7 @@ class _CascadeExpression extends TopLevelMixin with AbstractExpressionMixin { @override Expression buildExpression([Scope scope]) { - return new CascadeExpression( + return astFactory.cascadeExpression( _target.buildExpression(scope), _cascades.map((e) => e.buildExpression(scope)).toList(), ); diff --git a/pkgs/code_builder/lib/src/builders/expression/invocation.dart b/pkgs/code_builder/lib/src/builders/expression/invocation.dart index 80cd1bf71..684b21580 100644 --- a/pkgs/code_builder/lib/src/builders/expression/invocation.dart +++ b/pkgs/code_builder/lib/src/builders/expression/invocation.dart @@ -25,15 +25,15 @@ abstract class AbstractInvocationBuilderMixin implements InvocationBuilder { allArguments.addAll( _positional.map/**/((e) => e.buildExpression(scope))); _named.forEach((name, e) { - allArguments.add(new NamedExpression( - new Label( + allArguments.add(astFactory.namedExpression( + astFactory.label( stringIdentifier(name), $colon, ), e.buildExpression(scope), )); }); - return new ArgumentList( + return astFactory.argumentList( $openParen, allArguments, $closeParen, @@ -71,7 +71,7 @@ class _FunctionInvocationBuilder extends Object @override Expression buildExpression([Scope scope]) { - return new FunctionExpressionInvocation( + return astFactory.functionExpressionInvocation( _target.buildExpression(scope), null, buildArgumentList(scope), @@ -89,7 +89,7 @@ class _MethodInvocationBuilder extends Object @override Expression buildExpression([Scope scope]) { - return new MethodInvocation( + return astFactory.methodInvocation( _target.buildExpression(scope), $period, stringIdentifier(_method), diff --git a/pkgs/code_builder/lib/src/builders/expression/negate.dart b/pkgs/code_builder/lib/src/builders/expression/negate.dart index 2e18f4833..979d2c04f 100644 --- a/pkgs/code_builder/lib/src/builders/expression/negate.dart +++ b/pkgs/code_builder/lib/src/builders/expression/negate.dart @@ -14,7 +14,7 @@ class _NegateExpression extends AbstractExpressionMixin with TopLevelMixin { @override Expression buildExpression([Scope scope]) { - return new PrefixExpression( + return astFactory.prefixExpression( $not, _expression.parentheses().buildExpression(scope), ); @@ -31,7 +31,7 @@ class _NegativeExpression extends AbstractExpressionMixin with TopLevelMixin { @override Expression buildExpression([Scope scope]) { - return new PrefixExpression( + return astFactory.prefixExpression( $minus, _expression.parentheses().buildExpression(scope), ); diff --git a/pkgs/code_builder/lib/src/builders/expression/operators.dart b/pkgs/code_builder/lib/src/builders/expression/operators.dart index 0d4ee0f53..809f2d159 100644 --- a/pkgs/code_builder/lib/src/builders/expression/operators.dart +++ b/pkgs/code_builder/lib/src/builders/expression/operators.dart @@ -17,7 +17,7 @@ class _AsBinaryExpression extends Object @override Expression buildExpression([Scope scope]) { - return new BinaryExpression( + return astFactory.binaryExpression( _left.buildExpression(scope), _operator, _right.buildExpression(scope), diff --git a/pkgs/code_builder/lib/src/builders/expression/return.dart b/pkgs/code_builder/lib/src/builders/expression/return.dart index ade5cea31..41de4360c 100644 --- a/pkgs/code_builder/lib/src/builders/expression/return.dart +++ b/pkgs/code_builder/lib/src/builders/expression/return.dart @@ -14,7 +14,7 @@ class _AsReturn extends TopLevelMixin implements StatementBuilder { @override Statement buildStatement([Scope scope]) { - return new ReturnStatement( + return astFactory.returnStatement( $return, _value.buildExpression(), $semicolon, diff --git a/pkgs/code_builder/lib/src/builders/field.dart b/pkgs/code_builder/lib/src/builders/field.dart index da5f83572..5964e4a36 100644 --- a/pkgs/code_builder/lib/src/builders/field.dart +++ b/pkgs/code_builder/lib/src/builders/field.dart @@ -4,6 +4,7 @@ import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:analyzer/src/dart/ast/token.dart'; import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/class.dart'; @@ -129,7 +130,7 @@ class _FieldBuilderImpl extends TopLevelMixin @override FieldDeclaration buildField(bool static, [Scope scope]) { - return new FieldDeclaration( + return astFactory.fieldDeclaration( null, buildAnnotations(scope), static ? $static : null, @@ -140,7 +141,7 @@ class _FieldBuilderImpl extends TopLevelMixin @override Statement buildStatement([Scope scope]) { - return new VariableDeclarationStatement( + return astFactory.variableDeclarationStatement( _buildVariableList(scope), $semicolon, ); @@ -148,7 +149,7 @@ class _FieldBuilderImpl extends TopLevelMixin @override TopLevelVariableDeclaration buildTopLevel([Scope scope]) { - return new TopLevelVariableDeclaration( + return astFactory.topLevelVariableDeclaration( null, null, _buildVariableList(scope), @@ -157,13 +158,13 @@ class _FieldBuilderImpl extends TopLevelMixin } VariableDeclarationList _buildVariableList([Scope scope]) { - return new VariableDeclarationList( + return astFactory.variableDeclarationList( null, null, _keyword != null ? new KeywordToken(_keyword, 0) : null, _type?.buildType(scope), [ - new VariableDeclaration( + astFactory.variableDeclaration( stringIdentifier(_name), _value != null ? $equals : null, _value?.buildExpression(scope), diff --git a/pkgs/code_builder/lib/src/builders/file.dart b/pkgs/code_builder/lib/src/builders/file.dart index 59042bd73..cc93d547e 100644 --- a/pkgs/code_builder/lib/src/builders/file.dart +++ b/pkgs/code_builder/lib/src/builders/file.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/tokens.dart'; @@ -69,7 +70,7 @@ class LibraryBuilder extends FileBuilder { var directives = [] ..addAll(_scope.toImports().map((d) => d.buildAst())) ..addAll(_directives.map((d) => d.buildAst())); - return new CompilationUnit( + return astFactory.compilationUnit( null, null, directives, @@ -90,17 +91,18 @@ class PartBuilder extends FileBuilder { @override CompilationUnit buildAst([_]) { - return new CompilationUnit( + return astFactory.compilationUnit( null, null, [ - new PartOfDirective( + astFactory.partOfDirective( null, null, $part, $of, - new LibraryIdentifier([ - new SimpleIdentifier(stringToken(_name)), + null, + astFactory.libraryIdentifier([ + astFactory.simpleIdentifier(stringToken(_name)), ]), $semicolon, ) @@ -123,12 +125,12 @@ class _LibraryDirectiveBuilder implements AstBuilder { @override LibraryDirective buildAst([_]) { - return new LibraryDirective( + return astFactory.libraryDirective( null, null, $library, - new LibraryIdentifier([ - new SimpleIdentifier( + astFactory.libraryIdentifier([ + astFactory.simpleIdentifier( stringToken(_name), ), ]), @@ -173,7 +175,7 @@ class ImportBuilder implements AstBuilder { var combinators = []; if (_show.isNotEmpty) { combinators.add( - new ShowCombinator( + astFactory.showCombinator( $show, _show.map(stringIdentifier).toList(), ), @@ -181,17 +183,17 @@ class ImportBuilder implements AstBuilder { } if (_hide.isNotEmpty) { combinators.add( - new HideCombinator( + astFactory.hideCombinator( $hide, _hide.map(stringIdentifier).toList(), ), ); } - return new ImportDirective( + return astFactory.importDirective( null, null, null, - new SimpleStringLiteral(stringToken("'$_uri'"), _uri), + astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri), null, _deferred ? $deferred : null, _prefix != null ? $as : null, @@ -234,7 +236,7 @@ class ExportBuilder implements AstBuilder { var combinators = []; if (_show.isNotEmpty) { combinators.add( - new ShowCombinator( + astFactory.showCombinator( $show, _show.map(stringIdentifier).toList(), ), @@ -242,17 +244,17 @@ class ExportBuilder implements AstBuilder { } if (_hide.isNotEmpty) { combinators.add( - new HideCombinator( + astFactory.hideCombinator( $hide, _hide.map(stringIdentifier).toList(), ), ); } - return new ExportDirective( + return astFactory.exportDirective( null, null, null, - new SimpleStringLiteral(stringToken("'$_uri'"), _uri), + astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri), null, combinators, $semicolon, diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index e4660ee53..6ac013c86 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -4,6 +4,7 @@ import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:analyzer/src/dart/ast/token.dart'; import 'package:code_builder/code_builder.dart'; import 'package:code_builder/dart/core.dart'; @@ -330,10 +331,10 @@ class _LambdaMethodBuilder extends Object } FunctionExpression _buildExpression(Scope scope, {bool isStatement}) { - return new FunctionExpression( + return astFactory.functionExpression( null, _property != Keyword.GET ? buildParameterList(scope) : null, - new ExpressionFunctionBody( + astFactory.expressionFunctionBody( null, null, _expression.buildExpression(scope), @@ -344,7 +345,7 @@ class _LambdaMethodBuilder extends Object @override FunctionDeclaration buildFunction([Scope scope]) { - return new FunctionDeclaration( + return astFactory.functionDeclaration( null, buildAnnotations(scope), null, @@ -357,7 +358,7 @@ class _LambdaMethodBuilder extends Object @override MethodDeclaration buildMethod(bool static, [Scope scope]) { - return new MethodDeclaration( + return astFactory.methodDeclaration( null, buildAnnotations(scope), null, @@ -368,7 +369,7 @@ class _LambdaMethodBuilder extends Object stringIdentifier(_name), null, _property != Keyword.GET ? buildParameterList(scope) : null, - new ExpressionFunctionBody( + astFactory.expressionFunctionBody( null, null, _expression.buildExpression(scope), @@ -411,10 +412,10 @@ class _MethodBuilderImpl extends Object @override Expression buildExpression([Scope scope]) { - return new FunctionExpression( + return astFactory.functionExpression( null, _property != Keyword.GET ? buildParameterList(scope) : null, - new BlockFunctionBody( + astFactory.blockFunctionBody( null, null, buildBlock(scope), @@ -424,7 +425,7 @@ class _MethodBuilderImpl extends Object @override FunctionDeclaration buildFunction([Scope scope]) { - return new FunctionDeclaration( + return astFactory.functionDeclaration( null, buildAnnotations(scope), null, @@ -437,7 +438,7 @@ class _MethodBuilderImpl extends Object @override MethodDeclaration buildMethod(bool static, [Scope scope]) { - return new MethodDeclaration( + return astFactory.methodDeclaration( null, buildAnnotations(scope), null, @@ -448,7 +449,7 @@ class _MethodBuilderImpl extends Object identifier(scope, _name), null, _property != Keyword.GET ? buildParameterList(scope) : null, - new BlockFunctionBody( + astFactory.blockFunctionBody( null, null, buildBlock(scope), @@ -485,7 +486,7 @@ class _NormalConstructorBuilder extends Object @override ConstructorDeclaration buildConstructor(TypeBuilder returnType, [Scope scope]) { - return new ConstructorDeclaration( + return astFactory.constructorDeclaration( null, buildAnnotations(scope), null, @@ -499,8 +500,8 @@ class _NormalConstructorBuilder extends Object null, null, !hasStatements - ? new EmptyFunctionBody($semicolon) - : new BlockFunctionBody( + ? astFactory.emptyFunctionBody($semicolon) + : astFactory.blockFunctionBody( null, null, buildBlock(scope), diff --git a/pkgs/code_builder/lib/src/builders/parameter.dart b/pkgs/code_builder/lib/src/builders/parameter.dart index 58df28e33..5f2cc31a8 100644 --- a/pkgs/code_builder/lib/src/builders/parameter.dart +++ b/pkgs/code_builder/lib/src/builders/parameter.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/code_builder.dart'; import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/method.dart'; @@ -66,7 +67,7 @@ abstract class HasParametersMixin implements HasParameters { /// Builds a [FormalParameterList]. FormalParameterList buildParameterList([Scope scope]) { - return new FormalParameterList( + return astFactory.formalParameterList( $openParen, _parameters .map/**/((p) => p.buildParameter(scope)) @@ -122,7 +123,7 @@ class _OptionalParameterBuilder extends Object @override FormalParameter buildNamed(bool field, [Scope scope]) { - return new DefaultFormalParameter( + return astFactory.defaultFormalParameter( _parameter.buildPositional(field, scope), ParameterKind.NAMED, _expression != null ? $colon : null, @@ -132,7 +133,7 @@ class _OptionalParameterBuilder extends Object @override FormalParameter buildPositional(bool field, [Scope scope]) { - return new DefaultFormalParameter( + return astFactory.defaultFormalParameter( _parameter.buildPositional(field, scope), ParameterKind.POSITIONAL, _expression != null ? $equals : null, @@ -190,7 +191,7 @@ class _SimpleParameterBuilder extends Object @override FormalParameter buildPositional(bool field, [Scope scope]) { if (field) { - return new FieldFormalParameter( + return astFactory.fieldFormalParameter( null, buildAnnotations(scope), null, @@ -202,7 +203,7 @@ class _SimpleParameterBuilder extends Object null, ); } - return new SimpleFormalParameter( + return astFactory.simpleFormalParameter( null, buildAnnotations(scope), null, diff --git a/pkgs/code_builder/lib/src/builders/reference.dart b/pkgs/code_builder/lib/src/builders/reference.dart index 292ae4fbd..b48f725b9 100644 --- a/pkgs/code_builder/lib/src/builders/reference.dart +++ b/pkgs/code_builder/lib/src/builders/reference.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/expression.dart'; import 'package:code_builder/src/builders/shared.dart'; @@ -36,7 +37,7 @@ class ReferenceBuilder extends Object @override Annotation buildAnnotation([Scope scope]) { - return new Annotation( + return astFactory.annotation( $at, stringIdentifier(_name), null, diff --git a/pkgs/code_builder/lib/src/builders/shared.dart b/pkgs/code_builder/lib/src/builders/shared.dart index 3c1626405..772759fab 100644 --- a/pkgs/code_builder/lib/src/builders/shared.dart +++ b/pkgs/code_builder/lib/src/builders/shared.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/src/scope.dart'; import 'package:code_builder/src/tokens.dart'; @@ -10,7 +11,7 @@ export 'package:code_builder/src/scope.dart'; /// Returns a string [Literal] from [value]. Identifier stringIdentifier(String value) => - new SimpleIdentifier(stringToken(value)); + astFactory.simpleIdentifier(stringToken(value)); /// Lazily builds an analyzer [AstNode] when [buildAst] is invoked. /// diff --git a/pkgs/code_builder/lib/src/builders/statement.dart b/pkgs/code_builder/lib/src/builders/statement.dart index d19d7ae26..85d2befa2 100644 --- a/pkgs/code_builder/lib/src/builders/statement.dart +++ b/pkgs/code_builder/lib/src/builders/statement.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/src/builders/method.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement/if.dart'; @@ -36,7 +37,7 @@ abstract class HasStatementsMixin implements HasStatements { /// Returns a [Block] statement. Block buildBlock([Scope scope]) { - return new Block( + return astFactory.block( $openCurly, buildStatements(scope), $closeCurly, @@ -92,7 +93,7 @@ class _ReturnStatementBuilder extends Object implements StatementBuilder { @override Statement buildStatement([_]) { - return new ReturnStatement($return, null, $semicolon); + return astFactory.returnStatement($return, null, $semicolon); } @override diff --git a/pkgs/code_builder/lib/src/builders/statement/block.dart b/pkgs/code_builder/lib/src/builders/statement/block.dart index d39cf0ece..284440b7e 100644 --- a/pkgs/code_builder/lib/src/builders/statement/block.dart +++ b/pkgs/code_builder/lib/src/builders/statement/block.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/tokens.dart'; @@ -22,7 +23,7 @@ class _BlockStatementBuilder extends Object @override Statement buildStatement([Scope scope]) { - return new Block( + return astFactory.block( $openCurly, buildStatements(scope), $closeCurly, diff --git a/pkgs/code_builder/lib/src/builders/statement/if.dart b/pkgs/code_builder/lib/src/builders/statement/if.dart index 31fd59bd4..875ee8cfb 100644 --- a/pkgs/code_builder/lib/src/builders/statement/if.dart +++ b/pkgs/code_builder/lib/src/builders/statement/if.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/src/builders/expression.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement.dart'; @@ -72,7 +73,7 @@ class _BlockIfStatementBuilder extends Object @override Statement buildStatement([Scope scope]) { - return new IfStatement( + return astFactory.ifStatement( $if, $openParen, _condition.buildExpression(scope), diff --git a/pkgs/code_builder/lib/src/builders/type.dart b/pkgs/code_builder/lib/src/builders/type.dart index 540d66252..27f6b6ad4 100644 --- a/pkgs/code_builder/lib/src/builders/type.dart +++ b/pkgs/code_builder/lib/src/builders/type.dart @@ -6,6 +6,7 @@ library code_builder.src.builders.type; import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:analyzer/src/dart/ast/token.dart'; import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/expression.dart'; @@ -107,7 +108,7 @@ class TypeBuilder extends Object /// Returns an [TypeName] AST representing the builder. TypeName buildType([Scope scope]) { - return new TypeName( + return astFactory.typeName( identifier( scope, _name, @@ -115,7 +116,7 @@ class TypeBuilder extends Object ), _generics.isEmpty ? null - : new TypeArgumentList( + : astFactory.typeArgumentList( $openBracket, _generics.map((t) => t.buildType(scope)).toList(), $closeBracket, diff --git a/pkgs/code_builder/lib/src/builders/type/new_instance.dart b/pkgs/code_builder/lib/src/builders/type/new_instance.dart index 6129d876b..9c48bc80e 100644 --- a/pkgs/code_builder/lib/src/builders/type/new_instance.dart +++ b/pkgs/code_builder/lib/src/builders/type/new_instance.dart @@ -33,7 +33,7 @@ class _NewInvocationBuilderImpl extends Object @override Annotation buildAnnotation([Scope scope]) { - return new Annotation( + return astFactory.annotation( $at, _type.buildType(scope).name, $period, @@ -44,9 +44,9 @@ class _NewInvocationBuilderImpl extends Object @override Expression buildExpression([Scope scope]) { - return new InstanceCreationExpression( + return astFactory.instanceCreationExpression( new KeywordToken(_keyword, 0), - new ConstructorName( + astFactory.constructorName( _type.buildType(scope), _name != null ? $period : null, _name != null ? stringIdentifier(_name) : null, diff --git a/pkgs/code_builder/lib/src/scope.dart b/pkgs/code_builder/lib/src/scope.dart index f6f6ec48f..120695598 100644 --- a/pkgs/code_builder/lib/src/scope.dart +++ b/pkgs/code_builder/lib/src/scope.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'builders/file.dart'; import 'tokens.dart'; @@ -82,7 +83,7 @@ class _IdentityScope implements Scope { @override Identifier identifier(String name, [_]) { - return new SimpleIdentifier(stringToken(name)); + return astFactory.simpleIdentifier(stringToken(name)); } @override @@ -100,7 +101,7 @@ class _IncrementingScope extends _IdentityScope { return super.identifier(name); } var newId = _imports.putIfAbsent(importFrom, () => _counter++); - return new PrefixedIdentifier( + return astFactory.prefixedIdentifier( super.identifier('_i$newId'), $period, super.identifier(name), diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index e06ebe341..312281383 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -8,7 +8,7 @@ environment: sdk: '>=1.9.1 <2.0.0' dependencies: - analyzer: '>=0.28.1 <0.30.0' + analyzer: '>=0.29.1 <0.30.0' dart_style: ^0.2.10 matcher: ^0.12.0+2 meta: ^1.0.2 From f8867d255d8a06660fa6feaf2d6bf8abdcc7736a Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Tue, 29 Nov 2016 14:45:51 -0800 Subject: [PATCH 022/271] Update pubspec and changelog (dart-lang/code_builder#37) --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 72803f7a6..741587371 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.0-alpha+7 + +- Make use of new analyzer API in preparation for analyzer version 0.30. + ## 1.0.0-alpha+6 - `MethodBuilder.closure` emits properly as a top-level function diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 312281383..9fbdca234 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-alpha+6 +version: 1.0.0-alpha+7 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From cf0cfa03482cbec278ebd12a743e242c3617cb48 Mon Sep 17 00:00:00 2001 From: Andrew Lorenzen Date: Sun, 4 Dec 2016 14:00:11 -0800 Subject: [PATCH 023/271] Fix inconsistency in scope.dart (dart-lang/code_builder#41) Change Scope.identifier() to make importFrom an optional parameter. All subclasses of Scope.identifier already do this, so it is inconsistent for the actual interface to not.. --- pkgs/code_builder/lib/src/scope.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/lib/src/scope.dart b/pkgs/code_builder/lib/src/scope.dart index 120695598..d1edcf181 100644 --- a/pkgs/code_builder/lib/src/scope.dart +++ b/pkgs/code_builder/lib/src/scope.dart @@ -56,7 +56,7 @@ abstract class Scope { factory Scope.dedupe() => new _DeduplicatingScope(); /// Given a [name] and and import path, returns an [Identifier]. - Identifier identifier(String name, String importFrom); + Identifier identifier(String name, [String importFrom]); /// Return a list of import statements. List toImports(); From 3a282141903cbe38853560069d394bbd95bfbfd0 Mon Sep 17 00:00:00 2001 From: Yegor Date: Tue, 13 Dec 2016 10:14:55 -0800 Subject: [PATCH 024/271] forward Scope in returns and constructors (dart-lang/code_builder#44) * forward Scope in returns and constructors * add test * changelog + version bump --- pkgs/code_builder/CHANGELOG.md | 4 ++++ .../lib/src/builders/expression/return.dart | 2 +- pkgs/code_builder/lib/src/builders/method.dart | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/e2e_test.dart | 10 +++++++++- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 741587371..2b429cac8 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.0-alpha+8 + +- Fix an import scoping bug in `return` statements and named constructor invocations. + ## 1.0.0-alpha+7 - Make use of new analyzer API in preparation for analyzer version 0.30. diff --git a/pkgs/code_builder/lib/src/builders/expression/return.dart b/pkgs/code_builder/lib/src/builders/expression/return.dart index 41de4360c..2a0af2981 100644 --- a/pkgs/code_builder/lib/src/builders/expression/return.dart +++ b/pkgs/code_builder/lib/src/builders/expression/return.dart @@ -16,7 +16,7 @@ class _AsReturn extends TopLevelMixin implements StatementBuilder { Statement buildStatement([Scope scope]) { return astFactory.returnStatement( $return, - _value.buildExpression(), + _value.buildExpression(scope), $semicolon, ); } diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index 6ac013c86..5ba04f122 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -492,7 +492,7 @@ class _NormalConstructorBuilder extends Object null, null, null, - returnType.buildType().name, + returnType.buildType(scope).name, _name != null ? $period : null, _name != null ? stringIdentifier(_name) : null, buildParameterList(scope), diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 9fbdca234..de1f53f5f 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-alpha+7 +version: 1.0.0-alpha+8 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/e2e_test.dart b/pkgs/code_builder/test/e2e_test.dart index 1c887808c..9a00f7e2c 100644 --- a/pkgs/code_builder/test/e2e_test.dart +++ b/pkgs/code_builder/test/e2e_test.dart @@ -84,7 +84,11 @@ void main() { reference('_module').invoke('getDep1', []), reference('_module').invoke('getDep2', []), ]), - )..addAnnotation(lib$core.override))); + )..addAnnotation(lib$core.override)) + ..addMethod(new MethodBuilder( + 'instantiateAndReturnNamedThing', + returnType: thingRef, + )..addStatement(thingRef.namedNewInstance('named', []).asReturn()))); expect( lib, equalsSource( @@ -99,6 +103,10 @@ void main() { @override _i2.Thing getThing() => new _i2.Thing(_module.getDep1(), _module.getDep2()); + + _i2.Thing instantiateAndReturnNamedThing() { + return new _i2.Thing.named(); + } } ''', pretty: true, From 75c8c69440bc1b80eb66989ca8625602713044b0 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 19 Dec 2016 21:57:24 -0800 Subject: [PATCH 025/271] Add async/await/sync/yield and toImport/ExportBuilder (dart-lang/code_builder#46) * Various changes. * Update presubmit. * Add async, await, yield * . * . * Update CHANGELOG.md * Update pubspec.yaml --- pkgs/code_builder/CHANGELOG.md | 6 ++ pkgs/code_builder/lib/code_builder.dart | 1 + pkgs/code_builder/lib/src/builders/class.dart | 11 +++ .../lib/src/builders/expression.dart | 27 +++++- .../lib/src/builders/expression/await.dart | 22 +++++ .../lib/src/builders/expression/yield.dart | 25 ++++++ .../code_builder/lib/src/builders/method.dart | 88 +++++++++++++++---- .../lib/src/builders/reference.dart | 21 +++++ pkgs/code_builder/lib/src/builders/type.dart | 27 ++++++ pkgs/code_builder/lib/src/pretty_printer.dart | 5 +- pkgs/code_builder/lib/src/tokens.dart | 12 +++ pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/expression_test.dart | 27 ++++++ .../test/builders/method_test.dart | 43 +++++++-- .../code_builder/test/builders/type_test.dart | 18 ++++ 15 files changed, 309 insertions(+), 26 deletions(-) create mode 100644 pkgs/code_builder/lib/src/builders/expression/await.dart create mode 100644 pkgs/code_builder/lib/src/builders/expression/yield.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 2b429cac8..a45bafc33 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.0.0-alpha+9 + +- Add support for `async`, `sync`, `sync*` functions +- Add support for expression `asAwait`, `asYield`, `asYieldStar` +- Add `toExportBuilder` and `toImportBuilder` to types and references + ## 1.0.0-alpha+8 - Fix an import scoping bug in `return` statements and named constructor invocations. diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 283898c7f..ed6494ee9 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -23,6 +23,7 @@ export 'src/builders/method.dart' named, ConstructorBuilder, MethodBuilder, + MethodModifier, ValidMethodMember; export 'src/builders/parameter.dart' show parameter, ParameterBuilder; export 'src/pretty_printer.dart' show prettyToSource; diff --git a/pkgs/code_builder/lib/src/builders/class.dart b/pkgs/code_builder/lib/src/builders/class.dart index 88830e8e4..ea1794caa 100644 --- a/pkgs/code_builder/lib/src/builders/class.dart +++ b/pkgs/code_builder/lib/src/builders/class.dart @@ -7,6 +7,7 @@ import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/dart/core.dart'; import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/field.dart'; +import 'package:code_builder/src/builders/file.dart'; import 'package:code_builder/src/builders/method.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/type.dart'; @@ -254,6 +255,16 @@ class _ClassBuilderImpl extends Object void setExtends(TypeBuilder extend) { _extends = extend; } + + @override + ExportBuilder toExportBuilder() { + throw new UnsupportedError('Not supported for ClassBuilder'); + } + + @override + ImportBuilder toImportBuilder({bool deferred: false, String prefix}) { + throw new UnsupportedError('Not supported for ClassBuilder'); + } } class _TypeNameWrapper implements ValidClassMember { diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index 56a04a304..b3f957d56 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -19,11 +19,13 @@ import 'package:code_builder/src/tokens.dart'; part 'expression/assert.dart'; part 'expression/assign.dart'; +part 'expression/await.dart'; part 'expression/cascade.dart'; part 'expression/invocation.dart'; part 'expression/negate.dart'; part 'expression/operators.dart'; part 'expression/return.dart'; +part 'expression/yield.dart'; final _false = astFactory.booleanLiteral(new KeywordToken(Keyword.FALSE, 0), true); @@ -141,6 +143,9 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { }) => new _AsAssign(this, variable, nullAware, target); + @override + ExpressionBuilder asAwait() => new _AsAwait(this); + @override StatementBuilder asConst(String variable, [TypeBuilder type]) { return new _AsAssignNew(this, variable, type, $const); @@ -165,6 +170,12 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { return new _AsAssignNew(this, variable, type, $var); } + @override + StatementBuilder asYield() => new _AsYield(this, false); + + @override + StatementBuilder asYieldStar() => new _AsYield(this, true); + @override Statement buildStatement([Scope scope]) { return asStatement().buildStatement(scope); @@ -273,8 +284,14 @@ abstract class ExpressionBuilder /// Returns as a [StatementBuilder] that assigns to an existing [variable]. /// /// If [target] is specified, determined to be `{target}.{variable}`. - StatementBuilder asAssign(String variable, - {ExpressionBuilder target, bool nullAware}); + StatementBuilder asAssign( + String variable, { + ExpressionBuilder target, + bool nullAware, + }); + + /// Returns as an expression `await`-ing this one. + ExpressionBuilder asAwait() => new _AsAwait(this); /// Returns as a [StatementBuilder] that assigns to a new `const` [variable]. StatementBuilder asConst(String variable, [TypeBuilder type]); @@ -300,6 +317,12 @@ abstract class ExpressionBuilder /// If [type] is supplied, the resulting statement is `{type} {variable} =`. StatementBuilder asVar(String variable, [TypeBuilder type]); + /// Returns as a [StatementBuilder] yielding this one. + StatementBuilder asYield(); + + /// Returns as a [StatementBuilder] yielding this one. + StatementBuilder asYieldStar(); + /// Returns an [Expression] AST representing the builder. Expression buildExpression([Scope scope]); diff --git a/pkgs/code_builder/lib/src/builders/expression/await.dart b/pkgs/code_builder/lib/src/builders/expression/await.dart new file mode 100644 index 000000000..5b15fabb0 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/await.dart @@ -0,0 +1,22 @@ +// 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. + +part of code_builder.src.builders.expression; + +class _AsAwait extends AbstractExpressionMixin with TopLevelMixin { + final ExpressionBuilder _expression; + + _AsAwait(this._expression); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return new AwaitExpression( + $await, + _expression.buildExpression(scope), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/yield.dart b/pkgs/code_builder/lib/src/builders/expression/yield.dart new file mode 100644 index 000000000..98742615d --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/yield.dart @@ -0,0 +1,25 @@ +// 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. + +part of code_builder.src.builders.expression; + +class _AsYield extends TopLevelMixin implements StatementBuilder { + final ExpressionBuilder _expression; + final bool _isStar; + + _AsYield(this._expression, this._isStar); + + @override + Statement buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) { + return new YieldStatement( + $yield, + _isStar ? $star : null, + _expression.buildExpression(scope), + $semicolon, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index 5ba04f122..f2bbd3c11 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -18,20 +18,42 @@ import 'package:code_builder/src/builders/type.dart'; import 'package:code_builder/src/tokens.dart'; /// Short-hand for `new ConstructorBuilder(...)`. -ConstructorBuilder constructor( - [Iterable members = const []]) { +ConstructorBuilder constructor([ + Iterable members = const [], +]) { return _constructorImpl(members: members); } /// Short-hand for `new ConstructorBuilder(name)`. -ConstructorBuilder constructorNamed(String name, - [Iterable members = const []]) { +ConstructorBuilder constructorNamed( + String name, [ + Iterable members = const [], +]) { return _constructorImpl(name: name, members: members); } +/// Various types of modifiers for methods. +class MethodModifier implements ValidMethodMember { + static const MethodModifier async = const MethodModifier._('async', false); + static const MethodModifier asyncStar = const MethodModifier._('async', true); + static const MethodModifier syncStar = const MethodModifier._('sync', true); + + final String _keyword; + + const MethodModifier._(this._keyword, this.isStar); + + @override + buildAst([_]) => throw new UnsupportedError('Not an AST'); + + final bool isStar; + + Token keyword() => new StringToken(TokenType.KEYWORD, _keyword, 0); +} + /// Short-hand for `new MethodBuilder.getter(...)`. MethodBuilder getter( String name, { + MethodModifier modifier, Iterable statements, ExpressionBuilder returns, TypeBuilder returnType, @@ -39,12 +61,14 @@ MethodBuilder getter( if (returns != null) { return new MethodBuilder.getter( name, + modifier: modifier, returnType: returnType, returns: returns, ); } else { return new MethodBuilder.getter( name, + modifier: modifier, returnType: returnType, )..addStatements(statements); } @@ -54,9 +78,15 @@ MethodBuilder getter( MethodBuilder lambda( String name, ExpressionBuilder value, { + MethodModifier modifier, TypeBuilder returnType, }) { - return new MethodBuilder(name, returns: value, returnType: returnType); + return new MethodBuilder( + name, + modifier: modifier, + returns: value, + returnType: returnType, + ); } /// A more short-hand way of constructing a [MethodBuilder]. @@ -67,6 +97,7 @@ MethodBuilder method( final List positional = []; final List<_NamedParameterWrapper> named = <_NamedParameterWrapper>[]; final List statements = []; + MethodModifier modifier; TypeBuilder returnType; for (final member in members) { if (member is TypeBuilder) { @@ -77,12 +108,15 @@ MethodBuilder method( named.add(member); } else if (member is StatementBuilder) { statements.add(member); + } else if (member is MethodModifier) { + modifier = member; } else { throw new StateError('Invalid AST type: ${member.runtimeType}'); } } final method = new _MethodBuilderImpl( name, + modifier: modifier, returns: returnType, ); positional.forEach(method.addPositional); @@ -161,8 +195,10 @@ abstract class ConstructorBuilder void addPositional(ParameterBuilder parameter, {bool asField: false}); /// Returns an [ConstructorDeclaration] AST representing the builder. - ConstructorDeclaration buildConstructor(TypeBuilder returnType, - [Scope scope]); + ConstructorDeclaration buildConstructor( + TypeBuilder returnType, [ + Scope scope, + ]); } /// Lazily builds a method/function AST when the builder is invoked. @@ -176,6 +212,7 @@ abstract class MethodBuilder /// Creates a new [MethodBuilder]. factory MethodBuilder( String name, { + MethodModifier modifier, ExpressionBuilder returns, TypeBuilder returnType, }) { @@ -185,10 +222,12 @@ abstract class MethodBuilder returns, returnType, null, + modifier, ); } else { return new _MethodBuilderImpl( name, + modifier: modifier, returns: returnType, ); } @@ -196,6 +235,7 @@ abstract class MethodBuilder /// Creates a new [MethodBuilder] that returns an anonymous closure. factory MethodBuilder.closure({ + MethodModifier modifier, ExpressionBuilder returns, TypeBuilder returnType, }) { @@ -205,10 +245,12 @@ abstract class MethodBuilder returns, returnType, null, + modifier, ); } else { return new _MethodBuilderImpl( null, + modifier: modifier, returns: returnType, ); } @@ -217,12 +259,14 @@ abstract class MethodBuilder /// Creates a getter. factory MethodBuilder.getter( String name, { + MethodModifier modifier, TypeBuilder returnType, ExpressionBuilder returns, }) { if (returns == null) { return new _MethodBuilderImpl( name, + modifier: modifier, returns: returnType, property: Keyword.GET, ); @@ -232,6 +276,7 @@ abstract class MethodBuilder returns, returnType, Keyword.GET, + modifier, ); } } @@ -246,6 +291,7 @@ abstract class MethodBuilder returns, lib$core.$void, null, + null, ); } @@ -265,6 +311,7 @@ abstract class MethodBuilder returns, null, Keyword.SET, + null, ); } } @@ -300,12 +347,18 @@ class _LambdaMethodBuilder extends Object TopLevelMixin implements MethodBuilder { final ExpressionBuilder _expression; + final MethodModifier _modifier; final String _name; final TypeBuilder _returnType; final Keyword _property; _LambdaMethodBuilder( - this._name, this._expression, this._returnType, this._property); + this._name, + this._expression, + this._returnType, + this._property, + this._modifier, + ); @override void addStatement(StatementBuilder statement) { @@ -335,7 +388,7 @@ class _LambdaMethodBuilder extends Object null, _property != Keyword.GET ? buildParameterList(scope) : null, astFactory.expressionFunctionBody( - null, + _modifier?.keyword(), null, _expression.buildExpression(scope), isStatement ? $semicolon : null, @@ -351,7 +404,7 @@ class _LambdaMethodBuilder extends Object null, _returnType?.buildType(scope), _property != null ? new KeywordToken(_property, 0) : null, - stringIdentifier(_name), + _name != null ? stringIdentifier(_name) : null, _buildExpression(scope, isStatement: true), ); } @@ -370,7 +423,7 @@ class _LambdaMethodBuilder extends Object null, _property != Keyword.GET ? buildParameterList(scope) : null, astFactory.expressionFunctionBody( - null, + _modifier?.keyword(), null, _expression.buildExpression(scope), $semicolon, @@ -390,16 +443,19 @@ class _MethodBuilderImpl extends Object HasStatementsMixin, TopLevelMixin implements MethodBuilder { + final MethodModifier _modifier; final String _name; final TypeBuilder _returnType; final Keyword _property; _MethodBuilderImpl( this._name, { + MethodModifier modifier, TypeBuilder returns, Keyword property, }) - : _returnType = returns, + : _modifier = modifier, + _returnType = returns, _property = property; @override @@ -416,8 +472,8 @@ class _MethodBuilderImpl extends Object null, _property != Keyword.GET ? buildParameterList(scope) : null, astFactory.blockFunctionBody( - null, - null, + _modifier?.keyword(), + _modifier?.isStar == true ? $star : null, buildBlock(scope), ), ); @@ -450,8 +506,8 @@ class _MethodBuilderImpl extends Object null, _property != Keyword.GET ? buildParameterList(scope) : null, astFactory.blockFunctionBody( - null, - null, + _modifier?.keyword(), + _modifier?.isStar == true ? $star : null, buildBlock(scope), ), ); diff --git a/pkgs/code_builder/lib/src/builders/reference.dart b/pkgs/code_builder/lib/src/builders/reference.dart index b48f725b9..5e771ad0b 100644 --- a/pkgs/code_builder/lib/src/builders/reference.dart +++ b/pkgs/code_builder/lib/src/builders/reference.dart @@ -6,6 +6,7 @@ import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/expression.dart'; +import 'package:code_builder/src/builders/file.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/builders/type.dart'; @@ -63,6 +64,26 @@ class ReferenceBuilder extends Object return new TypeBuilder(_name, importFrom: _importFrom).buildType(scope); } + @override + ExportBuilder toExportBuilder() { + if (_importFrom == null) { + throw new StateError('Cannot create an import - no URI provided'); + } + return new ExportBuilder(_importFrom)..show(_name); + } + + @override + ImportBuilder toImportBuilder({bool deferred: false, String prefix}) { + if (_importFrom == null) { + throw new StateError('Cannot create an import - no URI provided'); + } + return new ImportBuilder( + _importFrom, + deferred: deferred, + prefix: prefix, + )..show(_name); + } + /// Returns a new [ReferenceBuilder] with [genericTypes]. /// /// Example use: diff --git a/pkgs/code_builder/lib/src/builders/type.dart b/pkgs/code_builder/lib/src/builders/type.dart index 27f6b6ad4..851462bc4 100644 --- a/pkgs/code_builder/lib/src/builders/type.dart +++ b/pkgs/code_builder/lib/src/builders/type.dart @@ -8,6 +8,7 @@ import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:analyzer/src/dart/ast/token.dart'; +import 'package:code_builder/code_builder.dart'; import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/expression.dart'; import 'package:code_builder/src/builders/method.dart'; @@ -62,6 +63,12 @@ abstract class AbstractTypeBuilderMixin { return builder; } + /// Returns as an import to this reference. + ImportBuilder toImportBuilder({bool deferred: false, String prefix}); + + /// Returns as an export to the reference. + ExportBuilder toExportBuilder(); + static void _addArguments( NewInstanceBuilder builder, Iterable positional, @@ -123,4 +130,24 @@ class TypeBuilder extends Object ), ); } + + @override + ExportBuilder toExportBuilder() { + if (_importFrom == null) { + throw new StateError('Cannot create an import - no URI provided'); + } + return new ExportBuilder(_importFrom)..show(_name); + } + + @override + ImportBuilder toImportBuilder({bool deferred: false, String prefix}) { + if (_importFrom == null) { + throw new StateError('Cannot create an import - no URI provided'); + } + return new ImportBuilder( + _importFrom, + deferred: deferred, + prefix: prefix, + )..show(_name); + } } diff --git a/pkgs/code_builder/lib/src/pretty_printer.dart b/pkgs/code_builder/lib/src/pretty_printer.dart index 53d332420..5aef4dc04 100644 --- a/pkgs/code_builder/lib/src/pretty_printer.dart +++ b/pkgs/code_builder/lib/src/pretty_printer.dart @@ -84,7 +84,10 @@ class _PrettyToSourceVisitor extends ToSourceVisitor { // Write a list of [nodes], separated by the given [separator], followed by // the given [suffix] if the list is not empty. void _visitNodeListWithSeparatorAndSuffix( - NodeList nodes, String separator, String suffix) { + NodeList nodes, + String separator, + String suffix, + ) { if (nodes != null) { int size = nodes.length; if (size > 0) { diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index 883e2c26c..01b42da9b 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -14,9 +14,15 @@ final Token $as = new KeywordToken(Keyword.AS, 0); /// The `assert` token. final Token $assert = new KeywordToken(Keyword.ASSERT, 0); +/// The `async` token. +final Token $async = new StringToken(TokenType.KEYWORD, 'async', 0); + /// The `@` token. final Token $at = new Token(TokenType.AT, 0); +/// The `await` token. +final Token $await = new StringToken(TokenType.KEYWORD, 'await', 0); + /// The `class` token. final Token $class = new KeywordToken(Keyword.CLASS, 0); @@ -65,11 +71,17 @@ final Token $gt = new Token(TokenType.GT, 0); /// The `if` token. final Token $if = new KeywordToken(Keyword.IF, 0); +/// The `yield` token. +final Token $yield = new StringToken(TokenType.KEYWORD, 'yield', 0); + // Simple tokens /// The `&&` token. final Token $and = new Token(TokenType.AMPERSAND_AMPERSAND, 0); +/// The `*` token. +final Token $star = $multiply; + /// The `hide` token. final Token $hide = new StringToken(TokenType.KEYWORD, 'hide', 0); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index de1f53f5f..5b84babd5 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-alpha+8 +version: 1.0.0-alpha+9 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 2fa687bb9..36f477ea5 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -294,4 +294,31 @@ void main() { '''), ); }); + + test('should emit await', () { + expect( + reference('foo').asAwait(), + equalsSource(r''' + await foo + '''), + ); + }); + + test('should emit yield', () { + expect( + reference('foo').asYield(), + equalsSource(r''' + yield foo; + '''), + ); + }); + + test('should emit yield*', () { + expect( + reference('foo').asYieldStar(), + equalsSource(r''' + yield* foo; + '''), + ); + }); } diff --git a/pkgs/code_builder/test/builders/method_test.dart b/pkgs/code_builder/test/builders/method_test.dart index 332cdf913..5ff6c7ad0 100644 --- a/pkgs/code_builder/test/builders/method_test.dart +++ b/pkgs/code_builder/test/builders/method_test.dart @@ -170,6 +170,33 @@ void main() { ); }); + test('should emit an async method', () { + expect( + method('fetch', [MethodModifier.async]), + equalsSource(r''' + fetch() async {} + '''), + ); + }); + + test('should emit an async* method', () { + expect( + method('fetch', [MethodModifier.asyncStar]), + equalsSource(r''' + fetch() async* {} + '''), + ); + }); + + test('should emit an sync* method', () { + expect( + method('fetch', [MethodModifier.syncStar]), + equalsSource(r''' + fetch() sync* {} + '''), + ); + }); + group('closure', () { MethodBuilder closure; setUp(() { @@ -185,22 +212,26 @@ void main() { expect( closure, equalsSource(r''' - (bool defaultTo) => false || defaultTo - '''), + (bool defaultTo) => false || defaultTo + '''), ); test('should treat closure as expression', () { expect( - list([true, false]).invoke('where', [closure]), - equalsSource( - '[true, false].where((bool defaultTo) => false || defaultTo)')); + list([true, false]).invoke('where', [closure]), + equalsSource( + '[true, false].where((bool defaultTo) => false || defaultTo)', + ), + ); }); test('should emit a closure as a function in a library', () { final library = new LibraryBuilder(); library.addMember(closure); expect( - library, equalsSource('(bool defaultTo) => false || defaultTo;')); + library, + equalsSource('(bool defaultTo) => false || defaultTo;'), + ); }); }); }); diff --git a/pkgs/code_builder/test/builders/type_test.dart b/pkgs/code_builder/test/builders/type_test.dart index bd82af37b..16c9f4d70 100644 --- a/pkgs/code_builder/test/builders/type_test.dart +++ b/pkgs/code_builder/test/builders/type_test.dart @@ -94,5 +94,23 @@ void main() { '''), ); }); + + test('emits an export builder', () { + expect( + reference('Foo', 'package:foo/foo.dart').toExportBuilder(), + equalsSource(r''' + export 'package:foo/foo.dart' show Foo; + '''), + ); + }); + + test('emits an export builder', () { + expect( + reference('Foo', 'package:foo/foo.dart').toImportBuilder(), + equalsSource(r''' + import 'package:foo/foo.dart' show Foo; + '''), + ); + }); }); } From 528393fdc200223e6924faf6730a30adbd3f06ec Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 4 Jan 2017 20:23:13 -0500 Subject: [PATCH 026/271] New features for 1.0.0-beta (dart-lang/code_builder#52) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add for/for-in loop Closes https://github.com/dart-lang/code_builder/issues/49 * Add support for while/do-while * Add constructor initializers Closes https://github.com/dart-lang/code_builder/issues/50 * Update CHANGELOG and pubspec for beta * Add “name” getter for ParameterBuilder Partial support towards https://github.com/dart-lang/code_builder/issues/43 * Update CHANGELOG * Address feedback --- pkgs/code_builder/CHANGELOG.md | 9 +- pkgs/code_builder/lib/code_builder.dart | 4 +- .../lib/src/builders/expression.dart | 61 ++++++++- .../src/builders/expression/operators.dart | 43 +++++++ .../code_builder/lib/src/builders/method.dart | 78 ++++++++++- .../lib/src/builders/parameter.dart | 18 ++- .../lib/src/builders/statement.dart | 4 + .../lib/src/builders/statement/for.dart | 121 ++++++++++++++++++ .../lib/src/builders/statement/while.dart | 44 +++++++ pkgs/code_builder/lib/src/tokens.dart | 21 +++ pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/class_test.dart | 15 +++ .../test/builders/statement_test.dart | 44 +++++++ 13 files changed, 444 insertions(+), 20 deletions(-) create mode 100644 pkgs/code_builder/lib/src/builders/statement/for.dart create mode 100644 pkgs/code_builder/lib/src/builders/statement/while.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index a45bafc33..be412e6e3 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,12 +1,13 @@ -## 1.0.0-alpha+9 +## 1.0.0-beta - Add support for `async`, `sync`, `sync*` functions - Add support for expression `asAwait`, `asYield`, `asYieldStar` - Add `toExportBuilder` and `toImportBuilder` to types and references - -## 1.0.0-alpha+8 - - Fix an import scoping bug in `return` statements and named constructor invocations. +- Added constructor initializer support +- Add `while` and `do {} while` loop support +- Add `for` and `for-in` support +- Added a `name` getter for `ParameterBuilder` ## 1.0.0-alpha+7 diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index ed6494ee9..26a9ae82c 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -36,6 +36,8 @@ export 'src/builders/statement.dart' elseIf, elseThen, returnVoid, + ForStatementBuilder, IfStatementBuilder, - StatementBuilder; + StatementBuilder, + WhileStatementBuilder; export 'src/builders/type.dart' show NewInstanceBuilder, TypeBuilder; diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index b3f957d56..4a0d4e0b2 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -14,6 +14,7 @@ import 'package:code_builder/src/builders/reference.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/builders/statement/if.dart'; +import 'package:code_builder/src/builders/statement/while.dart'; import 'package:code_builder/src/builders/type.dart'; import 'package:code_builder/src/tokens.dart'; @@ -35,6 +36,9 @@ final _null = astFactory.nullLiteral(new KeywordToken(Keyword.NULL, 0)); final _true = astFactory.booleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); +/// A reference to `super`. +ExpressionBuilder get superRef => new _SuperExpression(); + /// Returns a pre-defined literal expression of [value]. /// /// Only primitive values are allowed. @@ -123,6 +127,24 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { ); } + @override + ExpressionBuilder operator >(ExpressionBuilder other) { + return new _AsBinaryExpression( + this, + other, + $gt, + ); + } + + @override + ExpressionBuilder operator <(ExpressionBuilder other) { + return new _AsBinaryExpression( + this, + other, + $lt, + ); + } + @override ExpressionBuilder and(ExpressionBuilder other) { return new _AsBinaryExpression( @@ -176,6 +198,11 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { @override StatementBuilder asYieldStar() => new _AsYield(this, true); + @override + WhileStatementBuilder asWhile({bool asDo: false}) { + return new WhileStatementBuilder(asDo, this); + } + @override Statement buildStatement([Scope scope]) { return asStatement().buildStatement(scope); @@ -200,6 +227,9 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { return new _CascadeExpression(this, create(reference('.'))); } + @override + ExpressionBuilder decrement() => new _DecrementExpression(this); + @override ExpressionBuilder equals(ExpressionBuilder other) { return new _AsBinaryExpression( @@ -209,9 +239,14 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { ); } + @override + ExpressionBuilder increment([bool prefix = false]) { + return new _IncrementExpression(this, prefix); + } + @override ExpressionBuilder identical(ExpressionBuilder other) { - return lib$core.identical.call([ + return lib$core.identical.call([ this, other, ]); @@ -275,6 +310,12 @@ abstract class ExpressionBuilder /// Returns as an [ExpressionBuilder] dividing by [other]. ExpressionBuilder operator /(ExpressionBuilder other); + /// Returns as an [ExpressionBuilder] `<` by [other]. + ExpressionBuilder operator <(ExpressionBuilder other); + + /// Returns as an [ExpressionBuilder] `>` by [other]. + ExpressionBuilder operator >(ExpressionBuilder other); + /// Returns as an [ExpressionBuilder] `&&` [other]. ExpressionBuilder and(ExpressionBuilder other); @@ -323,6 +364,9 @@ abstract class ExpressionBuilder /// Returns as a [StatementBuilder] yielding this one. StatementBuilder asYieldStar(); + /// Returns as a [WhileStatementBuilder] with this as the condition. + WhileStatementBuilder asWhile({bool asDo: false}); + /// Returns an [Expression] AST representing the builder. Expression buildExpression([Scope scope]); @@ -337,12 +381,18 @@ abstract class ExpressionBuilder Iterable create(ExpressionBuilder self), ); + /// Returns as an [ExpressionBuilder] decrementing this expression. + ExpressionBuilder decrement(); + /// Returns as an [ExpressionBuilder] comparing using `==` against [other]. ExpressionBuilder equals(ExpressionBuilder other); /// Returns as an [ExpressionBuilder] comparing using `identical`. ExpressionBuilder identical(ExpressionBuilder other); + /// Returns as an [ExpressionBuilder] incrementing this expression. + ExpressionBuilder increment([bool prefix = false]); + /// Returns as an [InvocationBuilder] on [method] of this expression. InvocationBuilder invoke( String method, @@ -476,6 +526,15 @@ ExpressionBuilder _expressionify(v) { throw new ArgumentError('Could not expressionify $v'); } +class _SuperExpression extends Object + with AbstractExpressionMixin, TopLevelMixin { + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([_]) => astFactory.superExpression($super); +} + class _TypedListExpression extends Object with AbstractExpressionMixin, TopLevelMixin { static List _toExpression(Iterable values) { diff --git a/pkgs/code_builder/lib/src/builders/expression/operators.dart b/pkgs/code_builder/lib/src/builders/expression/operators.dart index 809f2d159..99bf9eaa4 100644 --- a/pkgs/code_builder/lib/src/builders/expression/operators.dart +++ b/pkgs/code_builder/lib/src/builders/expression/operators.dart @@ -24,3 +24,46 @@ class _AsBinaryExpression extends Object ); } } + +class _DecrementExpression extends Object + with AbstractExpressionMixin, TopLevelMixin { + final ExpressionBuilder _expression; + + _DecrementExpression(this._expression); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return astFactory.postfixExpression( + _expression.buildExpression(scope), + $minusMinus, + ); + } +} + +class _IncrementExpression extends Object + with AbstractExpressionMixin, TopLevelMixin { + final ExpressionBuilder _expression; + final bool _prefix; + + _IncrementExpression(this._expression, this._prefix); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + if (_prefix) { + return astFactory.prefixExpression( + $plusPlus, + _expression.buildExpression(scope), + ); + } + return astFactory.postfixExpression( + _expression.buildExpression(scope), + $plusPlus, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index f2bbd3c11..44e747369 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -171,7 +171,7 @@ ConstructorBuilder _constructorImpl({ throw new StateError('Invalid AST type: ${member.runtimeType}'); } } - final constructor = new ConstructorBuilder(name); + final constructor = new ConstructorBuilder(name: name); _addFunctions.forEach((a) => a(constructor)); return constructor; } @@ -186,7 +186,20 @@ abstract class ConstructorBuilder HasStatements, ValidClassMember { /// Create a new [ConstructorBuilder], optionally with a [name]. - factory ConstructorBuilder([String name]) = _NormalConstructorBuilder; + /// + /// Can invoke `super` if [invokeSuper] is set, using super.[superName]. + factory ConstructorBuilder({ + String name, + String superName, + List invokeSuper, + }) = _NormalConstructorBuilder; + + /// Adds a field initializer to this constructor. + void addInitializer( + String fieldName, { + ExpressionBuilder toExpression, + String toParameter, + }); @override void addNamed(ParameterBuilder parameter, {bool asField: false}); @@ -530,9 +543,28 @@ class _NamedParameterWrapper class _NormalConstructorBuilder extends Object with HasAnnotationsMixin, HasParametersMixin, HasStatementsMixin implements ConstructorBuilder { + final _initializers = {}; final String _name; + final String _superName; + final List _superInvocation; - _NormalConstructorBuilder([this._name]); + _NormalConstructorBuilder({ + List invokeSuper, + String name, + String superName, + }) + : _name = name, + _superInvocation = invokeSuper, + _superName = superName; + + @override + void addInitializer( + String fieldName, { + ExpressionBuilder toExpression, + String toParameter, + }) { + _initializers[fieldName] = toExpression ?? reference(toParameter); + } @override ConstructorDeclaration buildAst([Scope scope]) { @@ -540,8 +572,40 @@ class _NormalConstructorBuilder extends Object } @override - ConstructorDeclaration buildConstructor(TypeBuilder returnType, - [Scope scope]) { + ConstructorDeclaration buildConstructor( + TypeBuilder returnType, [ + Scope scope, + ]) { + List initializers; + if (_initializers.isNotEmpty) { + initializers ??= []; + initializers.addAll( + _initializers.keys.map((fieldName) { + return astFactory.constructorFieldInitializer( + null, + null, + astFactory.simpleIdentifier(stringToken(fieldName)), + $equals, + _initializers[fieldName].buildExpression(scope), + ); + }), + ); + } + if (_superInvocation != null) { + initializers ??= []; + initializers.add(astFactory.superConstructorInvocation( + $super, + _superName != null ? $period : null, + _superName != null + ? astFactory.simpleIdentifier(stringToken(_superName)) + : null, + astFactory.argumentList( + $openParen, + _superInvocation.map((e) => e.buildExpression(scope)).toList(), + $closeParen, + ), + )); + } return astFactory.constructorDeclaration( null, buildAnnotations(scope), @@ -552,8 +616,8 @@ class _NormalConstructorBuilder extends Object _name != null ? $period : null, _name != null ? stringIdentifier(_name) : null, buildParameterList(scope), - null, - null, + initializers != null && initializers.isNotEmpty ? $semicolon : null, + initializers, null, !hasStatements ? astFactory.emptyFunctionBody($semicolon) diff --git a/pkgs/code_builder/lib/src/builders/parameter.dart b/pkgs/code_builder/lib/src/builders/parameter.dart index 5f2cc31a8..a3443c1db 100644 --- a/pkgs/code_builder/lib/src/builders/parameter.dart +++ b/pkgs/code_builder/lib/src/builders/parameter.dart @@ -100,6 +100,9 @@ abstract class ParameterBuilder /// Returns a positional [FormalParameter] AST representing the builder. FormalParameter buildPositional(bool field, [Scope scope]); + + /// Name of the parameter. + String get name; } /// A marker interface for an AST that could be added to [ParameterBuilder]. @@ -140,6 +143,9 @@ class _OptionalParameterBuilder extends Object _expression?.buildExpression(scope), ); } + + @override + String get name => _parameter.name; } class _ParameterPair { @@ -165,15 +171,15 @@ class _ParameterPair { class _SimpleParameterBuilder extends Object with HasAnnotationsMixin implements ParameterBuilder { - final String _name; + @override + final String name; final TypeBuilder _type; _SimpleParameterBuilder( - String name, { + this.name, { TypeBuilder type, }) - : _name = name, - _type = type; + : _type = type; @override ParameterBuilder asOptional([ExpressionBuilder defaultTo]) { @@ -198,7 +204,7 @@ class _SimpleParameterBuilder extends Object _type?.buildType(scope), $this, $period, - stringIdentifier(_name), + stringIdentifier(name), null, null, ); @@ -208,7 +214,7 @@ class _SimpleParameterBuilder extends Object buildAnnotations(scope), null, _type?.buildType(scope), - stringIdentifier(_name), + stringIdentifier(name), ); } } diff --git a/pkgs/code_builder/lib/src/builders/statement.dart b/pkgs/code_builder/lib/src/builders/statement.dart index 85d2befa2..8f7e6a22c 100644 --- a/pkgs/code_builder/lib/src/builders/statement.dart +++ b/pkgs/code_builder/lib/src/builders/statement.dart @@ -9,8 +9,12 @@ import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement/if.dart'; import 'package:code_builder/src/tokens.dart'; +export 'package:code_builder/src/builders/statement/for.dart' + show ForStatementBuilder; export 'package:code_builder/src/builders/statement/if.dart' show IfStatementBuilder, elseIf, elseThen, ifThen; +export 'package:code_builder/src/builders/statement/while.dart' + show WhileStatementBuilder; /// An [AstBuilder] that can add [StatementBuilder]. abstract class HasStatements implements AstBuilder { diff --git a/pkgs/code_builder/lib/src/builders/statement/for.dart b/pkgs/code_builder/lib/src/builders/statement/for.dart new file mode 100644 index 000000000..58bf8d869 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/statement/for.dart @@ -0,0 +1,121 @@ +// 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. + +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; +import 'package:code_builder/src/builders/expression.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:code_builder/src/tokens.dart'; + +abstract class ForStatementBuilder implements HasStatements, StatementBuilder { + factory ForStatementBuilder( + String identifier, + ExpressionBuilder initializer, + ExpressionBuilder condition, + List updaters, + ) = _ForLoopStatementBuilder; + + factory ForStatementBuilder.forEach( + String identifier, + ExpressionBuilder iterable, { + bool asAwait: false, + bool asFinal: false, + }) { + return new _ForIteratorStatementBuilder( + asAwait, + asFinal, + identifier, + iterable, + ); + } +} + +class _ForIteratorStatementBuilder extends Object + with HasStatementsMixin, TopLevelMixin + implements ForStatementBuilder { + final bool _asAwait; + final bool _asFinal; + final String _identifier; + final ExpressionBuilder _iterable; + + _ForIteratorStatementBuilder( + this._asAwait, + this._asFinal, + this._identifier, + this._iterable, + ); + + @override + AstNode buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) { + return astFactory.forEachStatementWithDeclaration( + _asAwait ? $await : null, + $for, + $openParen, + astFactory.declaredIdentifier( + null, + null, + _asFinal ? $final : $var, + null, + astFactory.simpleIdentifier(stringToken(_identifier)), + ), + $in, + _iterable.buildExpression(scope), + $closeParen, + buildBlock(scope), + ); + } +} + +class _ForLoopStatementBuilder extends Object + with HasStatementsMixin, TopLevelMixin + implements ForStatementBuilder { + final String _identifier; + final ExpressionBuilder _initializer; + final ExpressionBuilder _condition; + final List _updaters; + + _ForLoopStatementBuilder( + this._identifier, + this._initializer, + this._condition, + this._updaters, + ); + + @override + AstNode buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) { + return astFactory.forStatement( + $for, + $openParen, + astFactory.variableDeclarationList( + null, + null, + $var, + null, + [ + astFactory.variableDeclaration( + astFactory.simpleIdentifier( + stringToken(_identifier), + ), + $equals, + _initializer.buildExpression(scope), + ), + ], + ), + null, + $semicolon, + _condition.buildExpression(scope), + $semicolon, + _updaters.map((e) => e.buildExpression(scope)).toList(), + $closeParen, + buildBlock(scope), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/statement/while.dart b/pkgs/code_builder/lib/src/builders/statement/while.dart new file mode 100644 index 000000000..ba1cb622c --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/statement/while.dart @@ -0,0 +1,44 @@ +// 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. + +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; +import 'package:code_builder/src/builders/expression.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:code_builder/src/tokens.dart'; + +class WhileStatementBuilder extends HasStatementsMixin + with TopLevelMixin + implements StatementBuilder { + final bool _asDo; + final ExpressionBuilder _condition; + + WhileStatementBuilder(this._asDo, this._condition); + + @override + AstNode buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) { + if (_asDo) { + return astFactory.doStatement( + $do, + buildBlock(scope), + $while, + $openParen, + _condition.buildExpression(scope), + $closeParen, + $semicolon, + ); + } + return astFactory.whileStatement( + $while, + $openParen, + _condition.buildExpression(scope), + $closeParen, + buildBlock(scope), + ); + } +} diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index 01b42da9b..84fbc0631 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -47,6 +47,9 @@ final Token $deferred = new KeywordToken(Keyword.DEFERRED, 0); /// The `/` token. final Token $divide = new Token(TokenType.SLASH, 0); +/// The `do` keyword. +final Token $do = new KeywordToken(Keyword.DO, 0); + /// The `else` token. final Token $else = new KeywordToken(Keyword.ELSE, 0); @@ -65,15 +68,24 @@ final Token $false = new KeywordToken(Keyword.FALSE, 0); /// The `final` token. final Token $final = new KeywordToken(Keyword.FINAL, 0); +/// The `for` keyword. +final Token $for = new KeywordToken(Keyword.FOR, 0); + /// The `>` token. final Token $gt = new Token(TokenType.GT, 0); /// The `if` token. final Token $if = new KeywordToken(Keyword.IF, 0); +/// The `super` keyword. +final Token $super = new KeywordToken(Keyword.SUPER, 0); + /// The `yield` token. final Token $yield = new StringToken(TokenType.KEYWORD, 'yield', 0); +/// The `while` keyword. +final Token $while = new KeywordToken(Keyword.WHILE, 0); + // Simple tokens /// The `&&` token. @@ -88,6 +100,9 @@ final Token $hide = new StringToken(TokenType.KEYWORD, 'hide', 0); /// The `implements` token. final Token $implements = new KeywordToken(Keyword.IMPLEMENTS, 0); +/// The `in` token. +final Token $in = new KeywordToken(Keyword.IN, 0); + /// The `library` token. final Token $library = new KeywordToken(Keyword.LIBRARY, 0); @@ -97,6 +112,9 @@ final Token $lt = new Token(TokenType.LT, 0); /// The `-` token. final Token $minus = new Token(TokenType.MINUS, 0); +/// The `--` token. +final Token $minusMinus = new Token(TokenType.MINUS_MINUS, 0); + /// The `*` token. final Token $multiply = new Token(TokenType.STAR, 0); @@ -139,6 +157,9 @@ final Token $period = new Token(TokenType.PERIOD, 0); /// The `+` token. final Token $plus = new Token(TokenType.PLUS, 0); +/// The `++` token. +final Token $plusPlus = new Token(TokenType.PLUS_PLUS, 0); + /// The `return` token. final Token $return = new KeywordToken(Keyword.RETURN, 0); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 5b84babd5..6f46486e3 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-alpha+9 +version: 1.0.0-beta description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/class_test.dart b/pkgs/code_builder/test/builders/class_test.dart index 40fe307dc..776ee4fec 100644 --- a/pkgs/code_builder/test/builders/class_test.dart +++ b/pkgs/code_builder/test/builders/class_test.dart @@ -101,6 +101,21 @@ void main() { ); }); + test('should emit a class with a constructor with initializers', () { + expect( + clazz('Animal', [ + new ConstructorBuilder( + invokeSuper: const [], + )..addInitializer('name', toParameter: 'other'), + ]), + equalsSource(r''' + class Animal { + Animal() : name = other, super(); + } + '''), + ); + }); + test('should emit a class with fields', () { expect( clazz('Animal', [ diff --git a/pkgs/code_builder/test/builders/statement_test.dart b/pkgs/code_builder/test/builders/statement_test.dart index f76680892..7f0384b2b 100644 --- a/pkgs/code_builder/test/builders/statement_test.dart +++ b/pkgs/code_builder/test/builders/statement_test.dart @@ -95,4 +95,48 @@ void main() { ); }); }); + + group('for statements', () { + test('should emit a simple for-loop', () { + expect( + new ForStatementBuilder( + 'i', + literal(0), + reference('i') < reference('items').property('length'), + [ + reference('i').increment(), + ], + ), + equalsSource(r''' + for (var i = 0; i < items.length; i++) {} + '''), + ); + }); + + test('should emit a simple for-each loop', () { + expect( + new ForStatementBuilder.forEach( + 'item', + reference('items'), + ), + equalsSource(r''' + for (var item in items) {} + '''), + ); + }); + }); + + group('while loop', () { + test('should emit a simple while loop', () { + expect(literal(true).asWhile(), equalsSource(r''' + while(true) {} + ''')); + }); + + test('should emit a simple do-while loop', () { + expect(literal(true).asWhile(asDo: true), equalsSource(r''' + do {} while (true); + ''')); + }); + }); } From ec5ba08d670ba621d08b3bb1f3490748758fee16 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 5 Jan 2017 14:31:19 -0500 Subject: [PATCH 027/271] More test cases, useful until we have more docs (dart-lang/code_builder#55) * Cover another 2 test cases * Remove debug statement --- .../test/builders/expression_test.dart | 11 ++++ .../test/builders/method_test.dart | 52 ++++++++++++------- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 36f477ea5..0510f2088 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -295,6 +295,17 @@ void main() { ); }); + test('should scope on newInstance', () { + expect( + reference('Foo', 'package:foo/foo.dart').newInstance([]).asReturn(), + equalsSource( + r''' + return new _i1.Foo(); + ''', + scope: new Scope()), + ); + }); + test('should emit await', () { expect( reference('foo').asAwait(), diff --git a/pkgs/code_builder/test/builders/method_test.dart b/pkgs/code_builder/test/builders/method_test.dart index 5ff6c7ad0..8a6c7b9bf 100644 --- a/pkgs/code_builder/test/builders/method_test.dart +++ b/pkgs/code_builder/test/builders/method_test.dart @@ -202,7 +202,6 @@ void main() { setUp(() { closure = new MethodBuilder.closure( returns: literal(false).or(reference('defaultTo')), - returnType: lib$core.bool, )..addPositional(parameter('defaultTo', [lib$core.bool])); }); @@ -215,24 +214,41 @@ void main() { (bool defaultTo) => false || defaultTo '''), ); + }); + + test('should treat closure as expression', () { + expect( + list([true, false]).invoke('where', [closure]), + equalsSource( + '[true, false].where((bool defaultTo) => false || defaultTo)', + ), + ); + }); + + test('should emit a closure as a function in a library', () { + final library = new LibraryBuilder(); + library.addMember(closure); + expect( + library, + equalsSource('(bool defaultTo) => false || defaultTo;'), + ); + }); - test('should treat closure as expression', () { - expect( - list([true, false]).invoke('where', [closure]), - equalsSource( - '[true, false].where((bool defaultTo) => false || defaultTo)', - ), - ); - }); - - test('should emit a closure as a function in a library', () { - final library = new LibraryBuilder(); - library.addMember(closure); - expect( - library, - equalsSource('(bool defaultTo) => false || defaultTo;'), - ); - }); + test('should emit a closure with a statement body', () { + expect( + (new MethodBuilder.closure() + ..addPositional(new ParameterBuilder('value')) + ..addStatement(reference('value').invoke( + 'join', + [literal(' - ')], + ).asAssign('title'))) + .asStatement(), + equalsSource(r''' + (value) { + title = value.join(' - '); + }; + '''), + ); }); }); } From 5b04ac9606e304901a5f6ff755329259fc0de778 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 10 Jan 2017 00:34:02 -0500 Subject: [PATCH 028/271] Added support for switch and break statements (dart-lang/code_builder#56) * Added switch statements, and break statements * Edited test * dartfmt on break.dart * BSD header and more --- pkgs/code_builder/lib/code_builder.dart | 7 + .../lib/src/builders/statement.dart | 10 ++ .../lib/src/builders/statement/break.dart | 30 ++++ .../lib/src/builders/statement/switch.dart | 150 ++++++++++++++++++ pkgs/code_builder/lib/src/tokens.dart | 12 ++ .../test/builders/break_test.dart | 13 ++ .../test/builders/switch_test.dart | 56 +++++++ 7 files changed, 278 insertions(+) create mode 100644 pkgs/code_builder/lib/src/builders/statement/break.dart create mode 100644 pkgs/code_builder/lib/src/builders/statement/switch.dart create mode 100644 pkgs/code_builder/test/builders/break_test.dart create mode 100644 pkgs/code_builder/test/builders/switch_test.dart diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 26a9ae82c..4a3f6d4a7 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -32,12 +32,19 @@ export 'src/builders/reference.dart' export 'src/builders/shared.dart' show AstBuilder, Scope; export 'src/builders/statement.dart' show + breakStatement, ifThen, elseIf, elseThen, returnVoid, + switchCase, + switchDefault, + switchStatement, ForStatementBuilder, IfStatementBuilder, StatementBuilder, + SwitchCaseBuilder, + SwitchDefaultCaseBuilder, + SwitchStatementBuilder, WhileStatementBuilder; export 'src/builders/type.dart' show NewInstanceBuilder, TypeBuilder; diff --git a/pkgs/code_builder/lib/src/builders/statement.dart b/pkgs/code_builder/lib/src/builders/statement.dart index 8f7e6a22c..b18c11a6e 100644 --- a/pkgs/code_builder/lib/src/builders/statement.dart +++ b/pkgs/code_builder/lib/src/builders/statement.dart @@ -9,10 +9,20 @@ import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement/if.dart'; import 'package:code_builder/src/tokens.dart'; +export 'package:code_builder/src/builders/statement/break.dart' + show breakStatement; export 'package:code_builder/src/builders/statement/for.dart' show ForStatementBuilder; export 'package:code_builder/src/builders/statement/if.dart' show IfStatementBuilder, elseIf, elseThen, ifThen; +export 'package:code_builder/src/builders/statement/switch.dart' + show + SwitchCaseBuilder, + SwitchDefaultCaseBuilder, + SwitchStatementBuilder, + switchDefault, + switchCase, + switchStatement; export 'package:code_builder/src/builders/statement/while.dart' show WhileStatementBuilder; diff --git a/pkgs/code_builder/lib/src/builders/statement/break.dart b/pkgs/code_builder/lib/src/builders/statement/break.dart new file mode 100644 index 000000000..e2da27535 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/statement/break.dart @@ -0,0 +1,30 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:code_builder/src/tokens.dart'; + +/// Represents a break statement AST. +const breakStatement = const _BreakStatementBuilder(); + +class _BreakStatementBuilder extends Object implements StatementBuilder { + const _BreakStatementBuilder(); + + @override + AstNode buildAst([Scope scope]) => buildStatement(scope); + + @override + Statement buildStatement([Scope scope]) => buildBreakStatement(scope); + + BreakStatement buildBreakStatement([Scope scope]) => + astFactory.breakStatement($break, null, $semicolon); + + @override + CompilationUnitMember buildTopLevelAst([Scope scope]) { + throw new UnsupportedError('$runtimeType does not work in the top-level'); + } +} diff --git a/pkgs/code_builder/lib/src/builders/statement/switch.dart b/pkgs/code_builder/lib/src/builders/statement/switch.dart new file mode 100644 index 000000000..e2bc1bf63 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/statement/switch.dart @@ -0,0 +1,150 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/ast/standard_ast_factory.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/expression.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:code_builder/src/tokens.dart'; + +/// Short-hand syntax for `new SwitchCaseBuilder(...)`. +SwitchCaseBuilder switchCase(ExpressionBuilder condition, + [Iterable statements = const []]) => + new SwitchCaseBuilder(condition)..addStatements(statements ?? []); + +/// Short-hand syntax for `new SwitchDefaultCaseBuilder(...)`. +SwitchDefaultCaseBuilder switchDefault( + [Iterable statements = const []]) => + new SwitchDefaultCaseBuilder()..addStatements(statements ?? []); + +/// Short-hand syntax for `new SwitchStatementBuilder(...)`. +SwitchStatementBuilder switchStatement(ExpressionBuilder expression, + {Iterable cases: const [], + SwitchDefaultCaseBuilder defaultCase}) => + new SwitchStatementBuilder(expression) + ..setDefaultCase(defaultCase) + ..addCases(cases ?? []); + +/// Represents an [ExpressionBuilder] and a series of [SwitchCaseBuilder]s as a switch statement AST. +abstract class SwitchStatementBuilder implements StatementBuilder { + /// Creates a new [SwitchStatementBuilder]. + factory SwitchStatementBuilder(ExpressionBuilder expression, + [Iterable members = const []]) => + new _SwitchStatementBuilder(expression, members); + + /// Adds a [switchCase] to the builder. + void addCase(SwitchCaseBuilder switchCase); + + /// Adds a [switchCase]s to the builder. + void addCases(Iterable switchCases); + + /// Returns an [SwitchStatement] AST representing the builder. + SwitchStatement buildSwitchStatement(); + + /// Sets the `default` cases of the builder. + void setDefaultCase(SwitchDefaultCaseBuilder defaultCase); +} + +/// A marker interface for an AST that could be added to [SwitchStatementBuilder]. +/// +/// This can be either a [SwitchCaseBuilder] or a [SwitchDefaultCaseBuilder]. +abstract class ValidSwitchMember {} + +/// Represents an [ExpressionBuilder] and a series of [Statement]s as a switch case AST. +abstract class SwitchCaseBuilder implements HasStatements, ValidSwitchMember { + /// Creates a new [SwitchCaseBuilder]. + factory SwitchCaseBuilder(ExpressionBuilder condition) => + new _SwitchCaseBuilder(condition); + + /// Returns an [SwitchMember] AST representing the builder. + SwitchMember buildSwitchMember([Scope scope]); +} + +/// Represents a series of [Statement]s as a default switch case AST. +abstract class SwitchDefaultCaseBuilder + implements HasStatements, ValidSwitchMember { + factory SwitchDefaultCaseBuilder() => new _SwitchDefaultCaseBuilder(); + + /// Returns an [SwitchMember] AST representing the builder. + SwitchMember buildSwitchMember([Scope scope]); +} + +class _SwitchStatementBuilder extends Object + with TopLevelMixin + implements SwitchStatementBuilder { + final ExpressionBuilder _expression; + final List _cases = []; + SwitchDefaultCaseBuilder _defaultCase; + + _SwitchStatementBuilder(this._expression, + [Iterable members = const []]) { + for (final member in members) { + if (member is SwitchDefaultCaseBuilder) + _defaultCase = member; + else if (member is SwitchCaseBuilder) _cases.add(member); + } + } + + @override + void addCase(SwitchCaseBuilder switchCase) => _cases.add(switchCase); + + @override + void addCases(Iterable switchCases) => + _cases.addAll(switchCases); + + @override + void setDefaultCase(SwitchDefaultCaseBuilder defaultCase) { + _defaultCase = defaultCase; + } + + @override + AstNode buildAst([Scope scope]) => buildStatement(); + + @override + SwitchStatement buildSwitchStatement([Scope scope]) { + var members = _cases.map((c) => c.buildSwitchMember(scope)).toList(); + + if (_defaultCase != null) + members.add(_defaultCase.buildSwitchMember(scope)); + + return astFactory.switchStatement( + $switch, + $openBracket, + _expression.buildExpression(), + $closeParen, + $openBracket, + members, + $closeBracket); + } + + @override + Statement buildStatement([Scope scope]) => buildSwitchStatement(scope); +} + +class _SwitchCaseBuilder extends Object + with HasStatementsMixin + implements SwitchCaseBuilder { + final ExpressionBuilder _condition; + + _SwitchCaseBuilder(this._condition); + + @override + AstNode buildAst([Scope scope]) => buildSwitchMember(scope); + + @override + SwitchMember buildSwitchMember([Scope scope]) => astFactory.switchCase(null, + $case, _condition.buildExpression(), $colon, buildStatements(scope)); +} + +class _SwitchDefaultCaseBuilder extends Object + with HasStatementsMixin + implements SwitchDefaultCaseBuilder { + @override + AstNode buildAst([Scope scope]) => buildSwitchMember(scope); + + @override + SwitchMember buildSwitchMember([Scope scope]) => + astFactory.switchDefault(null, $default, $colon, buildStatements()); +} diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index 84fbc0631..88687a65f 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -23,6 +23,12 @@ final Token $at = new Token(TokenType.AT, 0); /// The `await` token. final Token $await = new StringToken(TokenType.KEYWORD, 'await', 0); +/// The `break` token. +final Token $break = new KeywordToken(Keyword.BREAK, 0); + +/// The `case` token. +final Token $case = new KeywordToken(Keyword.CASE, 0); + /// The `class` token. final Token $class = new KeywordToken(Keyword.CLASS, 0); @@ -41,6 +47,9 @@ final Token $colon = new Token(TokenType.COLON, 0); /// The `const` token. final Token $const = new KeywordToken(Keyword.CONST, 0); +/// The `default` token. +final Token $default = new KeywordToken(Keyword.DEFAULT, 0); + /// The `deferred` token. final Token $deferred = new KeywordToken(Keyword.DEFERRED, 0); @@ -77,6 +86,9 @@ final Token $gt = new Token(TokenType.GT, 0); /// The `if` token. final Token $if = new KeywordToken(Keyword.IF, 0); +/// The `switch` keyword. +final Token $switch = new KeywordToken(Keyword.SWITCH, 0); + /// The `super` keyword. final Token $super = new KeywordToken(Keyword.SUPER, 0); diff --git a/pkgs/code_builder/test/builders/break_test.dart b/pkgs/code_builder/test/builders/break_test.dart new file mode 100644 index 000000000..de03eec99 --- /dev/null +++ b/pkgs/code_builder/test/builders/break_test.dart @@ -0,0 +1,13 @@ +// 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. + +import 'package:code_builder/src/builders/statement/break.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit a break statement', () { + expect(breakStatement, equalsSource('break;')); + }); +} diff --git a/pkgs/code_builder/test/builders/switch_test.dart b/pkgs/code_builder/test/builders/switch_test.dart new file mode 100644 index 000000000..daf50a63c --- /dev/null +++ b/pkgs/code_builder/test/builders/switch_test.dart @@ -0,0 +1,56 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/src/builders/statement/switch.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +void main() { + test('should emit an empty switch statement', () { + expect(switchStatement(reference('foo')), equalsSource(''' + switch (foo) {} + ''')); + }); + + test('should emit cases', () { + expect( + switchStatement(reference('foo'), cases: [ + switchCase(literal('bar'), [literal('baz').asReturn()]), + switchCase(literal(42) * literal(5), [ + reference('math') + .call([literal(24) + reference('three')]).asReturn() + ]) + ]), + equalsSource(''' + switch (foo) { + case 'bar': + return 'baz'; + case 42 * 5: + return math(24 + three); + } + ''')); + }); + + test('should emit default case if given', () { + expect( + switchStatement(reference('foo'), + cases: [ + switchCase(literal('bar'), [ + reference('print').call([literal('baz')]), + breakStatement + ]) + ], + defaultCase: switchDefault([literal(null).asReturn()])), + equalsSource(''' + switch(foo) { + case 'bar': + print('baz'); + break; + default: + return null; + } + ''')); + }); +} From 57233fb71a9a6915bce48ec88067dc1ebeb8fdd1 Mon Sep 17 00:00:00 2001 From: Andrew Lorenzen Date: Tue, 10 Jan 2017 17:58:28 -0800 Subject: [PATCH 029/271] Fix type discrepancy between toTyped() and _TypedReferenceBuilder (dart-lang/code_builder#63) --- pkgs/code_builder/lib/src/builders/reference.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/lib/src/builders/reference.dart b/pkgs/code_builder/lib/src/builders/reference.dart index 5e771ad0b..612201341 100644 --- a/pkgs/code_builder/lib/src/builders/reference.dart +++ b/pkgs/code_builder/lib/src/builders/reference.dart @@ -90,7 +90,8 @@ class ReferenceBuilder extends Object /// // List /// reference('List').toTyped([reference('String')]) ReferenceBuilder toTyped(Iterable genericTypes) { - return new _TypedReferenceBuilder(genericTypes, _name, _importFrom); + return new _TypedReferenceBuilder( + genericTypes.toList(), _name, _importFrom); } } From dce287a665427eaaf0ca4e1bc06bcd02fd67ebce Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 10 Jan 2017 20:14:37 -0800 Subject: [PATCH 030/271] Add support for raw builders (dart-lang/code_builder#57) --- pkgs/code_builder/CHANGELOG.md | 9 ++++++ .../lib/src/builders/expression.dart | 4 +++ .../lib/src/builders/expression/raw.dart | 28 ++++++++++++++++++ .../lib/src/builders/statement.dart | 3 ++ .../lib/src/builders/statement/raw.dart | 29 +++++++++++++++++++ pkgs/code_builder/pubspec.yaml | 3 +- .../test/builders/expression_test.dart | 14 +++++++++ .../test/builders/statement_test.dart | 13 +++++++++ 8 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 pkgs/code_builder/lib/src/builders/expression/raw.dart create mode 100644 pkgs/code_builder/lib/src/builders/statement/raw.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index be412e6e3..381b2aae4 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,12 @@ +## 1.0.0-beta+1 + +- Add support for `switch` statements +- Add support for a raw expression and statement + - `new ExpressionBuilder.raw(...)` + - `new StatemnetBuilder.raw(...)` + +This should help cover any cases not covered with builders today. + ## 1.0.0-beta - Add support for `async`, `sync`, `sync*` functions diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index 4a0d4e0b2..5e086e2c7 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -12,6 +12,7 @@ import 'package:code_builder/src/builders/method.dart'; import 'package:code_builder/src/builders/parameter.dart'; import 'package:code_builder/src/builders/reference.dart'; import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/expression/raw.dart'; import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/builders/statement/if.dart'; import 'package:code_builder/src/builders/statement/while.dart'; @@ -298,6 +299,9 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { /// Builds an [Expression] AST when [buildExpression] is invoked. abstract class ExpressionBuilder implements AstBuilder, StatementBuilder, ValidParameterMember { + /// Create an expression builder that parses and emits a [raw] expression. + factory ExpressionBuilder.raw(String raw(Scope scope)) = RawExpressionBuilder; + /// Returns as an [ExpressionBuilder] multiplying by [other]. ExpressionBuilder operator *(ExpressionBuilder other); diff --git a/pkgs/code_builder/lib/src/builders/expression/raw.dart b/pkgs/code_builder/lib/src/builders/expression/raw.dart new file mode 100644 index 000000000..1dff88564 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/raw.dart @@ -0,0 +1,28 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/src/builders/expression.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:func/func.dart'; + +class RawExpressionBuilder extends Object + with AbstractExpressionMixin, TopLevelMixin + implements ExpressionBuilder { + final Func1 _raw; + + RawExpressionBuilder(this._raw); + + @override + AstNode buildAst([Scope scope]) { + FunctionDeclaration d = + parseCompilationUnit('main() => ${_raw(scope)};').declarations.first; + ExpressionFunctionBody f = d.functionExpression.body; + return f.expression; + } + + @override + Expression buildExpression([Scope scope]) => buildAst(scope); +} diff --git a/pkgs/code_builder/lib/src/builders/statement.dart b/pkgs/code_builder/lib/src/builders/statement.dart index b18c11a6e..9c36211cd 100644 --- a/pkgs/code_builder/lib/src/builders/statement.dart +++ b/pkgs/code_builder/lib/src/builders/statement.dart @@ -7,6 +7,7 @@ import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/src/builders/method.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement/if.dart'; +import 'package:code_builder/src/builders/statement/raw.dart'; import 'package:code_builder/src/tokens.dart'; export 'package:code_builder/src/builders/statement/break.dart' @@ -82,6 +83,8 @@ abstract class StatementBuilder ValidIfStatementMember, ValidConstructorMember, ValidMethodMember { + factory StatementBuilder.raw(String raw(Scope scope)) = RawStatementBuilder; + /// Returns an [Statement] AST representing the builder. Statement buildStatement([Scope scope]); } diff --git a/pkgs/code_builder/lib/src/builders/statement/raw.dart b/pkgs/code_builder/lib/src/builders/statement/raw.dart new file mode 100644 index 000000000..ed489d03a --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/statement/raw.dart @@ -0,0 +1,29 @@ +// 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. + +import 'package:analyzer/analyzer.dart'; +import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; +import 'package:func/func.dart'; + +class RawStatementBuilder implements StatementBuilder { + final Func1 _raw; + + const RawStatementBuilder(this._raw); + + @override + AstNode buildAst([Scope scope]) { + FunctionDeclaration d = + parseCompilationUnit('raw() { ${_raw(scope)} }').declarations.first; + BlockFunctionBody f = d.functionExpression.childEntities.elementAt(1); + Block b = f.childEntities.first; + return b.statements.first; + } + + @override + Statement buildStatement([Scope scope]) => buildAst(scope); + + @override + CompilationUnitMember buildTopLevelAst([Scope scope]) => buildAst(scope); +} diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 6f46486e3..3db2f2382 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-beta +version: 1.0.0-beta+1 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -10,6 +10,7 @@ environment: dependencies: analyzer: '>=0.29.1 <0.30.0' dart_style: ^0.2.10 + func: ^0.1.0 matcher: ^0.12.0+2 meta: ^1.0.2 diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 0510f2088..0eae4bb84 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -332,4 +332,18 @@ void main() { '''), ); }); + + test('raw expression', () { + expect( + lambda( + 'main', + new ExpressionBuilder.raw( + (scope) => '5 + 3 + ${scope.identifier('q')}', + ), + ), + equalsSource(r''' + main() => 5 + 3 + q; + '''), + ); + }); } diff --git a/pkgs/code_builder/test/builders/statement_test.dart b/pkgs/code_builder/test/builders/statement_test.dart index 7f0384b2b..ca6f91277 100644 --- a/pkgs/code_builder/test/builders/statement_test.dart +++ b/pkgs/code_builder/test/builders/statement_test.dart @@ -139,4 +139,17 @@ void main() { ''')); }); }); + + test('raw statement', () { + expect( + method('main', [ + new StatementBuilder.raw((scope) => 'print(${scope.identifier('q')});'), + ]), + equalsSource(r''' + main() { + print(q); + } + '''), + ); + }); } From f95c5b70c05a4ea1477932875579235ee56e4d35 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 10 Jan 2017 21:32:31 -0800 Subject: [PATCH 031/271] Only run using stable Dart SDK on Travis right now (dart-lang/code_builder#60) --- pkgs/code_builder/.travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index 08997a645..fcb7af47c 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -1,7 +1,8 @@ language: dart dart: - - dev + # pkg/test is currently failing @ dev + # - dev - stable script: ./tool/presubmit.sh From 2e0eb5907d69a3342f5429fa66398773a901d560 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 11 Jan 2017 10:15:07 -0800 Subject: [PATCH 032/271] Close a bunch of open issues for 1.0.0-beta+1 (dart-lang/code_builder#64) * Close a bunch of open issues. * Update CHANGELOG. --- pkgs/code_builder/CHANGELOG.md | 15 ++++ pkgs/code_builder/lib/src/builders/class.dart | 13 ++- .../lib/src/builders/expression.dart | 21 +++-- .../lib/src/builders/expression/assign.dart | 7 +- .../lib/src/builders/expression/await.dart | 2 +- .../lib/src/builders/expression/index.dart | 25 ++++++ .../lib/src/builders/expression/yield.dart | 2 +- .../lib/src/builders/statement/switch.dart | 85 ++++++++++++------- pkgs/code_builder/lib/src/builders/type.dart | 16 +++- .../test/builders/expression_test.dart | 24 +++++- .../test/builders/method_test.dart | 4 +- .../code_builder/test/builders/type_test.dart | 18 ++++ 12 files changed, 176 insertions(+), 56 deletions(-) create mode 100644 pkgs/code_builder/lib/src/builders/expression/index.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 381b2aae4..32c4fef25 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -7,6 +7,21 @@ This should help cover any cases not covered with builders today. +- Allow referring to a `ClassBuilder` and `TypeBuilder` as an expression +- Add support for accessing the index `[]` operator on an expression + +### BREAKING CHANGES + +- Changed `ExpressionBuilder.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: + +```dart +literal(true).asAssign(reference('flag')) +``` + +... emits `flag = true`. + ## 1.0.0-beta - Add support for `async`, `sync`, `sync*` functions diff --git a/pkgs/code_builder/lib/src/builders/class.dart b/pkgs/code_builder/lib/src/builders/class.dart index ea1794caa..9217ab5b7 100644 --- a/pkgs/code_builder/lib/src/builders/class.dart +++ b/pkgs/code_builder/lib/src/builders/class.dart @@ -6,10 +6,13 @@ import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/standard_ast_factory.dart'; import 'package:code_builder/dart/core.dart'; import 'package:code_builder/src/builders/annotation.dart'; +import 'package:code_builder/src/builders/expression.dart'; import 'package:code_builder/src/builders/field.dart'; import 'package:code_builder/src/builders/file.dart'; import 'package:code_builder/src/builders/method.dart'; +import 'package:code_builder/src/builders/reference.dart'; import 'package:code_builder/src/builders/shared.dart'; +import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/builders/type.dart'; import 'package:code_builder/src/tokens.dart'; @@ -133,7 +136,7 @@ abstract class ClassBuilder abstract class ValidClassMember implements AstBuilder {} class _ClassBuilderImpl extends Object - with AbstractTypeBuilderMixin, HasAnnotationsMixin + with AbstractExpressionMixin, AbstractTypeBuilderMixin, HasAnnotationsMixin implements ClassBuilder { final _constructors = []; final _fields = {}; @@ -265,6 +268,14 @@ class _ClassBuilderImpl extends Object ImportBuilder toImportBuilder({bool deferred: false, String prefix}) { throw new UnsupportedError('Not supported for ClassBuilder'); } + + @override + Expression buildExpression([Scope scope]) { + return reference(_name).buildExpression(scope); + } + + @override + CompilationUnitMember buildTopLevelAst([Scope scope]) => buildClass(scope); } class _TypeNameWrapper implements ValidClassMember { diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index 5e086e2c7..b63fe0697 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -23,6 +23,7 @@ part 'expression/assert.dart'; part 'expression/assign.dart'; part 'expression/await.dart'; part 'expression/cascade.dart'; +part 'expression/index.dart'; part 'expression/invocation.dart'; part 'expression/negate.dart'; part 'expression/operators.dart'; @@ -146,6 +147,11 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { ); } + @override + ExpressionBuilder operator [](ExpressionBuilder index) { + return new _IndexExpression(this, index); + } + @override ExpressionBuilder and(ExpressionBuilder other) { return new _AsBinaryExpression( @@ -160,11 +166,10 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { @override StatementBuilder asAssign( - String variable, { - ExpressionBuilder target, + ExpressionBuilder target, { bool nullAware: false, }) => - new _AsAssign(this, variable, nullAware, target); + new _AsAssign(this, nullAware, target); @override ExpressionBuilder asAwait() => new _AsAwait(this); @@ -320,18 +325,18 @@ abstract class ExpressionBuilder /// Returns as an [ExpressionBuilder] `>` by [other]. ExpressionBuilder operator >(ExpressionBuilder other); + /// Returns as an [ExpressionBuilder] reading the `[]` property with [index]. + ExpressionBuilder operator [](ExpressionBuilder index); + /// Returns as an [ExpressionBuilder] `&&` [other]. ExpressionBuilder and(ExpressionBuilder other); /// Return as a [StatementBuilder] that `assert`s this expression. StatementBuilder asAssert(); - /// Returns as a [StatementBuilder] that assigns to an existing [variable]. - /// - /// If [target] is specified, determined to be `{target}.{variable}`. + /// Returns as a [StatementBuilder] that assigns to [target]. StatementBuilder asAssign( - String variable, { - ExpressionBuilder target, + ExpressionBuilder target, { bool nullAware, }); diff --git a/pkgs/code_builder/lib/src/builders/expression/assign.dart b/pkgs/code_builder/lib/src/builders/expression/assign.dart index 2f9c72aa1..20b4dc90f 100644 --- a/pkgs/code_builder/lib/src/builders/expression/assign.dart +++ b/pkgs/code_builder/lib/src/builders/expression/assign.dart @@ -5,12 +5,11 @@ part of code_builder.src.builders.expression; class _AsAssign extends AbstractExpressionMixin with TopLevelMixin { - final String _name; final bool _nullAware; final ExpressionBuilder _value; final ExpressionBuilder _target; - _AsAssign(this._value, this._name, this._nullAware, this._target); + _AsAssign(this._value, this._nullAware, this._target); @override AstNode buildAst([Scope scope]) => buildExpression(scope); @@ -18,9 +17,7 @@ class _AsAssign extends AbstractExpressionMixin with TopLevelMixin { @override Expression buildExpression([Scope scope]) { return astFactory.assignmentExpression( - _target != null - ? _target.property(_name).buildExpression(scope) - : stringIdentifier(_name), + _target.buildExpression(scope), _nullAware ? $nullAwareEquals : $equals, _value.buildExpression(scope), ); diff --git a/pkgs/code_builder/lib/src/builders/expression/await.dart b/pkgs/code_builder/lib/src/builders/expression/await.dart index 5b15fabb0..011cf45be 100644 --- a/pkgs/code_builder/lib/src/builders/expression/await.dart +++ b/pkgs/code_builder/lib/src/builders/expression/await.dart @@ -14,7 +14,7 @@ class _AsAwait extends AbstractExpressionMixin with TopLevelMixin { @override Expression buildExpression([Scope scope]) { - return new AwaitExpression( + return astFactory.awaitExpression( $await, _expression.buildExpression(scope), ); diff --git a/pkgs/code_builder/lib/src/builders/expression/index.dart b/pkgs/code_builder/lib/src/builders/expression/index.dart new file mode 100644 index 000000000..2591e2c40 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/index.dart @@ -0,0 +1,25 @@ +// 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. + +part of code_builder.src.builders.expression; + +class _IndexExpression extends AbstractExpressionMixin with TopLevelMixin { + final ExpressionBuilder _target; + final ExpressionBuilder _index; + + _IndexExpression(this._target, this._index); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return astFactory.indexExpressionForTarget( + _target.buildExpression(scope), + $openBracket, + _index.buildExpression(scope), + $closeBracket, + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/yield.dart b/pkgs/code_builder/lib/src/builders/expression/yield.dart index 98742615d..decbcfb35 100644 --- a/pkgs/code_builder/lib/src/builders/expression/yield.dart +++ b/pkgs/code_builder/lib/src/builders/expression/yield.dart @@ -15,7 +15,7 @@ class _AsYield extends TopLevelMixin implements StatementBuilder { @override Statement buildStatement([Scope scope]) { - return new YieldStatement( + return astFactory.yieldStatement( $yield, _isStar ? $star : null, _expression.buildExpression(scope), diff --git a/pkgs/code_builder/lib/src/builders/statement/switch.dart b/pkgs/code_builder/lib/src/builders/statement/switch.dart index e2bc1bf63..f8e49cb85 100644 --- a/pkgs/code_builder/lib/src/builders/statement/switch.dart +++ b/pkgs/code_builder/lib/src/builders/statement/switch.dart @@ -10,28 +10,35 @@ import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/tokens.dart'; /// Short-hand syntax for `new SwitchCaseBuilder(...)`. -SwitchCaseBuilder switchCase(ExpressionBuilder condition, - [Iterable statements = const []]) => +SwitchCaseBuilder switchCase( + ExpressionBuilder condition, [ + Iterable statements = const [], +]) => new SwitchCaseBuilder(condition)..addStatements(statements ?? []); /// Short-hand syntax for `new SwitchDefaultCaseBuilder(...)`. -SwitchDefaultCaseBuilder switchDefault( - [Iterable statements = const []]) => +SwitchDefaultCaseBuilder switchDefault([ + Iterable statements = const [], +]) => new SwitchDefaultCaseBuilder()..addStatements(statements ?? []); /// Short-hand syntax for `new SwitchStatementBuilder(...)`. -SwitchStatementBuilder switchStatement(ExpressionBuilder expression, - {Iterable cases: const [], - SwitchDefaultCaseBuilder defaultCase}) => +SwitchStatementBuilder switchStatement( + ExpressionBuilder expression, { + Iterable cases: const [], + SwitchDefaultCaseBuilder defaultCase, +}) => new SwitchStatementBuilder(expression) ..setDefaultCase(defaultCase) ..addCases(cases ?? []); -/// Represents an [ExpressionBuilder] and a series of [SwitchCaseBuilder]s as a switch statement AST. +/// Represents an [ExpressionBuilder] switches as an AST. abstract class SwitchStatementBuilder implements StatementBuilder { /// Creates a new [SwitchStatementBuilder]. - factory SwitchStatementBuilder(ExpressionBuilder expression, - [Iterable members = const []]) => + factory SwitchStatementBuilder( + ExpressionBuilder expression, [ + Iterable members = const [], + ]) => new _SwitchStatementBuilder(expression, members); /// Adds a [switchCase] to the builder. @@ -47,16 +54,15 @@ abstract class SwitchStatementBuilder implements StatementBuilder { void setDefaultCase(SwitchDefaultCaseBuilder defaultCase); } -/// A marker interface for an AST that could be added to [SwitchStatementBuilder]. +/// A marker interface for an AST usable within a [SwitchStatementBuilder]. /// /// This can be either a [SwitchCaseBuilder] or a [SwitchDefaultCaseBuilder]. abstract class ValidSwitchMember {} -/// Represents an [ExpressionBuilder] and a series of [Statement]s as a switch case AST. +/// Represents an [ExpressionBuilder] and statements as a switch case AST. abstract class SwitchCaseBuilder implements HasStatements, ValidSwitchMember { /// Creates a new [SwitchCaseBuilder]. - factory SwitchCaseBuilder(ExpressionBuilder condition) => - new _SwitchCaseBuilder(condition); + factory SwitchCaseBuilder(ExpressionBuilder condition) = _SwitchCaseBuilder; /// Returns an [SwitchMember] AST representing the builder. SwitchMember buildSwitchMember([Scope scope]); @@ -65,7 +71,7 @@ abstract class SwitchCaseBuilder implements HasStatements, ValidSwitchMember { /// Represents a series of [Statement]s as a default switch case AST. abstract class SwitchDefaultCaseBuilder implements HasStatements, ValidSwitchMember { - factory SwitchDefaultCaseBuilder() => new _SwitchDefaultCaseBuilder(); + factory SwitchDefaultCaseBuilder() = _SwitchDefaultCaseBuilder; /// Returns an [SwitchMember] AST representing the builder. SwitchMember buildSwitchMember([Scope scope]); @@ -78,12 +84,16 @@ class _SwitchStatementBuilder extends Object final List _cases = []; SwitchDefaultCaseBuilder _defaultCase; - _SwitchStatementBuilder(this._expression, - [Iterable members = const []]) { + _SwitchStatementBuilder( + this._expression, [ + Iterable members = const [], + ]) { for (final member in members) { - if (member is SwitchDefaultCaseBuilder) + if (member is SwitchDefaultCaseBuilder) { _defaultCase = member; - else if (member is SwitchCaseBuilder) _cases.add(member); + } else if (member is SwitchCaseBuilder) { + _cases.add(member); + } } } @@ -105,18 +115,18 @@ class _SwitchStatementBuilder extends Object @override SwitchStatement buildSwitchStatement([Scope scope]) { var members = _cases.map((c) => c.buildSwitchMember(scope)).toList(); - - if (_defaultCase != null) + if (_defaultCase != null) { members.add(_defaultCase.buildSwitchMember(scope)); - + } return astFactory.switchStatement( - $switch, - $openBracket, - _expression.buildExpression(), - $closeParen, - $openBracket, - members, - $closeBracket); + $switch, + $openBracket, + _expression.buildExpression(), + $closeParen, + $openBracket, + members, + $closeBracket, + ); } @override @@ -134,8 +144,13 @@ class _SwitchCaseBuilder extends Object AstNode buildAst([Scope scope]) => buildSwitchMember(scope); @override - SwitchMember buildSwitchMember([Scope scope]) => astFactory.switchCase(null, - $case, _condition.buildExpression(), $colon, buildStatements(scope)); + SwitchMember buildSwitchMember([Scope scope]) => astFactory.switchCase( + null, + $case, + _condition.buildExpression(), + $colon, + buildStatements(scope), + ); } class _SwitchDefaultCaseBuilder extends Object @@ -145,6 +160,10 @@ class _SwitchDefaultCaseBuilder extends Object AstNode buildAst([Scope scope]) => buildSwitchMember(scope); @override - SwitchMember buildSwitchMember([Scope scope]) => - astFactory.switchDefault(null, $default, $colon, buildStatements()); + SwitchMember buildSwitchMember([Scope scope]) => astFactory.switchDefault( + null, + $default, + $colon, + buildStatements(), + ); } diff --git a/pkgs/code_builder/lib/src/builders/type.dart b/pkgs/code_builder/lib/src/builders/type.dart index 851462bc4..7653c4c97 100644 --- a/pkgs/code_builder/lib/src/builders/type.dart +++ b/pkgs/code_builder/lib/src/builders/type.dart @@ -81,8 +81,12 @@ abstract class AbstractTypeBuilderMixin { /// Lazily builds an [TypeName] AST when [buildType] is invoked. class TypeBuilder extends Object - with AbstractTypeBuilderMixin - implements AstBuilder, ValidMethodMember, ValidParameterMember { + with AbstractExpressionMixin, AbstractTypeBuilderMixin, TopLevelMixin + implements + AstBuilder, + ExpressionBuilder, + ValidMethodMember, + ValidParameterMember { final List _generics; final String _importFrom; final String _name; @@ -150,4 +154,12 @@ class TypeBuilder extends Object prefix: prefix, )..show(_name); } + + @override + Expression buildExpression([Scope scope]) { + if (_generics.isNotEmpty) { + throw new StateError('Cannot refer to a type with generic parameters'); + } + return reference(_name, _importFrom).buildExpression(scope); + } } diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 0eae4bb84..99c6670bd 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -76,7 +76,7 @@ void main() { test('should emit an assign expression', () { expect( - literal(true).asAssign('flag'), + literal(true).asAssign(reference('flag')), equalsSource(r''' flag = true '''), @@ -85,7 +85,7 @@ void main() { test('should emit an assign expression with a null aware', () { expect( - literal(true).asAssign('flag', nullAware: true), + literal(true).asAssign(reference('flag'), nullAware: true), equalsSource(r''' flag ??= true '''), @@ -268,6 +268,24 @@ void main() { ); }); + test('should return as an index expression', () { + expect( + literal([literal(1), literal(2), literal(3)])[literal(0)], + equalsSource(r''' + [1, 2, 3][0] + '''), + ); + }); + + test('should return as an index expression assignment', () { + expect( + reference('value').asAssign(reference('list')[reference('index')]), + equalsSource(r''' + list[index] = value + '''), + ); + }); + test('should emit a top-level field declaration', () { expect( new LibraryBuilder()..addMember(literal(false).asConst('foo')), @@ -283,7 +301,7 @@ void main() { .cascade((c) => [ c.invoke('doThis', []), c.invoke('doThat', []), - reference('Bar').newInstance([]).asAssign('bar', target: c), + reference('Bar').newInstance([]).asAssign(c.property('bar')), ]) .asStatement(), equalsSource(r''' diff --git a/pkgs/code_builder/test/builders/method_test.dart b/pkgs/code_builder/test/builders/method_test.dart index 8a6c7b9bf..3c2836f75 100644 --- a/pkgs/code_builder/test/builders/method_test.dart +++ b/pkgs/code_builder/test/builders/method_test.dart @@ -160,7 +160,7 @@ void main() { test('should emit a setter', () { expect( setter('name', parameter('name', [lib$core.String]), [ - (reference('name') + literal('!')).asAssign('_name'), + (reference('name') + literal('!')).asAssign(reference('_name')), ]), equalsSource(r''' set name(String name) { @@ -241,7 +241,7 @@ void main() { ..addStatement(reference('value').invoke( 'join', [literal(' - ')], - ).asAssign('title'))) + ).asAssign(reference('title')))) .asStatement(), equalsSource(r''' (value) { diff --git a/pkgs/code_builder/test/builders/type_test.dart b/pkgs/code_builder/test/builders/type_test.dart index 16c9f4d70..436edf0f7 100644 --- a/pkgs/code_builder/test/builders/type_test.dart +++ b/pkgs/code_builder/test/builders/type_test.dart @@ -113,4 +113,22 @@ void main() { ); }); }); + + test('emits as a Type to be used as an expression', () { + expect( + lambda('foo', new TypeBuilder('Foo')), + equalsSource(r''' + foo() => Foo; + '''), + ); + }); + + test('throws when a Type references generics for an expression', () { + expect( + () => new TypeBuilder('Foo', genericTypes: [ + new TypeBuilder('Bar'), + ]).buildExpression(), + throwsStateError, + ); + }); } From a688a0ce0691dd276e91a374537b9c355f071c38 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 11 Jan 2017 11:18:03 -0800 Subject: [PATCH 033/271] Update class.dart (dart-lang/code_builder#67) Remove an unused import. --- pkgs/code_builder/lib/src/builders/class.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/code_builder/lib/src/builders/class.dart b/pkgs/code_builder/lib/src/builders/class.dart index 9217ab5b7..c3aa9ecb7 100644 --- a/pkgs/code_builder/lib/src/builders/class.dart +++ b/pkgs/code_builder/lib/src/builders/class.dart @@ -12,7 +12,6 @@ import 'package:code_builder/src/builders/file.dart'; import 'package:code_builder/src/builders/method.dart'; import 'package:code_builder/src/builders/reference.dart'; import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/builders/type.dart'; import 'package:code_builder/src/tokens.dart'; From ae77038eb4de8d040c8ded7bdb362e7ab9220dca Mon Sep 17 00:00:00 2001 From: Yegor Date: Wed, 18 Jan 2017 10:54:41 -0800 Subject: [PATCH 034/271] rename MethodModifier constant names (dart-lang/code_builder#68) --- pkgs/code_builder/CHANGELOG.md | 6 ++++++ pkgs/code_builder/lib/src/builders/method.dart | 7 ++++--- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/builders/method_test.dart | 6 +++--- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 32c4fef25..5f26dbe85 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.0.0-beta+2 + +- BREAKING CHANGE: `MethodModifier.async`, `MethodModifier.asyncStar` and + `MethodModifier.syncStar` are now `MethodModifier.asAsync`, + `MethodModifier.asAsyncStar` and `MethodModifier.asSyncStar` + ## 1.0.0-beta+1 - Add support for `switch` statements diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index 44e747369..a25edbe3a 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -34,9 +34,10 @@ ConstructorBuilder constructorNamed( /// Various types of modifiers for methods. class MethodModifier implements ValidMethodMember { - static const MethodModifier async = const MethodModifier._('async', false); - static const MethodModifier asyncStar = const MethodModifier._('async', true); - static const MethodModifier syncStar = const MethodModifier._('sync', true); + static const MethodModifier asAsync = const MethodModifier._('async', false); + static const MethodModifier asAsyncStar = + const MethodModifier._('async', true); + static const MethodModifier asSyncStar = const MethodModifier._('sync', true); final String _keyword; diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 3db2f2382..b14803149 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-beta+1 +version: 1.0.0-beta+2 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/method_test.dart b/pkgs/code_builder/test/builders/method_test.dart index 3c2836f75..8c89ee02b 100644 --- a/pkgs/code_builder/test/builders/method_test.dart +++ b/pkgs/code_builder/test/builders/method_test.dart @@ -172,7 +172,7 @@ void main() { test('should emit an async method', () { expect( - method('fetch', [MethodModifier.async]), + method('fetch', [MethodModifier.asAsync]), equalsSource(r''' fetch() async {} '''), @@ -181,7 +181,7 @@ void main() { test('should emit an async* method', () { expect( - method('fetch', [MethodModifier.asyncStar]), + method('fetch', [MethodModifier.asAsyncStar]), equalsSource(r''' fetch() async* {} '''), @@ -190,7 +190,7 @@ void main() { test('should emit an sync* method', () { expect( - method('fetch', [MethodModifier.syncStar]), + method('fetch', [MethodModifier.asSyncStar]), equalsSource(r''' fetch() sync* {} '''), From 2cd87a9cd1ca9a23ce4299c9002abe76e1114614 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 31 Jan 2017 13:35:13 -0800 Subject: [PATCH 035/271] Add support for generic types in methods and `as` cast (dart-lang/code_builder#70) * Add support for generic types and as cast * Update CHANGELOG and pubspec. * Rename name: to constructor: --- pkgs/code_builder/CHANGELOG.md | 65 ++++++++++++++++++- pkgs/code_builder/lib/dart/core.dart | 3 + .../lib/src/builders/expression.dart | 35 ++++++---- .../lib/src/builders/expression/cast.dart | 24 +++++++ .../src/builders/expression/invocation.dart | 30 ++++++--- pkgs/code_builder/lib/src/builders/type.dart | 48 +++++--------- .../lib/src/builders/type/new_instance.dart | 42 ++++++++---- pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/expression_test.dart | 42 +++++++++++- .../code_builder/test/builders/type_test.dart | 10 +-- pkgs/code_builder/test/e2e_test.dart | 4 +- 11 files changed, 231 insertions(+), 74 deletions(-) create mode 100644 pkgs/code_builder/lib/src/builders/expression/cast.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 5f26dbe85..b98c0d2d4 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,8 +1,67 @@ +## 1.0.0-beta+3 + +- Added support for `genericTypes` parameter for `ExpressionBuilder#invoke`: + +```dart +expect( + explicitThis.invoke('doThing', [literal(true)], genericTypes: [ + lib$core.bool, + ]), + equalsSource(r''' + this.doThing(true) + '''), +); +``` + +- Added a `castAs` method to `ExpressionBuilder`: + +```dart +expect( + literal(1.0).castAs(lib$core.num), + equalsSource(r''' + 1.0 as num + '''), +); +``` + +### BREAKING CHANGES + +- Removed `namedNewInstance` and `namedConstInstance`, replaced with `constructor: `: + +```dart +expect( + reference('Foo').newInstance([], constructor: 'other'), + equalsSource(r''' + new Foo.other() + '''), +); +``` + +- Renamed `named` parameter to `namedArguments`: + +```dart +expect( + reference('doThing').call( + [literal(true)], + namedArguments: { + 'otherFlag': literal(false), + }, + ), + equalsSource(r''' + doThing(true, otherFlag: false) + '''), +); +``` + ## 1.0.0-beta+2 -- BREAKING CHANGE: `MethodModifier.async`, `MethodModifier.asyncStar` and - `MethodModifier.syncStar` are now `MethodModifier.asAsync`, - `MethodModifier.asAsyncStar` and `MethodModifier.asSyncStar` +### BREAKING CHANGES + +Avoid creating symbols that can collide with the Dart language: + +- `MethodModifier.async` -> `MethodModifier.asAsync` +- `MethodModifier.asyncStar` -> `MethodModifier.asAsyncStar` +- `MethodModifier.syncStar` -> `MethodModifier.asSyncStar` ## 1.0.0-beta+1 diff --git a/pkgs/code_builder/lib/dart/core.dart b/pkgs/code_builder/lib/dart/core.dart index fbbe89f03..5066e2cfe 100644 --- a/pkgs/code_builder/lib/dart/core.dart +++ b/pkgs/code_builder/lib/dart/core.dart @@ -53,6 +53,9 @@ class DartCore { /// References [dart_core.int]. final ReferenceBuilder int = _ref('int'); + /// References [dart_core.num]. + final ReferenceBuilder num = _ref('num'); + /// References [dart_core.AbstractClassInstantiationError]. final ReferenceBuilder AbstractClassInstantiationError = _ref('AbstractClassInstantiationError'); diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index b63fe0697..213c7447d 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -23,6 +23,7 @@ part 'expression/assert.dart'; part 'expression/assign.dart'; part 'expression/await.dart'; part 'expression/cascade.dart'; +part 'expression/cast.dart'; part 'expression/index.dart'; part 'expression/invocation.dart'; part 'expression/negate.dart'; @@ -216,15 +217,18 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { @override InvocationBuilder call( - Iterable positionalArguments, [ - Map namedArguments = const {}, - ]) { + Iterable positionalArguments, { + Map namedArguments: const {}, + }) { final invocation = new InvocationBuilder._(this); positionalArguments.forEach(invocation.addPositionalArgument); namedArguments.forEach(invocation.addNamedArgument); return invocation; } + @override + ExpressionBuilder castAs(TypeBuilder type) => new _AsCast(this, type); + @override ExpressionBuilder cascade( Iterable create(ExpressionBuilder self), @@ -261,10 +265,15 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { @override InvocationBuilder invoke( String method, - Iterable positionalArguments, [ - Map namedArguments = const {}, - ]) { - final invocation = new InvocationBuilder._on(this, method); + Iterable positionalArguments, { + Iterable genericTypes: const [], + Map namedArguments: const {}, + }) { + final invocation = new InvocationBuilder._on( + this, + method, + genericTypes.toList(), + ); positionalArguments.forEach(invocation.addPositionalArgument); namedArguments.forEach(invocation.addNamedArgument); return invocation; @@ -381,9 +390,12 @@ abstract class ExpressionBuilder /// Returns as an [InvocationBuilder] with arguments added. InvocationBuilder call( - Iterable positionalArguments, [ + Iterable positionalArguments, { Map namedArguments, - ]); + }); + + /// Returns the expression casted as [type]. + ExpressionBuilder castAs(TypeBuilder type); /// Return as an [ExpressionBuilder] with `..` appended. ExpressionBuilder cascade( @@ -405,9 +417,10 @@ abstract class ExpressionBuilder /// Returns as an [InvocationBuilder] on [method] of this expression. InvocationBuilder invoke( String method, - Iterable positionalArguments, [ + Iterable positionalArguments, { + Iterable genericTypes, Map namedArguments, - ]); + }); /// Returns as an [ExpressionBuilder] negating using the `!` operator. ExpressionBuilder negate(); diff --git a/pkgs/code_builder/lib/src/builders/expression/cast.dart b/pkgs/code_builder/lib/src/builders/expression/cast.dart new file mode 100644 index 000000000..e18ecfaeb --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/cast.dart @@ -0,0 +1,24 @@ +// 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. + +part of code_builder.src.builders.expression; + +class _AsCast extends TopLevelMixin with AbstractExpressionMixin { + final ExpressionBuilder _target; + final TypeBuilder _type; + + _AsCast(this._target, this._type); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return astFactory.asExpression( + _target.buildExpression(scope), + $as, + _type.buildType(scope), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/expression/invocation.dart b/pkgs/code_builder/lib/src/builders/expression/invocation.dart index 684b21580..2868280b1 100644 --- a/pkgs/code_builder/lib/src/builders/expression/invocation.dart +++ b/pkgs/code_builder/lib/src/builders/expression/invocation.dart @@ -20,10 +20,13 @@ abstract class AbstractInvocationBuilderMixin implements InvocationBuilder { } /// Returns an [ArgumentList] AST. - ArgumentList buildArgumentList([Scope scope]) { + ArgumentList buildArgumentList({ + Scope scope, + }) { final allArguments = []; allArguments.addAll( - _positional.map/**/((e) => e.buildExpression(scope))); + _positional.map/**/((e) => e.buildExpression(scope)), + ); _named.forEach((name, e) { allArguments.add(astFactory.namedExpression( astFactory.label( @@ -51,8 +54,12 @@ abstract class InvocationBuilder return new _FunctionInvocationBuilder(target); } - factory InvocationBuilder._on(ExpressionBuilder target, String method) { - return new _MethodInvocationBuilder(target, method); + factory InvocationBuilder._on( + ExpressionBuilder target, + String method, + List generics, + ) { + return new _MethodInvocationBuilder(target, method, generics); } /// Adds [argument] as a [name]d argument to this method call. @@ -74,7 +81,7 @@ class _FunctionInvocationBuilder extends Object return astFactory.functionExpressionInvocation( _target.buildExpression(scope), null, - buildArgumentList(scope), + buildArgumentList(scope: scope), ); } } @@ -82,10 +89,11 @@ class _FunctionInvocationBuilder extends Object class _MethodInvocationBuilder extends Object with AbstractInvocationBuilderMixin, AbstractExpressionMixin, TopLevelMixin implements InvocationBuilder { + final List _generics; final String _method; final ExpressionBuilder _target; - _MethodInvocationBuilder(this._target, this._method); + _MethodInvocationBuilder(this._target, this._method, this._generics); @override Expression buildExpression([Scope scope]) { @@ -93,8 +101,14 @@ class _MethodInvocationBuilder extends Object _target.buildExpression(scope), $period, stringIdentifier(_method), - null, - buildArgumentList(scope), + _generics.isNotEmpty + ? new TypeArgumentList( + $openBracket, + _generics.map((t) => t.buildType(scope)).toList(), + $closeBracket, + ) + : null, + buildArgumentList(scope: scope), ); } } diff --git a/pkgs/code_builder/lib/src/builders/type.dart b/pkgs/code_builder/lib/src/builders/type.dart index 7653c4c97..f9136558e 100644 --- a/pkgs/code_builder/lib/src/builders/type.dart +++ b/pkgs/code_builder/lib/src/builders/type.dart @@ -23,42 +23,28 @@ part 'type/new_instance.dart'; abstract class AbstractTypeBuilderMixin { /// Invokes `const` on this type. NewInstanceBuilder constInstance( - Iterable positional, [ - Map named = const {}, - ]) { - final builder = new NewInstanceBuilder._const(this); - _addArguments(builder, positional, named); - return builder; - } - - /// Invokes `const` on this type with a [name]d constructor. - NewInstanceBuilder namedConstInstance( - String name, - Iterable positional, [ - Map named = const {}, - ]) { - final builder = new NewInstanceBuilder._const(this, name); - _addArguments(builder, positional, named); + Iterable positionalArguments, { + String constructor, + Map namedArguments: const {}, + }) { + final builder = new NewInstanceBuilder._const( + this, + constructor: constructor, + ); + _addArguments(builder, positionalArguments, namedArguments); return builder; } /// Invokes `new` on this type. NewInstanceBuilder newInstance( - Iterable positional, [ - Map named = const {}, - ]) { - final builder = new NewInstanceBuilder._new(this); - _addArguments(builder, positional, named); - return builder; - } - - /// Invokes `new` on this type with a [name]d constructor. - NewInstanceBuilder namedNewInstance( - String name, - Iterable positional, [ - Map named = const {}, - ]) { - final builder = new NewInstanceBuilder._new(this, name); + Iterable positional, { + String constructor, + Map named: const {}, + }) { + final builder = new NewInstanceBuilder._new( + this, + constructor: constructor, + ); _addArguments(builder, positional, named); return builder; } diff --git a/pkgs/code_builder/lib/src/builders/type/new_instance.dart b/pkgs/code_builder/lib/src/builders/type/new_instance.dart index 9c48bc80e..0a0441c17 100644 --- a/pkgs/code_builder/lib/src/builders/type/new_instance.dart +++ b/pkgs/code_builder/lib/src/builders/type/new_instance.dart @@ -8,28 +8,44 @@ part of code_builder.src.builders.type; /// /// See [TypeBuilder]: /// - [TypeBuilder.constInstance] -/// - [TypeBuilder.namedConstInstance] /// - [TypeBuilder.newInstance] -/// - [TypeBuilder.namedNewInstance] abstract class NewInstanceBuilder implements AnnotationBuilder, InvocationBuilder { - factory NewInstanceBuilder._const(TypeBuilder type, [String name]) { - return new _NewInvocationBuilderImpl(Keyword.CONST, type, name); + factory NewInstanceBuilder._const( + TypeBuilder type, { + String constructor, + }) { + return new _NewInvocationBuilderImpl( + Keyword.CONST, + type, + constructor, + ); } - factory NewInstanceBuilder._new(TypeBuilder type, [String name]) { - return new _NewInvocationBuilderImpl(Keyword.NEW, type, name); + factory NewInstanceBuilder._new( + TypeBuilder type, { + String constructor, + }) { + return new _NewInvocationBuilderImpl( + Keyword.NEW, + type, + constructor, + ); } } class _NewInvocationBuilderImpl extends Object with AbstractExpressionMixin, AbstractInvocationBuilderMixin, TopLevelMixin implements NewInstanceBuilder { - final String _name; + final String _constructor; final Keyword _keyword; final TypeBuilder _type; - _NewInvocationBuilderImpl(this._keyword, this._type, [this._name]); + _NewInvocationBuilderImpl( + this._keyword, + this._type, + this._constructor, + ); @override Annotation buildAnnotation([Scope scope]) { @@ -37,8 +53,8 @@ class _NewInvocationBuilderImpl extends Object $at, _type.buildType(scope).name, $period, - _name != null ? stringIdentifier(_name) : null, - buildArgumentList(scope), + _constructor != null ? stringIdentifier(_constructor) : null, + buildArgumentList(scope: scope), ); } @@ -48,10 +64,10 @@ class _NewInvocationBuilderImpl extends Object new KeywordToken(_keyword, 0), astFactory.constructorName( _type.buildType(scope), - _name != null ? $period : null, - _name != null ? stringIdentifier(_name) : null, + _constructor != null ? $period : null, + _constructor != null ? stringIdentifier(_constructor) : null, ), - buildArgumentList(scope), + buildArgumentList(scope: scope), ); } } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index b14803149..9ed6f6b62 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-beta+2 +version: 1.0.0-beta+3 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 99c6670bd..571d0b97a 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -159,7 +159,7 @@ void main() { expect( reference('doThing').call( [literal(true)], - { + namedArguments: { 'otherFlag': literal(false), }, ), @@ -178,6 +178,19 @@ void main() { ); }); + test('should call a method on an expression with generic parameters', () { + expect( + explicitThis.invoke('doThing', [ + literal(true) + ], genericTypes: [ + lib$core.bool, + ]), + equalsSource(r''' + this.doThing(true) + '''), + ); + }); + test('should emit an identical() expression', () { expect( literal(true).identical(literal(false)), @@ -313,6 +326,24 @@ void main() { ); }); + test('should emit a newInstance with a named constructor', () { + expect( + reference('Foo').newInstance([], constructor: 'other'), + equalsSource(r''' + new Foo.other() + '''), + ); + }); + + test('should emit a constInstance with a named constructor', () { + expect( + reference('Foo').constInstance([], constructor: 'other'), + equalsSource(r''' + const Foo.other() + '''), + ); + }); + test('should scope on newInstance', () { expect( reference('Foo', 'package:foo/foo.dart').newInstance([]).asReturn(), @@ -364,4 +395,13 @@ void main() { '''), ); }); + + test('should emit casted as another type', () { + expect( + literal(1.0).castAs(lib$core.num), + equalsSource(r''' + 1.0 as num + '''), + ); + }); } diff --git a/pkgs/code_builder/test/builders/type_test.dart b/pkgs/code_builder/test/builders/type_test.dart index 436edf0f7..14383d8ed 100644 --- a/pkgs/code_builder/test/builders/type_test.dart +++ b/pkgs/code_builder/test/builders/type_test.dart @@ -43,9 +43,9 @@ void main() { test('emits a new List.from', () { expect( - lib$core.List.namedNewInstance('from', [ + lib$core.List.newInstance([ literal([1, 2, 3]), - ]), + ], constructor: 'from'), equalsSource(r''' new List.from([1, 2, 3]) '''), @@ -80,10 +80,10 @@ void main() { test('emits a named const constructor as an annotation', () { expect( clazz('Animal', [ - reference('Component').namedConstInstance( - 'stateful', + reference('Component').constInstance( [], - { + constructor: 'stateful', + namedArguments: { 'selector': literal('animal'), }, ), diff --git a/pkgs/code_builder/test/e2e_test.dart b/pkgs/code_builder/test/e2e_test.dart index 9a00f7e2c..7060a1eae 100644 --- a/pkgs/code_builder/test/e2e_test.dart +++ b/pkgs/code_builder/test/e2e_test.dart @@ -88,7 +88,9 @@ void main() { ..addMethod(new MethodBuilder( 'instantiateAndReturnNamedThing', returnType: thingRef, - )..addStatement(thingRef.namedNewInstance('named', []).asReturn()))); + ) + ..addStatement( + thingRef.newInstance([], constructor: 'named').asReturn()))); expect( lib, equalsSource( From 7150070e3cdfc06f1a177149633062096359531d Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 31 Jan 2017 13:54:39 -0800 Subject: [PATCH 036/271] Add code coverage support for travis. (dart-lang/code_builder#71) --- ...meter_builder.dart => parameter_test.dart} | 0 pkgs/code_builder/tool/presubmit.sh | 9 +++++ .../tool/test_all_for_coverage.dart | 33 +++++++++++++++++++ 3 files changed, 42 insertions(+) rename pkgs/code_builder/test/builders/{parameter_builder.dart => parameter_test.dart} (100%) create mode 100644 pkgs/code_builder/tool/test_all_for_coverage.dart diff --git a/pkgs/code_builder/test/builders/parameter_builder.dart b/pkgs/code_builder/test/builders/parameter_test.dart similarity index 100% rename from pkgs/code_builder/test/builders/parameter_builder.dart rename to pkgs/code_builder/test/builders/parameter_test.dart diff --git a/pkgs/code_builder/tool/presubmit.sh b/pkgs/code_builder/tool/presubmit.sh index 364bee71d..2c7a343f3 100755 --- a/pkgs/code_builder/tool/presubmit.sh +++ b/pkgs/code_builder/tool/presubmit.sh @@ -27,3 +27,12 @@ echo "PASSED" set -e pub run test + +# Install dart_coveralls; gather and send coverage data. +if [ "$COVERALLS_TOKEN" ] && [ "$TRAVIS_DART_VERSION" = "stable" ]; then + pub global activate dart_coveralls + pub global run dart_coveralls report \ + --retry 2 \ + --exclude-test-files \ + tool/test_all_for_coverage.dart +fi diff --git a/pkgs/code_builder/tool/test_all_for_coverage.dart b/pkgs/code_builder/tool/test_all_for_coverage.dart new file mode 100644 index 000000000..1cd141266 --- /dev/null +++ b/pkgs/code_builder/tool/test_all_for_coverage.dart @@ -0,0 +1,33 @@ +// 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 '../test/e2e_test.dart' as test_01; +import '../test/scope_test.dart' as test_02; +import '../test/builders/break_test.dart' as test_03; +import '../test/builders/class_test.dart' as test_04; +import '../test/builders/expression_test.dart' as test_05; +import '../test/builders/field_test.dart' as test_06; +import '../test/builders/file_test.dart' as test_07; +import '../test/builders/method_test.dart' as test_08; +import '../test/builders/parameter_test.dart' as test_09; +import '../test/builders/shared_test.dart' as test_10; +import '../test/builders/statement_test.dart' as test_11; +import '../test/builders/switch_test.dart' as test_12; +import '../test/builders/type_test.dart' as test_13; + +void main() { + test_01.main(); + test_02.main(); + test_03.main(); + test_04.main(); + test_05.main(); + test_06.main(); + test_07.main(); + test_08.main(); + test_09.main(); + test_10.main(); + test_11.main(); + test_12.main(); + test_13.main(); +} From 215a5dde5593cfe4e68488b253b89de73cfa8861 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Sun, 5 Feb 2017 17:38:53 -0800 Subject: [PATCH 037/271] Update invocation.dart (dart-lang/code_builder#73) Use `astFactory` instead of `new`. --- pkgs/code_builder/lib/src/builders/expression/invocation.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/lib/src/builders/expression/invocation.dart b/pkgs/code_builder/lib/src/builders/expression/invocation.dart index 2868280b1..9805fd7ab 100644 --- a/pkgs/code_builder/lib/src/builders/expression/invocation.dart +++ b/pkgs/code_builder/lib/src/builders/expression/invocation.dart @@ -102,7 +102,7 @@ class _MethodInvocationBuilder extends Object $period, stringIdentifier(_method), _generics.isNotEmpty - ? new TypeArgumentList( + ? astFactory.typeArgumentList( $openBracket, _generics.map((t) => t.buildType(scope)).toList(), $closeBracket, From 48df864c10c277647dd1895d94bb2d0e892b4ae0 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 8 Feb 2017 11:31:48 -0800 Subject: [PATCH 038/271] Fix a bug in annotation scoping. (dart-lang/code_builder#76) --- pkgs/code_builder/lib/src/builders/reference.dart | 2 +- pkgs/code_builder/test/e2e_test.dart | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkgs/code_builder/lib/src/builders/reference.dart b/pkgs/code_builder/lib/src/builders/reference.dart index 612201341..9ec4d56bf 100644 --- a/pkgs/code_builder/lib/src/builders/reference.dart +++ b/pkgs/code_builder/lib/src/builders/reference.dart @@ -40,7 +40,7 @@ class ReferenceBuilder extends Object Annotation buildAnnotation([Scope scope]) { return astFactory.annotation( $at, - stringIdentifier(_name), + identifier(scope, _name, _importFrom), null, null, null, diff --git a/pkgs/code_builder/test/e2e_test.dart b/pkgs/code_builder/test/e2e_test.dart index 7060a1eae..482eccfc5 100644 --- a/pkgs/code_builder/test/e2e_test.dart +++ b/pkgs/code_builder/test/e2e_test.dart @@ -96,18 +96,19 @@ void main() { equalsSource( r''' import 'package:app/app.dart' as _i1; - import 'package:app/thing.dart' as _i2; + import 'dart:core' as _i2; + import 'package:app/thing.dart' as _i3; class Injector implements _i1.App { final _i1.Module _module; Injector(this._module); - @override - _i2.Thing getThing() => new _i2.Thing(_module.getDep1(), _module.getDep2()); + @_i2.override + _i3.Thing getThing() => new _i3.Thing(_module.getDep1(), _module.getDep2()); - _i2.Thing instantiateAndReturnNamedThing() { - return new _i2.Thing.named(); + _i3.Thing instantiateAndReturnNamedThing() { + return new _i3.Thing.named(); } } ''', From b0063eb2d30181bb72d01d389479bf9d6cf653ad Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 15 Feb 2017 10:32:33 -0800 Subject: [PATCH 039/271] Remove references to this being experimental (dart-lang/code_builder#77) It's already used in a couple projects successfully and we've burned down most of the bugs/usability issues. --- pkgs/code_builder/README.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index df51b80cf..4ef3eb421 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -17,17 +17,6 @@ the analyzer's own understood format. [analyzer]: https://pub.dartlang.org/packages/analyzer -## Experimental - -While `code_builder` is considered *stable*, the APIs are subject to -frequent breaking change - a number of Dart language features are not -yet implemented that make it unsuitable for all forms of code -generation. - -**Contributions are [welcome][welcome]!** - -[welcome]: CONTRIBUTING.md - ## Usage Code builder has a narrow and user-friendly API. From ae4268d8cb03db91a738f431bb2e073c8f15bf71 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Fri, 24 Feb 2017 01:02:56 -0500 Subject: [PATCH 040/271] Add asThrow to ExpressionBuilder (dart-lang/code_builder#85) --- .../lib/src/builders/expression.dart | 7 ++++++ .../lib/src/builders/expression/throw.dart | 22 +++++++++++++++++++ pkgs/code_builder/lib/src/builders/field.dart | 9 +++++--- pkgs/code_builder/lib/src/tokens.dart | 3 +++ .../test/builders/expression_test.dart | 11 ++++++++++ 5 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 pkgs/code_builder/lib/src/builders/expression/throw.dart diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index 213c7447d..4565cb4d6 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -29,6 +29,7 @@ part 'expression/invocation.dart'; part 'expression/negate.dart'; part 'expression/operators.dart'; part 'expression/return.dart'; +part 'expression/throw.dart'; part 'expression/yield.dart'; final _false = @@ -205,6 +206,9 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { @override StatementBuilder asYieldStar() => new _AsYield(this, true); + @override + ExpressionBuilder asThrow() => new _ThrowExpression(this); + @override WhileStatementBuilder asWhile({bool asDo: false}) { return new WhileStatementBuilder(asDo, this); @@ -371,6 +375,9 @@ abstract class ExpressionBuilder /// [Statement] AST instead of an expression. StatementBuilder asStatement(); + /// Returns as an [ExpressionBuilder] that throws this expression as an error. + ExpressionBuilder asThrow(); + /// Returns as a [StatementBuilder] that assigns to a new `var` [variable]. /// /// If [type] is supplied, the resulting statement is `{type} {variable} =`. diff --git a/pkgs/code_builder/lib/src/builders/expression/throw.dart b/pkgs/code_builder/lib/src/builders/expression/throw.dart new file mode 100644 index 000000000..5db07c6fe --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/throw.dart @@ -0,0 +1,22 @@ +// 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. + +part of code_builder.src.builders.expression; + +class _ThrowExpression extends AbstractExpressionMixin with TopLevelMixin { + final ExpressionBuilder _value; + + _ThrowExpression(this._value); + + @override + ExpressionBuilder asThrow() => this; + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return astFactory.throwExpression($throw, _value.buildExpression(scope)); + } +} diff --git a/pkgs/code_builder/lib/src/builders/field.dart b/pkgs/code_builder/lib/src/builders/field.dart index 5964e4a36..14244638a 100644 --- a/pkgs/code_builder/lib/src/builders/field.dart +++ b/pkgs/code_builder/lib/src/builders/field.dart @@ -106,9 +106,7 @@ abstract class FieldBuilder TopLevelVariableDeclaration buildTopLevel([Scope scope]); } -class _FieldBuilderImpl extends TopLevelMixin - with HasAnnotationsMixin - implements FieldBuilder { +class _FieldBuilderImpl extends HasAnnotationsMixin implements FieldBuilder { final Keyword _keyword; final String _name; final TypeBuilder _type; @@ -157,6 +155,11 @@ class _FieldBuilderImpl extends TopLevelMixin ); } + @override + CompilationUnitMember buildTopLevelAst([Scope scope]) { + return buildTopLevel(scope); + } + VariableDeclarationList _buildVariableList([Scope scope]) { return astFactory.variableDeclarationList( null, diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index 88687a65f..1ed09937e 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -187,6 +187,9 @@ final Token $static = new KeywordToken(Keyword.STATIC, 0); /// The `this` token. final Token $this = new KeywordToken(Keyword.THIS, 0); +/// The `throw` token. +final Token $throw = new KeywordToken(Keyword.THROW, 0); + /// The `true` token. final Token $true = new KeywordToken(Keyword.TRUE, 0); diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 571d0b97a..21a487669 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -404,4 +404,15 @@ void main() { '''), ); }); + + test('should throw an exception', () { + expect( + new TypeBuilder('StateError') + .newInstance([literal('Hey! No!')]) + .asThrow() + .asStatement(), + equalsSource(''' + throw new StateError('Hey! No!'); + ''')); + }); } From 15c9c6c597423a0d9b14251bde9c9ea04af209ed Mon Sep 17 00:00:00 2001 From: Filip Hracek Date: Tue, 28 Feb 2017 19:50:29 -0800 Subject: [PATCH 041/271] Allow quotes and newlines in string literal (dart-lang/code_builder#88) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows creating string literals like “hello ‘world’” and “””hello\nworld”””. --- .../lib/src/builders/expression.dart | 12 ++++++++- .../test/builders/expression_test.dart | 26 +++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index 4565cb4d6..24d0f6203 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -84,7 +84,7 @@ Literal _literal(value) { } else if (value is bool) { return value ? _true : _false; } else if (value is String) { - return astFactory.simpleStringLiteral(stringToken("'$value'"), value); + return astFactory.simpleStringLiteral(stringToken(_quote(value)), value); } else if (value is int) { return astFactory.integerLiteral(stringToken('$value'), value); } else if (value is double) { @@ -93,6 +93,16 @@ Literal _literal(value) { throw new ArgumentError.value(value, 'Unsupported'); } +/// Quotes the string literal. It is assumed that the [value] is meant to be +/// the raw string, so all `\` are escaped. +String _quote(String value) { + value = value.replaceAll(r'\', r'\\').replaceAll(r"'", r"\'"); + if (value.contains('\n')) { + return "'''$value'''"; + } + return "'$value'"; +} + /// Implements much of [ExpressionBuilder]. abstract class AbstractExpressionMixin implements ExpressionBuilder { @override diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 21a487669..6467d4b29 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -29,8 +29,30 @@ void main() { expect(literal(5.5), equalsSource(r'5.5')); }); - test('should emit a string', () { - expect(literal('Hello'), equalsSource(r"'Hello'")); + group('should emit a string', () { + test('simple', () { + expect(literal('Hello'), equalsSource(r"'Hello'")); + }); + + test("with a '", () { + expect(literal("Hello'"), equalsSource(r"'Hello\''")); + }); + + test(r"with a \'", () { + expect(literal(r"Hello\'"), equalsSource(r"'Hello\\\''")); + }); + + test(r"with a \\'", () { + expect(literal(r"Hello\\'"), equalsSource(r"'Hello\\\\\''")); + }); + + test(r"with a newline", () { + expect(literal("Hello\nworld"), equalsSource("'''Hello\nworld'''")); + }); + + test(r"with a newline and ending with a '", () { + expect(literal("Hello\nworld'"), equalsSource("'''Hello\nworld\\''''")); + }); }); test('should emit a list', () { From f55953728ec7ce2533fc5d9f0e0fe94cfc867727 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 28 Feb 2017 19:58:45 -0800 Subject: [PATCH 042/271] Resolve a number of open issues (dart-lang/code_builder#86) * Add new features. * More changes. * Dartfmt. * Yegors issue. * Address feedback and merge. * Oops. --- pkgs/code_builder/CHANGELOG.md | 11 +++ pkgs/code_builder/lib/code_builder.dart | 7 +- pkgs/code_builder/lib/src/builders/file.dart | 80 +++++++++++------ .../code_builder/lib/src/builders/method.dart | 89 ++++++++++++++++++- .../lib/src/builders/reference.dart | 23 +++-- .../lib/src/builders/type/new_instance.dart | 10 ++- pkgs/code_builder/lib/src/tokens.dart | 3 + pkgs/code_builder/pubspec.yaml | 2 +- .../code_builder/test/builders/file_test.dart | 38 +++++++- .../test/builders/method_test.dart | 42 +++++++++ 10 files changed, 260 insertions(+), 45 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index b98c0d2d4..dfecf2c86 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,14 @@ +## 1.0.0-beta+4 + +- Renamed `PartBuilder` to `PartOfBuilder`. +- Added a new class, `PartBuilder`, to represent `part '...dart'` directives. +- Added the `HasAnnotations` interface to all library/part/directive builders. +- Added `asFactory` and `asConst` to `ConstructorBuilder`. +- Added `ConstructorBuilder.redirectTo` for a redirecting factory constructor. +- Added a `name` getter to `ReferenceBuilder`. +- Supplying an empty constructor name (`''`) is equivalent to `null` (default). +- Automatically encodes string literals with multiple lines as `'''`. + ## 1.0.0-beta+3 - Added support for `genericTypes` parameter for `ExpressionBuilder#invoke`: diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 4a3f6d4a7..4432924f1 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -10,7 +10,12 @@ export 'src/builders/expression.dart' export 'src/builders/field.dart' show varConst, varField, varFinal, FieldBuilder; export 'src/builders/file.dart' - show ExportBuilder, ImportBuilder, LibraryBuilder, PartBuilder; + show + ExportBuilder, + ImportBuilder, + LibraryBuilder, + PartBuilder, + PartOfBuilder; export 'src/builders/method.dart' show constructor, diff --git a/pkgs/code_builder/lib/src/builders/file.dart b/pkgs/code_builder/lib/src/builders/file.dart index cc93d547e..52b52a530 100644 --- a/pkgs/code_builder/lib/src/builders/file.dart +++ b/pkgs/code_builder/lib/src/builders/file.dart @@ -4,13 +4,14 @@ import 'package:analyzer/analyzer.dart'; import 'package:analyzer/dart/ast/standard_ast_factory.dart'; +import 'package:code_builder/src/builders/annotation.dart'; import 'package:code_builder/src/builders/shared.dart'; import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/tokens.dart'; /// Builds a file of Dart source code. /// -/// See [LibraryBuilder] and [PartBuilder] for concrete implementations. +/// See [LibraryBuilder] and [PartOfBuilder] for concrete implementations. abstract class FileBuilder implements AstBuilder { final List _members = []; @@ -28,8 +29,9 @@ abstract class FileBuilder implements AstBuilder { } /// Builds a standalone file (library) of Dart source code. -class LibraryBuilder extends FileBuilder { +class LibraryBuilder extends FileBuilder with HasAnnotationsMixin { final List> _directives = >[]; + final String _name; final Scope _scope; /// Creates a new standalone Dart library, optionally with [name]. @@ -43,11 +45,7 @@ class LibraryBuilder extends FileBuilder { return new LibraryBuilder._(name, scope ?? new Scope()); } - LibraryBuilder._(String name, this._scope) : super._() { - if (name != null) { - _directives.add(new _LibraryDirectiveBuilder(name)); - } - } + LibraryBuilder._(this._name, this._scope) : super._(); /// Adds a file [directive]. void addDirective(AstBuilder directive) { @@ -60,14 +58,18 @@ class LibraryBuilder extends FileBuilder { } @override - CompilationUnit buildAst([_]) { + CompilationUnit buildAst([Scope scope]) { var members = _members.map((m) { if (m is TopLevelMixin) { return (m as TopLevelMixin).buildTopLevelAst(_scope); } return m.buildAst(_scope); }).toList(); - var directives = [] + var directives = []; + if (_name != null) { + directives.add(new _LibraryDirectiveBuilder(_name, this).buildAst(scope)); + } + directives ..addAll(_scope.toImports().map((d) => d.buildAst())) ..addAll(_directives.map((d) => d.buildAst())); return astFactory.compilationUnit( @@ -81,28 +83,30 @@ class LibraryBuilder extends FileBuilder { } /// Lazily builds a partial file (part of) Dart source code. -class PartBuilder extends FileBuilder { - final String _name; +class PartOfBuilder extends FileBuilder with HasAnnotationsMixin { + final String _uri; + final Scope _scope; /// Creates a partial Dart file. - factory PartBuilder(String name) = PartBuilder._; + factory PartOfBuilder(String uri, [Scope scope]) = PartOfBuilder._; - PartBuilder._(this._name) : super._(); + PartOfBuilder._(this._uri, [this._scope]) : super._(); @override - CompilationUnit buildAst([_]) { + CompilationUnit buildAst([Scope scope]) { + scope ??= _scope; return astFactory.compilationUnit( null, null, [ astFactory.partOfDirective( null, - null, + buildAnnotations(scope), $part, $of, null, astFactory.libraryIdentifier([ - astFactory.simpleIdentifier(stringToken(_name)), + astFactory.simpleIdentifier(stringToken("'$_uri'")), ]), $semicolon, ) @@ -119,15 +123,16 @@ class PartBuilder extends FileBuilder { } class _LibraryDirectiveBuilder implements AstBuilder { + final LibraryBuilder _library; final String _name; - _LibraryDirectiveBuilder(this._name); + _LibraryDirectiveBuilder(this._name, this._library); @override - LibraryDirective buildAst([_]) { + LibraryDirective buildAst([Scope scope]) { return astFactory.libraryDirective( null, - null, + _library.buildAnnotations(scope), $library, astFactory.libraryIdentifier([ astFactory.simpleIdentifier( @@ -139,8 +144,31 @@ class _LibraryDirectiveBuilder implements AstBuilder { } } +/// Lazily builds a [PartDirective] AST when built. +class PartBuilder extends Object + with HasAnnotationsMixin + implements AstBuilder { + final String _uri; + + factory PartBuilder(String uri) = PartBuilder._; + PartBuilder._(this._uri); + + @override + PartDirective buildAst([Scope scope]) { + return astFactory.partDirective( + null, + buildAnnotations(scope), + $part, + astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri), + $semicolon, + ); + } +} + /// Lazily builds an [ImportDirective] AST when built. -class ImportBuilder implements AstBuilder { +class ImportBuilder extends Object + with HasAnnotationsMixin + implements AstBuilder { final String _prefix; final String _uri; final bool _deferred; @@ -171,7 +199,7 @@ class ImportBuilder implements AstBuilder { } @override - ImportDirective buildAst([_]) { + ImportDirective buildAst([Scope scope]) { var combinators = []; if (_show.isNotEmpty) { combinators.add( @@ -191,7 +219,7 @@ class ImportBuilder implements AstBuilder { } return astFactory.importDirective( null, - null, + buildAnnotations(scope), null, astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri), null, @@ -205,7 +233,9 @@ class ImportBuilder implements AstBuilder { } /// Lazily builds an [ExportDirective] AST when built. -class ExportBuilder implements AstBuilder { +class ExportBuilder extends Object + with HasAnnotationsMixin + implements AstBuilder { final String _uri; final Set _show = new Set(); @@ -232,7 +262,7 @@ class ExportBuilder implements AstBuilder { } @override - ExportDirective buildAst([_]) { + ExportDirective buildAst([Scope scope]) { var combinators = []; if (_show.isNotEmpty) { combinators.add( @@ -252,7 +282,7 @@ class ExportBuilder implements AstBuilder { } return astFactory.exportDirective( null, - null, + buildAnnotations(scope), null, astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri), null, diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index a25edbe3a..905a0e102 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -183,6 +183,7 @@ typedef void _AddParameter(ConstructorBuilder constructor); abstract class ConstructorBuilder implements AstBuilder, + HasAnnotations, HasParameters, HasStatements, ValidClassMember { @@ -193,8 +194,18 @@ abstract class ConstructorBuilder String name, String superName, List invokeSuper, + bool asConst, + bool asFactory, }) = _NormalConstructorBuilder; + /// Create a new [ConstructorBuilder] that redirects to another constructor. + factory ConstructorBuilder.redirectTo( + String name, + TypeBuilder redirectToClass, { + String constructor, + bool asConst, + }) = _RedirectingConstructorBuilder; + /// Adds a field initializer to this constructor. void addInitializer( String fieldName, { @@ -541,10 +552,78 @@ class _NamedParameterWrapper AstNode buildAst([_]) => throw new UnsupportedError('Use within method'); } +class _RedirectingConstructorBuilder extends Object + with HasAnnotationsMixin, HasParametersMixin + implements ConstructorBuilder { + final String name; + final TypeBuilder redirectToClass; + final bool asConst; + final String constructor; + + _RedirectingConstructorBuilder( + this.name, + this.redirectToClass, { + this.asConst: false, + this.constructor, + }); + + @override + void addInitializer( + String fieldName, { + ExpressionBuilder toExpression, + String toParameter, + }) { + throw new UnsupportedError('Not valid for redirect constructors'); + } + + @override + void addStatement(StatementBuilder statement) { + throw new UnsupportedError('Not valid for redirect constructors'); + } + + @override + void addStatements(Iterable statements) { + throw new UnsupportedError('Not valid for redirect constructors'); + } + + @override + ConstructorDeclaration buildAst([_]) { + throw new UnsupportedError('Can only be built as part of a class.'); + } + + @override + ConstructorDeclaration buildConstructor( + TypeBuilder returnType, [ + Scope scope, + ]) { + return astFactory.constructorDeclaration( + null, + buildAnnotations(scope), + null, + asConst ? $const : null, + $factory, + returnType.buildType(scope).name, + name != null ? $period : null, + name != null ? stringIdentifier(name) : null, + buildParameterList(scope), + null, + null, + astFactory.constructorName( + redirectToClass.buildType(scope), + constructor != null ? $period : null, + constructor != null ? stringIdentifier(constructor) : null, + ), + astFactory.emptyFunctionBody($semicolon), + ); + } +} + class _NormalConstructorBuilder extends Object with HasAnnotationsMixin, HasParametersMixin, HasStatementsMixin implements ConstructorBuilder { final _initializers = {}; + final bool _asFactory; + final bool _asConst; final String _name; final String _superName; final List _superInvocation; @@ -553,10 +632,14 @@ class _NormalConstructorBuilder extends Object List invokeSuper, String name, String superName, + bool asConst: false, + bool asFactory: false, }) : _name = name, _superInvocation = invokeSuper, - _superName = superName; + _superName = superName, + _asConst = asConst, + _asFactory = asFactory; @override void addInitializer( @@ -611,8 +694,8 @@ class _NormalConstructorBuilder extends Object null, buildAnnotations(scope), null, - null, - null, + _asConst ? $const : null, + _asFactory ? $factory : null, returnType.buildType(scope).name, _name != null ? $period : null, _name != null ? stringIdentifier(_name) : null, diff --git a/pkgs/code_builder/lib/src/builders/reference.dart b/pkgs/code_builder/lib/src/builders/reference.dart index 9ec4d56bf..07400946b 100644 --- a/pkgs/code_builder/lib/src/builders/reference.dart +++ b/pkgs/code_builder/lib/src/builders/reference.dart @@ -32,15 +32,17 @@ class ReferenceBuilder extends Object with AbstractExpressionMixin, AbstractTypeBuilderMixin, TopLevelMixin implements AnnotationBuilder, ExpressionBuilder, TypeBuilder { final String _importFrom; - final String _name; - ReferenceBuilder._(this._name, [this._importFrom]); + /// Name of the reference. + final String name; + + ReferenceBuilder._(this.name, [this._importFrom]); @override Annotation buildAnnotation([Scope scope]) { return astFactory.annotation( $at, - identifier(scope, _name, _importFrom), + identifier(scope, name, _importFrom), null, null, null, @@ -54,14 +56,14 @@ class ReferenceBuilder extends Object Expression buildExpression([Scope scope]) { return identifier( scope, - _name, + name, _importFrom, ); } @override TypeName buildType([Scope scope]) { - return new TypeBuilder(_name, importFrom: _importFrom).buildType(scope); + return new TypeBuilder(name, importFrom: _importFrom).buildType(scope); } @override @@ -69,7 +71,7 @@ class ReferenceBuilder extends Object if (_importFrom == null) { throw new StateError('Cannot create an import - no URI provided'); } - return new ExportBuilder(_importFrom)..show(_name); + return new ExportBuilder(_importFrom)..show(name); } @override @@ -81,7 +83,7 @@ class ReferenceBuilder extends Object _importFrom, deferred: deferred, prefix: prefix, - )..show(_name); + )..show(name); } /// Returns a new [ReferenceBuilder] with [genericTypes]. @@ -91,7 +93,10 @@ class ReferenceBuilder extends Object /// reference('List').toTyped([reference('String')]) ReferenceBuilder toTyped(Iterable genericTypes) { return new _TypedReferenceBuilder( - genericTypes.toList(), _name, _importFrom); + genericTypes.toList(), + name, + _importFrom, + ); } } @@ -108,7 +113,7 @@ class _TypedReferenceBuilder extends ReferenceBuilder { @override TypeName buildType([Scope scope]) { return new TypeBuilder( - _name, + name, importFrom: _importFrom, genericTypes: _genericTypes, ) diff --git a/pkgs/code_builder/lib/src/builders/type/new_instance.dart b/pkgs/code_builder/lib/src/builders/type/new_instance.dart index 0a0441c17..e1ac8f5cf 100644 --- a/pkgs/code_builder/lib/src/builders/type/new_instance.dart +++ b/pkgs/code_builder/lib/src/builders/type/new_instance.dart @@ -53,7 +53,9 @@ class _NewInvocationBuilderImpl extends Object $at, _type.buildType(scope).name, $period, - _constructor != null ? stringIdentifier(_constructor) : null, + _constructor != null && _constructor.isNotEmpty + ? stringIdentifier(_constructor) + : null, buildArgumentList(scope: scope), ); } @@ -64,8 +66,10 @@ class _NewInvocationBuilderImpl extends Object new KeywordToken(_keyword, 0), astFactory.constructorName( _type.buildType(scope), - _constructor != null ? $period : null, - _constructor != null ? stringIdentifier(_constructor) : null, + _constructor != null && _constructor.isNotEmpty ? $period : null, + _constructor != null && _constructor.isNotEmpty + ? stringIdentifier(_constructor) + : null, ), buildArgumentList(scope: scope), ); diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index 1ed09937e..4b7b15e6f 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -71,6 +71,9 @@ final Token $equalsEquals = new Token(TokenType.EQ_EQ, 0); /// The `extends` token. final Token $extends = new KeywordToken(Keyword.EXTENDS, 0); +/// The `factory` token. +final Token $factory = new KeywordToken(Keyword.FACTORY, 0); + /// The `false` token. final Token $false = new KeywordToken(Keyword.FALSE, 0); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 9ed6f6b62..2737e185f 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-beta+3 +version: 1.0.0-beta+4 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/file_test.dart b/pkgs/code_builder/test/builders/file_test.dart index be486fe89..24dfe84b1 100644 --- a/pkgs/code_builder/test/builders/file_test.dart +++ b/pkgs/code_builder/test/builders/file_test.dart @@ -62,9 +62,41 @@ void main() { group('$LibraryBuilder', () { test('should handle empty methods', () { expect( - new LibraryBuilder() - ..addMember(new MethodBuilder.returnVoid('main')), - equalsSource('void main() {}')); + new LibraryBuilder()..addMember(new MethodBuilder.returnVoid('main')), + equalsSource('void main() {}'), + ); + }); + + test('should support metadata', () { + expect( + new LibraryBuilder('some_lib')..addAnnotation(reference('ignore')), + equalsSource(r''' + @ignore + library some_lib; + '''), + ); + }); + }); + + group('$PartBuilder', () { + test('should emit a part directive', () { + expect( + new LibraryBuilder()..addDirective(new PartBuilder('part.dart')), + equalsSource(r''' + part 'part.dart'; + '''), + ); + }); + }); + + group('$PartOfBuilder', () { + test('should emit a part-of file', () { + expect( + new PartOfBuilder('main.dart'), + equalsSource(r''' + part of 'main.dart'; + '''), + ); }); }); }); diff --git a/pkgs/code_builder/test/builders/method_test.dart b/pkgs/code_builder/test/builders/method_test.dart index 8c89ee02b..f757d482d 100644 --- a/pkgs/code_builder/test/builders/method_test.dart +++ b/pkgs/code_builder/test/builders/method_test.dart @@ -121,6 +121,48 @@ void main() { ); }); + test('should emit a const constructor', () { + expect( + new ConstructorBuilder(asConst: true) + .buildConstructor( + reference('Animal'), + ) + .toSource(), + equalsIgnoringWhitespace(r''' + const Animal(); + '''), + ); + }); + + test('should emit a factory constructor', () { + expect( + (new ConstructorBuilder(asFactory: true) + ..addStatement(literal(null).asReturn())) + .buildConstructor( + reference('Animal'), + ) + .toSource(), + equalsIgnoringWhitespace(r''' + factory Animal() {return null;} + '''), + ); + }); + + test('should emit a redirecting constructor', () { + expect( + new ConstructorBuilder.redirectTo( + 'noopAnimal', + reference('NoopAnimalImpl'), + asConst: true, + ) + .buildConstructor(reference('Animal')) + .toSource(), + equalsIgnoringWhitespace(r''' + const factory Animal.noopAnimal() = NoopAnimalImpl; + '''), + ); + }); + test('should a method with a lambda value', () { expect( lambda('supported', literal(true), returnType: lib$core.bool), From c3547379a33037efddf34888c845f6b4f42c74c1 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 28 Feb 2017 20:00:32 -0800 Subject: [PATCH 043/271] Update CHANGELOG.md --- pkgs/code_builder/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index dfecf2c86..733c85d6d 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -8,6 +8,8 @@ - Added a `name` getter to `ReferenceBuilder`. - Supplying an empty constructor name (`''`) is equivalent to `null` (default). - Automatically encodes string literals with multiple lines as `'''`. +- Added `asThrow` to `ExpressionBuilder`. +- Fixed a bug that prevented `FieldBuilder` from being used at the top-level. ## 1.0.0-beta+3 From cce5b54819f08bd5c4d9523753621b6ad04c33b9 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 2 Mar 2017 10:38:26 -0800 Subject: [PATCH 044/271] Fix pub publishing. --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 733c85d6d..3344afe6b 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.0-beta+5 + +- Re-published the package without merge conflicts. + ## 1.0.0-beta+4 - Renamed `PartBuilder` to `PartOfBuilder`. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 2737e185f..fbd51f500 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-beta+4 +version: 1.0.0-beta+5 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From c2b7c920e152e2aa263b920f2726d3975ebb7416 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 7 Mar 2017 18:38:58 -0800 Subject: [PATCH 045/271] More features towards completion (dart-lang/code_builder#94) * Add more features towards final. * Oops. * Update type_def.dart --- pkgs/code_builder/CHANGELOG.md | 6 ++ pkgs/code_builder/lib/code_builder.dart | 6 +- .../code_builder/lib/src/builders/method.dart | 87 ++++++++++++++----- .../lib/src/builders/parameter.dart | 40 +++++++++ pkgs/code_builder/lib/src/builders/type.dart | 1 + .../lib/src/builders/type/type_def.dart | 61 +++++++++++++ pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/class_test.dart | 15 ++++ .../test/builders/parameter_test.dart | 15 ++++ .../code_builder/test/builders/type_test.dart | 27 ++++++ 10 files changed, 234 insertions(+), 26 deletions(-) create mode 100644 pkgs/code_builder/lib/src/builders/type/type_def.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 3344afe6b..69cdf0b36 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.0.0-beta+6 + +- Added `TypeDefBuilder`. +- Added `FunctionParameterBuilder`. +- Added `asAbstract` to various `MethodBuilder` constructors. + ## 1.0.0-beta+5 - Re-published the package without merge conflicts. diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 4432924f1..d049656d0 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -30,7 +30,8 @@ export 'src/builders/method.dart' MethodBuilder, MethodModifier, ValidMethodMember; -export 'src/builders/parameter.dart' show parameter, ParameterBuilder; +export 'src/builders/parameter.dart' + show parameter, FunctionParameterBuilder, ParameterBuilder; export 'src/pretty_printer.dart' show prettyToSource; export 'src/builders/reference.dart' show explicitThis, reference, ReferenceBuilder; @@ -52,4 +53,5 @@ export 'src/builders/statement.dart' SwitchDefaultCaseBuilder, SwitchStatementBuilder, WhileStatementBuilder; -export 'src/builders/type.dart' show NewInstanceBuilder, TypeBuilder; +export 'src/builders/type.dart' + show NewInstanceBuilder, TypeBuilder, TypeDefBuilder; diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index 905a0e102..e1605cd80 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -34,10 +34,18 @@ ConstructorBuilder constructorNamed( /// Various types of modifiers for methods. class MethodModifier implements ValidMethodMember { - static const MethodModifier asAsync = const MethodModifier._('async', false); - static const MethodModifier asAsyncStar = - const MethodModifier._('async', true); - static const MethodModifier asSyncStar = const MethodModifier._('sync', true); + static const MethodModifier asAsync = const MethodModifier._( + 'async', + false, + ); + static const MethodModifier asAsyncStar = const MethodModifier._( + 'async', + true, + ); + static const MethodModifier asSyncStar = const MethodModifier._( + 'sync', + true, + ); final String _keyword; @@ -237,6 +245,7 @@ abstract class MethodBuilder /// Creates a new [MethodBuilder]. factory MethodBuilder( String name, { + bool asAbstract: false, MethodModifier modifier, ExpressionBuilder returns, TypeBuilder returnType, @@ -248,12 +257,14 @@ abstract class MethodBuilder returnType, null, modifier, + asAbstract, ); } else { return new _MethodBuilderImpl( name, modifier: modifier, returns: returnType, + asAbstract: asAbstract, ); } } @@ -263,6 +274,7 @@ abstract class MethodBuilder MethodModifier modifier, ExpressionBuilder returns, TypeBuilder returnType, + bool asAbstract: false, }) { if (returns != null) { return new _LambdaMethodBuilder( @@ -271,12 +283,14 @@ abstract class MethodBuilder returnType, null, modifier, + asAbstract, ); } else { return new _MethodBuilderImpl( null, modifier: modifier, returns: returnType, + asAbstract: asAbstract, ); } } @@ -287,6 +301,7 @@ abstract class MethodBuilder MethodModifier modifier, TypeBuilder returnType, ExpressionBuilder returns, + bool asAbstract: false, }) { if (returns == null) { return new _MethodBuilderImpl( @@ -294,6 +309,7 @@ abstract class MethodBuilder modifier: modifier, returns: returnType, property: Keyword.GET, + asAbstract: asAbstract, ); } else { return new _LambdaMethodBuilder( @@ -302,14 +318,23 @@ abstract class MethodBuilder returnType, Keyword.GET, modifier, + asAbstract, ); } } /// Creates a new [MethodBuilder] that returns `void`. - factory MethodBuilder.returnVoid(String name, {ExpressionBuilder returns}) { + factory MethodBuilder.returnVoid( + String name, { + ExpressionBuilder returns, + bool asAbstract: false, + }) { if (returns == null) { - return new _MethodBuilderImpl(name, returns: lib$core.$void); + return new _MethodBuilderImpl( + name, + returns: lib$core.$void, + asAbstract: asAbstract, + ); } return new _LambdaMethodBuilder( name, @@ -317,6 +342,7 @@ abstract class MethodBuilder lib$core.$void, null, null, + asAbstract, ); } @@ -324,11 +350,13 @@ abstract class MethodBuilder factory MethodBuilder.setter( String name, { ExpressionBuilder returns, + bool asAbstract: false, }) { if (returns == null) { return new _MethodBuilderImpl( name, property: Keyword.SET, + asAbstract: asAbstract, ); } else { return new _LambdaMethodBuilder( @@ -337,6 +365,7 @@ abstract class MethodBuilder null, Keyword.SET, null, + asAbstract, ); } } @@ -376,6 +405,7 @@ class _LambdaMethodBuilder extends Object final String _name; final TypeBuilder _returnType; final Keyword _property; + final bool _asAbstract; _LambdaMethodBuilder( this._name, @@ -383,6 +413,7 @@ class _LambdaMethodBuilder extends Object this._returnType, this._property, this._modifier, + this._asAbstract, ); @override @@ -430,7 +461,9 @@ class _LambdaMethodBuilder extends Object _returnType?.buildType(scope), _property != null ? new KeywordToken(_property, 0) : null, _name != null ? stringIdentifier(_name) : null, - _buildExpression(scope, isStatement: true), + _asAbstract + ? astFactory.emptyFunctionBody($semicolon) + : _buildExpression(scope, isStatement: true), ); } @@ -447,12 +480,14 @@ class _LambdaMethodBuilder extends Object stringIdentifier(_name), null, _property != Keyword.GET ? buildParameterList(scope) : null, - astFactory.expressionFunctionBody( - _modifier?.keyword(), - null, - _expression.buildExpression(scope), - $semicolon, - ), + _asAbstract + ? astFactory.emptyFunctionBody($semicolon) + : astFactory.expressionFunctionBody( + _modifier?.keyword(), + null, + _expression.buildExpression(scope), + $semicolon, + ), ); } @@ -472,12 +507,14 @@ class _MethodBuilderImpl extends Object final String _name; final TypeBuilder _returnType; final Keyword _property; + final bool asAbstract; _MethodBuilderImpl( this._name, { MethodModifier modifier, TypeBuilder returns, Keyword property, + this.asAbstract: false, }) : _modifier = modifier, _returnType = returns, @@ -496,11 +533,13 @@ class _MethodBuilderImpl extends Object return astFactory.functionExpression( null, _property != Keyword.GET ? buildParameterList(scope) : null, - astFactory.blockFunctionBody( - _modifier?.keyword(), - _modifier?.isStar == true ? $star : null, - buildBlock(scope), - ), + asAbstract + ? astFactory.emptyFunctionBody($semicolon) + : astFactory.blockFunctionBody( + _modifier?.keyword(), + _modifier?.isStar == true ? $star : null, + buildBlock(scope), + ), ); } @@ -530,11 +569,13 @@ class _MethodBuilderImpl extends Object identifier(scope, _name), null, _property != Keyword.GET ? buildParameterList(scope) : null, - astFactory.blockFunctionBody( - _modifier?.keyword(), - _modifier?.isStar == true ? $star : null, - buildBlock(scope), - ), + asAbstract + ? astFactory.emptyFunctionBody($semicolon) + : astFactory.blockFunctionBody( + _modifier?.keyword(), + _modifier?.isStar == true ? $star : null, + buildBlock(scope), + ), ); } diff --git a/pkgs/code_builder/lib/src/builders/parameter.dart b/pkgs/code_builder/lib/src/builders/parameter.dart index a3443c1db..c4bbf162d 100644 --- a/pkgs/code_builder/lib/src/builders/parameter.dart +++ b/pkgs/code_builder/lib/src/builders/parameter.dart @@ -218,3 +218,43 @@ class _SimpleParameterBuilder extends Object ); } } + +/// A parameter type that represents a function definition. +class FunctionParameterBuilder extends Object + with HasAnnotationsMixin, HasParametersMixin + implements ParameterBuilder { + @override + final String name; + final TypeBuilder returnType; + + FunctionParameterBuilder( + this.name, { + this.returnType, + }); + + @override + ParameterBuilder asOptional([ExpressionBuilder defaultTo]) { + return new _OptionalParameterBuilder(this, defaultTo); + } + + @override + FunctionTypedFormalParameter buildAst([Scope scope]) => + buildPositional(false, scope); + + @override + FunctionTypedFormalParameter buildNamed(bool field, [Scope scope]) { + return asOptional().buildNamed(field, scope); + } + + @override + FunctionTypedFormalParameter buildPositional(bool field, [Scope scope]) { + return astFactory.functionTypedFormalParameter( + null, + buildAnnotations(scope), + returnType?.buildType(scope), + stringIdentifier(name), + null, + buildParameterList(scope), + ); + } +} diff --git a/pkgs/code_builder/lib/src/builders/type.dart b/pkgs/code_builder/lib/src/builders/type.dart index f9136558e..e39de77bd 100644 --- a/pkgs/code_builder/lib/src/builders/type.dart +++ b/pkgs/code_builder/lib/src/builders/type.dart @@ -18,6 +18,7 @@ import 'package:code_builder/src/builders/statement.dart'; import 'package:code_builder/src/tokens.dart'; part 'type/new_instance.dart'; +part 'type/type_def.dart'; /// Implements the `new` and `const` constructor calls. abstract class AbstractTypeBuilderMixin { diff --git a/pkgs/code_builder/lib/src/builders/type/type_def.dart b/pkgs/code_builder/lib/src/builders/type/type_def.dart new file mode 100644 index 000000000..3be307b01 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/type/type_def.dart @@ -0,0 +1,61 @@ +// 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. + +part of code_builder.src.builders.type; + +TypeParameterList typeParameters(Scope scope, Map types) { + if (types.isEmpty) { + return null; + } + return astFactory.typeParameterList( + $openBracket, + types.keys.map((name) { + final type = types[name]; + return astFactory.typeParameter( + null, + null, + stringIdentifier(name), + type != null ? $extends : null, + type?.buildType(scope), + ); + }).toList(), + $closeBracket, + ); +} + +/// Lazily build a `typedef`, or [FunctionTypeAlias] AST. +class TypeDefBuilder extends AstBuilder + with HasAnnotationsMixin, HasParametersMixin, TopLevelMixin { + /// Optional generic type parameters. + final Map genericTypes; + + /// Name of the `typedef`. + final String name; + + /// Return type; if `null` defaults to implicitly dynamic. + final TypeBuilder returnType; + + TypeDefBuilder( + this.name, { + this.genericTypes: const {}, + this.returnType, + }); + + @override + FunctionTypeAlias buildAst([Scope scope]) { + return astFactory.functionTypeAlias( + null, + buildAnnotations(scope), + null, + returnType?.buildType(scope), + stringIdentifier(name), + typeParameters(scope, genericTypes), + buildParameterList(scope), + $semicolon, + ); + } + + @override + CompilationUnitMember buildTopLevelAst([Scope scope]) => buildAst(scope); +} diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index fbd51f500..9ec793f50 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-beta+5 +version: 1.0.0-beta+6 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/class_test.dart b/pkgs/code_builder/test/builders/class_test.dart index 776ee4fec..bea6d9417 100644 --- a/pkgs/code_builder/test/builders/class_test.dart +++ b/pkgs/code_builder/test/builders/class_test.dart @@ -18,6 +18,21 @@ void main() { ); }); + test('should emit an abstract class', () { + expect( + new ClassBuilder('Animal', asAbstract: true) + ..addMethod(new MethodBuilder.returnVoid( + 'eat', + asAbstract: true, + )), + equalsSource(r''' + abstract class Animal { + void eat(); + } + '''), + ); + }); + test('should emit a class with an annotation', () { expect( clazz('Animal', [reference('deprecated')]), diff --git a/pkgs/code_builder/test/builders/parameter_test.dart b/pkgs/code_builder/test/builders/parameter_test.dart index 8ac2d81dc..b77cb15a9 100644 --- a/pkgs/code_builder/test/builders/parameter_test.dart +++ b/pkgs/code_builder/test/builders/parameter_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/dart/core.dart'; import 'package:code_builder/testing.dart'; import 'package:test/test.dart'; @@ -47,4 +48,18 @@ void main() { equalsIgnoringCase(r'this.foo'), ); }); + + test('should emit a function typed parameter', () { + expect( + (new FunctionParameterBuilder( + 'callback', + returnType: lib$core.$void, + )..addPositional(parameter('value'))) + .buildPositional(false) + .toSource(), + equalsIgnoringWhitespace(r''' + void callback(value) + '''), + ); + }); } diff --git a/pkgs/code_builder/test/builders/type_test.dart b/pkgs/code_builder/test/builders/type_test.dart index 14383d8ed..18d356f03 100644 --- a/pkgs/code_builder/test/builders/type_test.dart +++ b/pkgs/code_builder/test/builders/type_test.dart @@ -131,4 +131,31 @@ void main() { throwsStateError, ); }); + + test('can create a simple typedef', () { + expect( + new TypeDefBuilder( + 'Callback', + returnType: lib$core.$void, + ), + equalsSource(r''' + typedef void Callback(); + '''), + ); + }); + + test('can create a more complex typedef', () { + expect( + new TypeDefBuilder( + 'Callback', + genericTypes: { + 'T': lib$core.Set, + }, + returnType: reference('T'), + )..addPositional(parameter('items')), + equalsSource(r''' + typedef T Callback(items); + '''), + ); + }); } From 54688fc1ba23b5b5cdd7cb1c6e1ea2ed7590dc01 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 15 Mar 2017 20:50:30 -0700 Subject: [PATCH 046/271] Update pubspec. --- pkgs/code_builder/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 9ec793f50..0ec2d772a 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -5,7 +5,7 @@ author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=1.9.1 <2.0.0' + sdk: '>=1.22.0 <2.0.0' dependencies: analyzer: '>=0.29.1 <0.30.0' From c6a7a6d66658b91574fadd53b3a6813296f19d35 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 29 Mar 2017 13:29:14 -0700 Subject: [PATCH 047/271] Add ExpressionBuilder#ternary. (dart-lang/code_builder#97) * Add ExpressionBuilder#ternary. * Run dartfmt. * Dartfmt and use the SDK version. * Run travis on more SDKs. --- pkgs/code_builder/.travis.yml | 4 +-- pkgs/code_builder/CHANGELOG.md | 4 +++ .../lib/src/builders/expression.dart | 14 +++++++++ .../lib/src/builders/expression/ternary.dart | 31 +++++++++++++++++++ pkgs/code_builder/lib/src/tokens.dart | 3 ++ pkgs/code_builder/pubspec.yaml | 2 +- .../test/builders/expression_test.dart | 9 ++++++ pkgs/code_builder/test/e2e_test.dart | 5 ++- pkgs/code_builder/tool/presubmit.sh | 2 +- 9 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 pkgs/code_builder/lib/src/builders/expression/ternary.dart diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index fcb7af47c..1470e94a2 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -1,8 +1,8 @@ language: dart dart: - # pkg/test is currently failing @ dev - # - dev + - 1.22.0 + - dev - stable script: ./tool/presubmit.sh diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 69cdf0b36..5c1bcf90f 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.0-beta+7 + +- Added `ExpressionBuilder#ternary`. + ## 1.0.0-beta+6 - Added `TypeDefBuilder`. diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index 24d0f6203..dbb32cbdc 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -29,6 +29,7 @@ part 'expression/invocation.dart'; part 'expression/negate.dart'; part 'expression/operators.dart'; part 'expression/return.dart'; +part 'expression/ternary.dart'; part 'expression/throw.dart'; part 'expression/yield.dart'; @@ -322,6 +323,13 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { @override ExpressionBuilder property(String name) => new _MemberExpression(this, name); + + @override + ExpressionBuilder ternary( + ExpressionBuilder ifTrue, + ExpressionBuilder ifFalse, + ) => + new _TernaryExpression(this, ifTrue, ifFalse); } /// Builds an [Expression] AST when [buildExpression] is invoked. @@ -456,6 +464,12 @@ abstract class ExpressionBuilder /// Returns {{this}}.{{name}}. ExpressionBuilder property(String name); + + /// Returns {{this}} ? {{ifTrue}} : {{ifFalse}}. + ExpressionBuilder ternary( + ExpressionBuilder ifTrue, + ExpressionBuilder ifFalse, + ); } /// An [AstBuilder] that can add [ExpressionBuilder]. diff --git a/pkgs/code_builder/lib/src/builders/expression/ternary.dart b/pkgs/code_builder/lib/src/builders/expression/ternary.dart new file mode 100644 index 000000000..5a93a3cf5 --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/ternary.dart @@ -0,0 +1,31 @@ +// 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. + +part of code_builder.src.builders.expression; + +class _TernaryExpression extends TopLevelMixin with AbstractExpressionMixin { + final ExpressionBuilder _target; + final ExpressionBuilder _ifTrue; + final ExpressionBuilder _ifFalse; + + _TernaryExpression( + this._target, + this._ifTrue, + this._ifFalse, + ); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return astFactory.conditionalExpression( + _target.buildExpression(scope), + $question, + _ifTrue.buildExpression(scope), + $colon, + _ifFalse.buildExpression(scope), + ); + } +} diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index 4b7b15e6f..b0464dc47 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -202,6 +202,9 @@ final Token $var = new KeywordToken(Keyword.VAR, 0); /// The `with` token. final Token $with = new KeywordToken(Keyword.WITH, 0); +/// The `?` token. +final Token $question = new Token(TokenType.QUESTION, 0); + /// Returns an int token for the given int [value]. StringToken intToken(int value) => new StringToken(TokenType.INT, '$value', 0); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 0ec2d772a..ceae7f928 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-beta+6 +version: 1.0.0-beta+7 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart index 6467d4b29..39d83547f 100644 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ b/pkgs/code_builder/test/builders/expression_test.dart @@ -437,4 +437,13 @@ void main() { throw new StateError('Hey! No!'); ''')); }); + + test('should create a ternary condition ? ifTrue : ifFalse', () { + expect( + reference('someValue').ternary(literal(true), literal(false)), + equalsSource(r''' + someValue ? true : false + '''), + ); + }); } diff --git a/pkgs/code_builder/test/e2e_test.dart b/pkgs/code_builder/test/e2e_test.dart index 482eccfc5..356e25e29 100644 --- a/pkgs/code_builder/test/e2e_test.dart +++ b/pkgs/code_builder/test/e2e_test.dart @@ -88,9 +88,8 @@ void main() { ..addMethod(new MethodBuilder( 'instantiateAndReturnNamedThing', returnType: thingRef, - ) - ..addStatement( - thingRef.newInstance([], constructor: 'named').asReturn()))); + )..addStatement( + thingRef.newInstance([], constructor: 'named').asReturn()))); expect( lib, equalsSource( diff --git a/pkgs/code_builder/tool/presubmit.sh b/pkgs/code_builder/tool/presubmit.sh index 2c7a343f3..8606c3438 100755 --- a/pkgs/code_builder/tool/presubmit.sh +++ b/pkgs/code_builder/tool/presubmit.sh @@ -3,7 +3,7 @@ # Make sure dartfmt is run on everything # This assumes you have dart_style as a dev_dependency echo "Checking dartfmt..." -NEEDS_DARTFMT="$(find lib test -name "*.dart" | xargs pub run dart_style:format -n)" +NEEDS_DARTFMT="$(find lib test -name "*.dart" | xargs dartfmt -n)" if [[ ${NEEDS_DARTFMT} != "" ]] then echo "FAILED" From f98d82aa71808ab444bf960615f65f358662e95f Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 30 Mar 2017 17:16:37 -0700 Subject: [PATCH 048/271] Run dartfmt to fix the build. (dart-lang/code_builder#102) * Dartfmt. * Remove dev. --- pkgs/code_builder/.travis.yml | 1 - pkgs/code_builder/test/e2e_test.dart | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index 1470e94a2..e3be4eb6e 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -2,7 +2,6 @@ language: dart dart: - 1.22.0 - - dev - stable script: ./tool/presubmit.sh diff --git a/pkgs/code_builder/test/e2e_test.dart b/pkgs/code_builder/test/e2e_test.dart index 356e25e29..482eccfc5 100644 --- a/pkgs/code_builder/test/e2e_test.dart +++ b/pkgs/code_builder/test/e2e_test.dart @@ -88,8 +88,9 @@ void main() { ..addMethod(new MethodBuilder( 'instantiateAndReturnNamedThing', returnType: thingRef, - )..addStatement( - thingRef.newInstance([], constructor: 'named').asReturn()))); + ) + ..addStatement( + thingRef.newInstance([], constructor: 'named').asReturn()))); expect( lib, equalsSource( From c5824711f68116c90184a43f3187911dc9162745 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 30 Mar 2017 17:16:54 -0700 Subject: [PATCH 049/271] Expose Uri for some builders. (dart-lang/code_builder#104) --- pkgs/code_builder/lib/code_builder.dart | 3 +- pkgs/code_builder/lib/src/builders/file.dart | 32 ++++++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index d049656d0..8fd41c75b 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -15,7 +15,8 @@ export 'src/builders/file.dart' ImportBuilder, LibraryBuilder, PartBuilder, - PartOfBuilder; + PartOfBuilder, + UriDirectiveBuilder; export 'src/builders/method.dart' show constructor, diff --git a/pkgs/code_builder/lib/src/builders/file.dart b/pkgs/code_builder/lib/src/builders/file.dart index 52b52a530..915dc64ef 100644 --- a/pkgs/code_builder/lib/src/builders/file.dart +++ b/pkgs/code_builder/lib/src/builders/file.dart @@ -144,14 +144,20 @@ class _LibraryDirectiveBuilder implements AstBuilder { } } +/// A builder that has a reference to a [uri]. +abstract class UriDirectiveBuilder implements AstBuilder { + String get uri; +} + /// Lazily builds a [PartDirective] AST when built. class PartBuilder extends Object with HasAnnotationsMixin - implements AstBuilder { - final String _uri; + implements AstBuilder, UriDirectiveBuilder { + @override + final String uri; factory PartBuilder(String uri) = PartBuilder._; - PartBuilder._(this._uri); + PartBuilder._(this.uri); @override PartDirective buildAst([Scope scope]) { @@ -159,7 +165,7 @@ class PartBuilder extends Object null, buildAnnotations(scope), $part, - astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri), + astFactory.simpleStringLiteral(stringToken("'$uri'"), uri), $semicolon, ); } @@ -168,9 +174,10 @@ class PartBuilder extends Object /// Lazily builds an [ImportDirective] AST when built. class ImportBuilder extends Object with HasAnnotationsMixin - implements AstBuilder { + implements AstBuilder, UriDirectiveBuilder { final String _prefix; - final String _uri; + @override + final String uri; final bool _deferred; final Set _show = new Set(); @@ -180,7 +187,7 @@ class ImportBuilder extends Object return new ImportBuilder._(path, prefix, deferred); } - ImportBuilder._(this._uri, this._prefix, this._deferred); + ImportBuilder._(this.uri, this._prefix, this._deferred); void hide(String identifier) { _hide.add(identifier); @@ -221,7 +228,7 @@ class ImportBuilder extends Object null, buildAnnotations(scope), null, - astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri), + astFactory.simpleStringLiteral(stringToken("'$uri'"), uri), null, _deferred ? $deferred : null, _prefix != null ? $as : null, @@ -235,15 +242,16 @@ class ImportBuilder extends Object /// Lazily builds an [ExportDirective] AST when built. class ExportBuilder extends Object with HasAnnotationsMixin - implements AstBuilder { - final String _uri; + implements AstBuilder, UriDirectiveBuilder { + @override + final String uri; final Set _show = new Set(); final Set _hide = new Set(); factory ExportBuilder(String path) = ExportBuilder._; - ExportBuilder._(this._uri); + ExportBuilder._(this.uri); void hide(String identifier) { _hide.add(identifier); @@ -284,7 +292,7 @@ class ExportBuilder extends Object null, buildAnnotations(scope), null, - astFactory.simpleStringLiteral(stringToken("'$_uri'"), _uri), + astFactory.simpleStringLiteral(stringToken("'$uri'"), uri), null, combinators, $semicolon, From f69b4fa636d575d2514e4f3d72b7832d269c389f Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 30 Mar 2017 17:17:11 -0700 Subject: [PATCH 050/271] Add tests showing lambda use. (dart-lang/code_builder#103) --- pkgs/code_builder/test/builders/class_test.dart | 6 ++++++ pkgs/code_builder/test/builders/method_test.dart | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/pkgs/code_builder/test/builders/class_test.dart b/pkgs/code_builder/test/builders/class_test.dart index bea6d9417..ba64f94fb 100644 --- a/pkgs/code_builder/test/builders/class_test.dart +++ b/pkgs/code_builder/test/builders/class_test.dart @@ -174,6 +174,11 @@ void main() { constructor([ lib$core.print.call([literal('Called constructor')]), ]), + new MethodBuilder( + 'toString', + returns: literal(r'$Animal'), + returnType: lib$core.String, + ), ]), equalsSource(r''' class Animal { @@ -186,6 +191,7 @@ void main() { void instanceMethod() { print('Called instanceMethod'); } + String toString() => '$Animal'; } '''), ); diff --git a/pkgs/code_builder/test/builders/method_test.dart b/pkgs/code_builder/test/builders/method_test.dart index f757d482d..01c495512 100644 --- a/pkgs/code_builder/test/builders/method_test.dart +++ b/pkgs/code_builder/test/builders/method_test.dart @@ -77,6 +77,15 @@ void main() { ); }); + test('should emit a function with a lambda expression', () { + expect( + new MethodBuilder('talk', returns: literal('Hello World')), + equalsSource(r''' + talk() => 'Hello World'; + '''), + ); + }); + group('constructors', () { test('should emit a simple constructor', () { expect( From 4707356dc99e430745445c825122904daa491a0e Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 30 Mar 2017 17:39:57 -0700 Subject: [PATCH 051/271] Prepare to release 1.0.0. (dart-lang/code_builder#105) --- pkgs/code_builder/CHANGELOG.md | 10 ++++++++++ pkgs/code_builder/README.md | 14 ++++++++++++++ pkgs/code_builder/pubspec.yaml | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 5c1bcf90f..4706747b2 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,13 @@ +## 1.0.0 + +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.** + +- Exposed `uri` in `ImportBuilder`, `ExportBuilder`, and `Part[Of]Builder`. + ## 1.0.0-beta+7 - Added `ExpressionBuilder#ternary`. diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 4ef3eb421..9eeefbc22 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -17,6 +17,20 @@ the analyzer's own understood format. [analyzer]: https://pub.dartlang.org/packages/analyzer +## Contributing + +* Read and help us document common patterns over [at the wiki][wiki]. +* Is there a *bug* in the code? [File an issue][issue]. + +If a feature is missing (the Dart language is always evolving) or you'd like an +easier or better way to do something, consider [opening a pull request][pull]. +You can always [file an issue][issue], but generally speaking feature requests +will be on a best-effort basis. + +[wiki]: https://github.com/dart-lang/code_builder/wiki +[issue]: https://github.com/dart-lang/code_builder/issues +[pull]: https://github.com/dart-lang/code_builder/pulls + ## Usage Code builder has a narrow and user-friendly API. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index ceae7f928..d79244b37 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0-beta+7 +version: 1.0.0 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From 92884b47aef034523317564578def54b54c5ca58 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 4 Apr 2017 19:46:49 -0700 Subject: [PATCH 052/271] Support latest pkg/dart_style (dart-lang/code_builder#106) --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 4706747b2..aa9b4d02d 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1 + +* Support the latest version of `package:dart_style`. + ## 1.0.0 First full release. At this point all changes until `2.0.0` will be backwards diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index d79244b37..5124be098 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.0 +version: 1.0.1 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -9,7 +9,7 @@ environment: dependencies: analyzer: '>=0.29.1 <0.30.0' - dart_style: ^0.2.10 + dart_style: '>=0.2.10 <2.0.0' func: ^0.1.0 matcher: ^0.12.0+2 meta: ^1.0.2 From fa167785db468e0638803329ec49bacbbec043b4 Mon Sep 17 00:00:00 2001 From: Dan Rubel Date: Tue, 2 May 2017 14:18:42 -0400 Subject: [PATCH 053/271] Update analyzer (dart-lang/code_builder#108) * upgrade to new analyzer API * bump version to 1.0.2 * dartfmt unrelated file from earlier PR to make travis happy * only check dartfmt on stable --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/lib/src/builders/method.dart | 10 +++++----- pkgs/code_builder/lib/src/tokens.dart | 12 ++++++------ pkgs/code_builder/pubspec.yaml | 4 ++-- pkgs/code_builder/test/e2e_test.dart | 5 ++--- pkgs/code_builder/tool/presubmit.sh | 18 +++++++++++------- 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index aa9b4d02d..5cc27467d 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.2 + +* update internals to use newer analyzer API + ## 1.0.1 * Support the latest version of `package:dart_style`. diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart index e1605cd80..270bc995c 100644 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ b/pkgs/code_builder/lib/src/builders/method.dart @@ -35,19 +35,19 @@ ConstructorBuilder constructorNamed( /// Various types of modifiers for methods. class MethodModifier implements ValidMethodMember { static const MethodModifier asAsync = const MethodModifier._( - 'async', + Keyword.ASYNC, false, ); static const MethodModifier asAsyncStar = const MethodModifier._( - 'async', + Keyword.ASYNC, true, ); static const MethodModifier asSyncStar = const MethodModifier._( - 'sync', + Keyword.SYNC, true, ); - final String _keyword; + final Keyword _keyword; const MethodModifier._(this._keyword, this.isStar); @@ -56,7 +56,7 @@ class MethodModifier implements ValidMethodMember { final bool isStar; - Token keyword() => new StringToken(TokenType.KEYWORD, _keyword, 0); + Token keyword() => new KeywordToken(_keyword, 0); } /// Short-hand for `new MethodBuilder.getter(...)`. diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index b0464dc47..d47f5b163 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -15,13 +15,13 @@ final Token $as = new KeywordToken(Keyword.AS, 0); final Token $assert = new KeywordToken(Keyword.ASSERT, 0); /// The `async` token. -final Token $async = new StringToken(TokenType.KEYWORD, 'async', 0); +final Token $async = new KeywordToken(Keyword.ASYNC, 0); /// The `@` token. final Token $at = new Token(TokenType.AT, 0); /// The `await` token. -final Token $await = new StringToken(TokenType.KEYWORD, 'await', 0); +final Token $await = new KeywordToken(Keyword.AWAIT, 0); /// The `break` token. final Token $break = new KeywordToken(Keyword.BREAK, 0); @@ -96,7 +96,7 @@ final Token $switch = new KeywordToken(Keyword.SWITCH, 0); final Token $super = new KeywordToken(Keyword.SUPER, 0); /// The `yield` token. -final Token $yield = new StringToken(TokenType.KEYWORD, 'yield', 0); +final Token $yield = new KeywordToken(Keyword.YIELD, 0); /// The `while` keyword. final Token $while = new KeywordToken(Keyword.WHILE, 0); @@ -110,7 +110,7 @@ final Token $and = new Token(TokenType.AMPERSAND_AMPERSAND, 0); final Token $star = $multiply; /// The `hide` token. -final Token $hide = new StringToken(TokenType.KEYWORD, 'hide', 0); +final Token $hide = new KeywordToken(Keyword.HIDE, 0); /// The `implements` token. final Token $implements = new KeywordToken(Keyword.IMPLEMENTS, 0); @@ -149,7 +149,7 @@ final Token $null = new KeywordToken(Keyword.NULL, 0); final Token $nullAwareEquals = new Token(TokenType.QUESTION_QUESTION_EQ, 0); /// The `of` token. -final Token $of = new StringToken(TokenType.KEYWORD, 'of', 0); +final Token $of = new KeywordToken(Keyword.OF, 0); /// The `||` token. final Token $or = new Token(TokenType.BAR_BAR, 0); @@ -182,7 +182,7 @@ final Token $return = new KeywordToken(Keyword.RETURN, 0); final Token $semicolon = new Token(TokenType.SEMICOLON, 0); /// The `show` token. -final Token $show = new StringToken(TokenType.KEYWORD, 'show', 0); +final Token $show = new KeywordToken(Keyword.SHOW, 0); /// The `static` token. final Token $static = new KeywordToken(Keyword.STATIC, 0); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 5124be098..e6cc381a0 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.1 +version: 1.0.2 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -8,7 +8,7 @@ environment: sdk: '>=1.22.0 <2.0.0' dependencies: - analyzer: '>=0.29.1 <0.30.0' + analyzer: '>=0.29.11 <0.30.0' dart_style: '>=0.2.10 <2.0.0' func: ^0.1.0 matcher: ^0.12.0+2 diff --git a/pkgs/code_builder/test/e2e_test.dart b/pkgs/code_builder/test/e2e_test.dart index 482eccfc5..356e25e29 100644 --- a/pkgs/code_builder/test/e2e_test.dart +++ b/pkgs/code_builder/test/e2e_test.dart @@ -88,9 +88,8 @@ void main() { ..addMethod(new MethodBuilder( 'instantiateAndReturnNamedThing', returnType: thingRef, - ) - ..addStatement( - thingRef.newInstance([], constructor: 'named').asReturn()))); + )..addStatement( + thingRef.newInstance([], constructor: 'named').asReturn()))); expect( lib, equalsSource( diff --git a/pkgs/code_builder/tool/presubmit.sh b/pkgs/code_builder/tool/presubmit.sh index 8606c3438..ba3c275c1 100755 --- a/pkgs/code_builder/tool/presubmit.sh +++ b/pkgs/code_builder/tool/presubmit.sh @@ -3,14 +3,18 @@ # Make sure dartfmt is run on everything # This assumes you have dart_style as a dev_dependency echo "Checking dartfmt..." -NEEDS_DARTFMT="$(find lib test -name "*.dart" | xargs dartfmt -n)" -if [[ ${NEEDS_DARTFMT} != "" ]] -then - echo "FAILED" - echo "${NEEDS_DARTFMT}" - exit 1 +if [ "$TRAVIS_DART_VERSION" = "stable" ]; then + NEEDS_DARTFMT="$(find lib test -name "*.dart" | xargs dartfmt -n)" + if [[ ${NEEDS_DARTFMT} != "" ]] + then + echo "FAILED" + echo "${NEEDS_DARTFMT}" + exit 1 + fi + echo "PASSED" +else + echo "SKIPPED" fi -echo "PASSED" # Make sure we pass the analyzer echo "Checking dartanalyzer..." From f8d116b2a731c3d2d0434fa61733efb6b6c178cc Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 12 May 2017 07:47:17 -1000 Subject: [PATCH 054/271] Support latest pkg/analyzer and pkg/func (dart-lang/code_builder#110) Closes https://github.com/dart-lang/code_builder/issues/107 --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/pubspec.yaml | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 5cc27467d..6c55b9970 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.3 + +* Support latest `pkg/analyzer` and `pkg/func`. + ## 1.0.2 * update internals to use newer analyzer API diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index e6cc381a0..f6cdf9741 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.2 +version: 1.0.3 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -8,9 +8,9 @@ environment: sdk: '>=1.22.0 <2.0.0' dependencies: - analyzer: '>=0.29.11 <0.30.0' + analyzer: '>=0.29.11 <0.31.0' dart_style: '>=0.2.10 <2.0.0' - func: ^0.1.0 + func: '>=0.1.0 <2.0.0' matcher: ^0.12.0+2 meta: ^1.0.2 From cb29bfd3576fdff33378e58ac3e89aa830f79ee6 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Fri, 16 Jun 2017 11:33:27 -0400 Subject: [PATCH 055/271] Add support for `is`, `is!` expressions (dart-lang/code_builder#111) * FieldBuilders now works to-level * Ran dartfmt * asThrow on ExpressionBuilder * Removed asThrow * Added isInstanceOf, isNotInstanceOf, and corresponding tests. Also added a .gitignore rule to exclude the `.idea` directory, for convenience's sake. * Undo .gitignore change * Undo .gitignore change, remove IntelliJ metadata * Removed isNotInstanceOf --- .../lib/src/builders/expression.dart | 8 +++++++ .../builders/expression/is_instance_of.dart | 22 +++++++++++++++++++ pkgs/code_builder/lib/src/tokens.dart | 3 +++ .../test/builders/is_instance_of_test.dart | 20 +++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 pkgs/code_builder/lib/src/builders/expression/is_instance_of.dart create mode 100644 pkgs/code_builder/test/builders/is_instance_of_test.dart diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart index dbb32cbdc..faa80ef0b 100644 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ b/pkgs/code_builder/lib/src/builders/expression.dart @@ -26,6 +26,7 @@ part 'expression/cascade.dart'; part 'expression/cast.dart'; part 'expression/index.dart'; part 'expression/invocation.dart'; +part 'expression/is_instance_of.dart'; part 'expression/negate.dart'; part 'expression/operators.dart'; part 'expression/return.dart'; @@ -294,6 +295,10 @@ abstract class AbstractExpressionMixin implements ExpressionBuilder { return invocation; } + @override + ExpressionBuilder isInstanceOf(TypeBuilder type) => + new _IsInstanceOfExpression(this, type); + @override ExpressionBuilder negate() => new _NegateExpression(this); @@ -447,6 +452,9 @@ abstract class ExpressionBuilder Map namedArguments, }); + /// Returns as an [ExpressionBuilder] indicating whether this expression is an instance of [type], using the `is` operator. + ExpressionBuilder isInstanceOf(TypeBuilder type); + /// Returns as an [ExpressionBuilder] negating using the `!` operator. ExpressionBuilder negate(); diff --git a/pkgs/code_builder/lib/src/builders/expression/is_instance_of.dart b/pkgs/code_builder/lib/src/builders/expression/is_instance_of.dart new file mode 100644 index 000000000..9fd38fbfe --- /dev/null +++ b/pkgs/code_builder/lib/src/builders/expression/is_instance_of.dart @@ -0,0 +1,22 @@ +// 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. + +part of code_builder.src.builders.expression; + +class _IsInstanceOfExpression extends AbstractExpressionMixin + with TopLevelMixin { + final ExpressionBuilder _expression; + final TypeBuilder _type; + + _IsInstanceOfExpression(this._expression, this._type); + + @override + AstNode buildAst([Scope scope]) => buildExpression(scope); + + @override + Expression buildExpression([Scope scope]) { + return astFactory.isExpression( + _expression.buildExpression(scope), $is, null, _type.buildType(scope)); + } +} diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart index d47f5b163..65a620709 100644 --- a/pkgs/code_builder/lib/src/tokens.dart +++ b/pkgs/code_builder/lib/src/tokens.dart @@ -118,6 +118,9 @@ final Token $implements = new KeywordToken(Keyword.IMPLEMENTS, 0); /// The `in` token. final Token $in = new KeywordToken(Keyword.IN, 0); +/// The `is` token. +final Token $is = new KeywordToken(Keyword.IS, 0); + /// The `library` token. final Token $library = new KeywordToken(Keyword.LIBRARY, 0); diff --git a/pkgs/code_builder/test/builders/is_instance_of_test.dart b/pkgs/code_builder/test/builders/is_instance_of_test.dart new file mode 100644 index 000000000..20bbf6c85 --- /dev/null +++ b/pkgs/code_builder/test/builders/is_instance_of_test.dart @@ -0,0 +1,20 @@ +// 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. + +import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/testing.dart'; +import 'package:test/test.dart'; + +final TypeBuilder _barType = new TypeBuilder('Bar'); + +void main() { + test('should emit an `is` expression', () { + expect(reference('foo').isInstanceOf(_barType), equalsSource('foo is Bar')); + }); + + test('should emit an `is!` expression', () { + expect(reference('foo').isInstanceOf(_barType).negate(), + equalsSource('!(foo is Bar)')); + }); +} From bf132dbfd296467ea401f2f4681eab42f8303ba0 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 16 Jun 2017 08:47:22 -0700 Subject: [PATCH 056/271] Prepare for 1.0.4. (dart-lang/code_builder#112) --- pkgs/code_builder/CHANGELOG.md | 13 ++++++++++++- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 6c55b9970..07dbf73c8 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,10 +1,21 @@ +## 1.0.4 + +* Added `isInstanceOf` to `ExpressionBuilder`, which performs an `is` check: + +```dart +expect( + reference('foo').isInstanceOf(_barType), + equalsSource('foo is Bar'), +); +``` + ## 1.0.3 * Support latest `pkg/analyzer` and `pkg/func`. ## 1.0.2 -* update internals to use newer analyzer API +* Update internals to use newer analyzer API ## 1.0.1 diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index f6cdf9741..4453fd355 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.3 +version: 1.0.4 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From c1fe78ffddc16232bef48f3441df561ed3758fc1 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 26 Jun 2017 20:01:14 -0700 Subject: [PATCH 057/271] Started on V2, not using ASTs... (dart-lang/code_builder#115) * Initial 2.0. * Add some classes. * Start using BuiltCollection|Value. * Add generics, inheritance. * Add methods (without bodies). * Added method bodies. * Further augment methods. * Add method parameters. * Added methods, bodies, and constructors. * Fix travis. * Add annotation support. * Add fields and constructor initializers. * Add e2e example. --- pkgs/code_builder/.analysis_options | 29 - pkgs/code_builder/.travis.yml | 27 +- pkgs/code_builder/README.md | 77 +- pkgs/code_builder/analysis_options.yaml | 54 ++ pkgs/code_builder/doc/SHORT_LINKS.md | 10 - pkgs/code_builder/lib/code_builder.dart | 68 +- pkgs/code_builder/lib/dart/async.dart | 47 -- pkgs/code_builder/lib/dart/core.dart | 234 ------ pkgs/code_builder/lib/src/analyzer_patch.dart | 65 -- pkgs/code_builder/lib/src/base.dart | 9 + .../lib/src/builders/annotation.dart | 49 -- pkgs/code_builder/lib/src/builders/class.dart | 295 ------- .../lib/src/builders/expression.dart | 689 ---------------- .../lib/src/builders/expression/assert.dart | 27 - .../lib/src/builders/expression/assign.dart | 79 -- .../lib/src/builders/expression/await.dart | 22 - .../lib/src/builders/expression/cascade.dart | 23 - .../lib/src/builders/expression/cast.dart | 24 - .../lib/src/builders/expression/index.dart | 25 - .../src/builders/expression/invocation.dart | 114 --- .../builders/expression/is_instance_of.dart | 22 - .../lib/src/builders/expression/negate.dart | 39 - .../src/builders/expression/operators.dart | 69 -- .../lib/src/builders/expression/raw.dart | 28 - .../lib/src/builders/expression/return.dart | 23 - .../lib/src/builders/expression/ternary.dart | 31 - .../lib/src/builders/expression/throw.dart | 22 - .../lib/src/builders/expression/yield.dart | 25 - pkgs/code_builder/lib/src/builders/field.dart | 178 ----- pkgs/code_builder/lib/src/builders/file.dart | 301 ------- .../code_builder/lib/src/builders/method.dart | 756 ------------------ .../lib/src/builders/parameter.dart | 260 ------ .../lib/src/builders/reference.dart | 122 --- .../code_builder/lib/src/builders/shared.dart | 28 - .../lib/src/builders/statement.dart | 120 --- .../lib/src/builders/statement/block.dart | 32 - .../lib/src/builders/statement/break.dart | 30 - .../lib/src/builders/statement/for.dart | 121 --- .../lib/src/builders/statement/if.dart | 101 --- .../lib/src/builders/statement/raw.dart | 29 - .../lib/src/builders/statement/switch.dart | 169 ---- .../lib/src/builders/statement/while.dart | 44 - pkgs/code_builder/lib/src/builders/type.dart | 152 ---- .../lib/src/builders/type/new_instance.dart | 77 -- .../lib/src/builders/type/type_def.dart | 61 -- pkgs/code_builder/lib/src/emitter.dart | 322 ++++++++ pkgs/code_builder/lib/src/matchers.dart | 50 ++ .../lib/src/mixins/annotations.dart | 15 + pkgs/code_builder/lib/src/mixins/dartdoc.dart | 15 + .../code_builder/lib/src/mixins/generics.dart | 17 + pkgs/code_builder/lib/src/pretty_printer.dart | 122 --- pkgs/code_builder/lib/src/scope.dart | 117 --- .../lib/src/specs/annotation.dart | 37 + .../lib/src/specs/annotation.g.dart | 89 +++ pkgs/code_builder/lib/src/specs/class.dart | 122 +++ pkgs/code_builder/lib/src/specs/class.g.dart | 312 ++++++++ pkgs/code_builder/lib/src/specs/code.dart | 41 + pkgs/code_builder/lib/src/specs/code.g.dart | 107 +++ .../lib/src/specs/constructor.dart | 111 +++ .../lib/src/specs/constructor.g.dart | 334 ++++++++ pkgs/code_builder/lib/src/specs/field.dart | 99 +++ pkgs/code_builder/lib/src/specs/field.g.dart | 221 +++++ pkgs/code_builder/lib/src/specs/method.dart | 202 +++++ pkgs/code_builder/lib/src/specs/method.g.dart | 574 +++++++++++++ .../code_builder/lib/src/specs/reference.dart | 54 ++ .../lib/src/specs/type_reference.dart | 65 ++ .../lib/src/specs/type_reference.g.dart | 148 ++++ pkgs/code_builder/lib/src/tokens.dart | 215 ----- pkgs/code_builder/lib/src/visitors.dart | 79 ++ pkgs/code_builder/lib/testing.dart | 100 --- pkgs/code_builder/pubspec.yaml | 14 +- .../test/builders/break_test.dart | 13 - .../test/builders/class_test.dart | 199 ----- .../test/builders/expression_test.dart | 449 ----------- .../test/builders/field_test.dart | 37 - .../code_builder/test/builders/file_test.dart | 103 --- .../test/builders/is_instance_of_test.dart | 20 - .../test/builders/method_test.dart | 305 ------- .../test/builders/parameter_test.dart | 65 -- .../test/builders/shared_test.dart | 21 - .../test/builders/statement_test.dart | 155 ---- .../test/builders/switch_test.dart | 56 -- .../code_builder/test/builders/type_test.dart | 161 ---- .../code_builder/test/e2e/injection_test.dart | 48 ++ pkgs/code_builder/test/e2e_test.dart | 118 --- pkgs/code_builder/test/scope_test.dart | 88 -- pkgs/code_builder/test/specs/class_test.dart | 337 ++++++++ pkgs/code_builder/test/specs/field_test.dart | 61 ++ pkgs/code_builder/test/specs/method_test.dart | 315 ++++++++ pkgs/code_builder/tool/build.dart | 20 + pkgs/code_builder/tool/presubmit.sh | 42 - .../tool/test_all_for_coverage.dart | 33 - pkgs/code_builder/tool/watch.dart | 20 + 93 files changed, 3926 insertions(+), 7129 deletions(-) delete mode 100644 pkgs/code_builder/.analysis_options create mode 100644 pkgs/code_builder/analysis_options.yaml delete mode 100644 pkgs/code_builder/doc/SHORT_LINKS.md delete mode 100644 pkgs/code_builder/lib/dart/async.dart delete mode 100644 pkgs/code_builder/lib/dart/core.dart delete mode 100644 pkgs/code_builder/lib/src/analyzer_patch.dart create mode 100644 pkgs/code_builder/lib/src/base.dart delete mode 100644 pkgs/code_builder/lib/src/builders/annotation.dart delete mode 100644 pkgs/code_builder/lib/src/builders/class.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/assert.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/assign.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/await.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/cascade.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/cast.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/index.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/invocation.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/is_instance_of.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/negate.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/operators.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/raw.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/return.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/ternary.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/throw.dart delete mode 100644 pkgs/code_builder/lib/src/builders/expression/yield.dart delete mode 100644 pkgs/code_builder/lib/src/builders/field.dart delete mode 100644 pkgs/code_builder/lib/src/builders/file.dart delete mode 100644 pkgs/code_builder/lib/src/builders/method.dart delete mode 100644 pkgs/code_builder/lib/src/builders/parameter.dart delete mode 100644 pkgs/code_builder/lib/src/builders/reference.dart delete mode 100644 pkgs/code_builder/lib/src/builders/shared.dart delete mode 100644 pkgs/code_builder/lib/src/builders/statement.dart delete mode 100644 pkgs/code_builder/lib/src/builders/statement/block.dart delete mode 100644 pkgs/code_builder/lib/src/builders/statement/break.dart delete mode 100644 pkgs/code_builder/lib/src/builders/statement/for.dart delete mode 100644 pkgs/code_builder/lib/src/builders/statement/if.dart delete mode 100644 pkgs/code_builder/lib/src/builders/statement/raw.dart delete mode 100644 pkgs/code_builder/lib/src/builders/statement/switch.dart delete mode 100644 pkgs/code_builder/lib/src/builders/statement/while.dart delete mode 100644 pkgs/code_builder/lib/src/builders/type.dart delete mode 100644 pkgs/code_builder/lib/src/builders/type/new_instance.dart delete mode 100644 pkgs/code_builder/lib/src/builders/type/type_def.dart create mode 100644 pkgs/code_builder/lib/src/emitter.dart create mode 100644 pkgs/code_builder/lib/src/matchers.dart create mode 100644 pkgs/code_builder/lib/src/mixins/annotations.dart create mode 100644 pkgs/code_builder/lib/src/mixins/dartdoc.dart create mode 100644 pkgs/code_builder/lib/src/mixins/generics.dart delete mode 100644 pkgs/code_builder/lib/src/pretty_printer.dart delete mode 100644 pkgs/code_builder/lib/src/scope.dart create mode 100644 pkgs/code_builder/lib/src/specs/annotation.dart create mode 100644 pkgs/code_builder/lib/src/specs/annotation.g.dart create mode 100644 pkgs/code_builder/lib/src/specs/class.dart create mode 100644 pkgs/code_builder/lib/src/specs/class.g.dart create mode 100644 pkgs/code_builder/lib/src/specs/code.dart create mode 100644 pkgs/code_builder/lib/src/specs/code.g.dart create mode 100644 pkgs/code_builder/lib/src/specs/constructor.dart create mode 100644 pkgs/code_builder/lib/src/specs/constructor.g.dart create mode 100644 pkgs/code_builder/lib/src/specs/field.dart create mode 100644 pkgs/code_builder/lib/src/specs/field.g.dart create mode 100644 pkgs/code_builder/lib/src/specs/method.dart create mode 100644 pkgs/code_builder/lib/src/specs/method.g.dart create mode 100644 pkgs/code_builder/lib/src/specs/reference.dart create mode 100644 pkgs/code_builder/lib/src/specs/type_reference.dart create mode 100644 pkgs/code_builder/lib/src/specs/type_reference.g.dart delete mode 100644 pkgs/code_builder/lib/src/tokens.dart create mode 100644 pkgs/code_builder/lib/src/visitors.dart delete mode 100644 pkgs/code_builder/lib/testing.dart delete mode 100644 pkgs/code_builder/test/builders/break_test.dart delete mode 100644 pkgs/code_builder/test/builders/class_test.dart delete mode 100644 pkgs/code_builder/test/builders/expression_test.dart delete mode 100644 pkgs/code_builder/test/builders/field_test.dart delete mode 100644 pkgs/code_builder/test/builders/file_test.dart delete mode 100644 pkgs/code_builder/test/builders/is_instance_of_test.dart delete mode 100644 pkgs/code_builder/test/builders/method_test.dart delete mode 100644 pkgs/code_builder/test/builders/parameter_test.dart delete mode 100644 pkgs/code_builder/test/builders/shared_test.dart delete mode 100644 pkgs/code_builder/test/builders/statement_test.dart delete mode 100644 pkgs/code_builder/test/builders/switch_test.dart delete mode 100644 pkgs/code_builder/test/builders/type_test.dart create mode 100644 pkgs/code_builder/test/e2e/injection_test.dart delete mode 100644 pkgs/code_builder/test/e2e_test.dart delete mode 100644 pkgs/code_builder/test/scope_test.dart create mode 100644 pkgs/code_builder/test/specs/class_test.dart create mode 100644 pkgs/code_builder/test/specs/field_test.dart create mode 100644 pkgs/code_builder/test/specs/method_test.dart create mode 100644 pkgs/code_builder/tool/build.dart delete mode 100755 pkgs/code_builder/tool/presubmit.sh delete mode 100644 pkgs/code_builder/tool/test_all_for_coverage.dart create mode 100644 pkgs/code_builder/tool/watch.dart diff --git a/pkgs/code_builder/.analysis_options b/pkgs/code_builder/.analysis_options deleted file mode 100644 index 1196b5dfa..000000000 --- a/pkgs/code_builder/.analysis_options +++ /dev/null @@ -1,29 +0,0 @@ -analyzer: - strong-mode: true -linter: - rules: - # Errors - - avoid_empty_else - - control_flow_in_finally - - empty_statements - - test_types_in_equals - - throw_in_finally - - valid_regexps - - # Style - - annotate_overrides - - avoid_init_to_null - - avoid_return_types_on_setters - - await_only_futures - - camel_case_types - - comment_references - - empty_catches - - empty_constructor_bodies - - hash_and_equals - - library_prefixes - # This convention is broken on purpose in parts of the code. - # - non_constant_identifier_names - - prefer_is_not_empty - - slash_for_doc_comments - - type_init_formals - - unrelated_type_equality_checks diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index e3be4eb6e..363e12b64 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -1,7 +1,28 @@ language: dart - dart: - - 1.22.0 + - dev - stable +cache: + directories: + - $HOME/.pub-cache + +branches: + only: [master, v2] + +# Check for analysis issues, run the test cases, and ensure `dartfmt` is run. +dart_task: + - test: --platform vm + - dartanalyzer + - dartfmt -script: ./tool/presubmit.sh +# The Dart language is constantly being worked on, and sometimes the dev and +# stable builds don't agree on what is considered formatted or what is analysis +# warning free (though this does not effect _using_ the library, likely). +# +# We exclude `dev` from analysis and formatting checks. +matrix: + allow_failure: + - dart: dev + dart_task: dartfmt + - dart: dev + dart_task: dartanalyzer diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 9eeefbc22..54b9533b6 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -6,78 +6,7 @@ `code_builder` is a fluent Dart API for generating valid Dart source code. -Code generation was traditionally done through a series of -package-specific string concatenations which usually results in messy -and sometimes invalid Dart code that is not easily readable and is very -difficult to refactor. +**Experimental Branch for _2.0_**: +- Drops use of the `package:analyzer` API. +- Uses a proper [builder pattern](https://github.com/square/javapoet). -`code_builder` uses the [analyzer](analyzer) package to create real Dart -language ASTs, which, while not guaranteed to be correct, always follows -the analyzer's own understood format. - -[analyzer]: https://pub.dartlang.org/packages/analyzer - -## Contributing - -* Read and help us document common patterns over [at the wiki][wiki]. -* Is there a *bug* in the code? [File an issue][issue]. - -If a feature is missing (the Dart language is always evolving) or you'd like an -easier or better way to do something, consider [opening a pull request][pull]. -You can always [file an issue][issue], but generally speaking feature requests -will be on a best-effort basis. - -[wiki]: https://github.com/dart-lang/code_builder/wiki -[issue]: https://github.com/dart-lang/code_builder/issues -[pull]: https://github.com/dart-lang/code_builder/pulls - -## Usage - -Code builder has a narrow and user-friendly API. - -For example creating a class with a method: - -```dart -var base = reference('Organism'); -var clazz = new ClassBuilder('Animal', asExtends: base); -clazz.addMethod( - new MethodBuilder.returnVoid( - 'eat', - returns: reference('print').call([literal('Yum')]), - ), -); -``` - -Outputs: -```dart -class Animal extends Organism { - void eat() => print('Yum!'); -} -``` - -Have a complicated set of dependencies for your generated code? -`code_builder` supports automatic scoping of your ASTs to automatically -use prefixes to avoid symbol conflicts: - -```dart -var lib = new LibraryBuilder.scope() - ..addMembers([ - new MethodBuilder( - 'doThing', - returnType: reference('Thing', 'package:thing/thing.dart'), - ), - new MethodBuilder( - 'doOtherThing', - returnType: reference('Thing', 'package:thing/alternative.dart'), - ), - ]); -``` - -Outputs: -```dart -import 'package:thing/thing.dart' as _i1; -import 'package:thing/alternative.dart' as _i2; - -_i1.Thing doThing() {} -_i2.Thing doOtherThing() {} -``` diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml new file mode 100644 index 000000000..cf2c8917f --- /dev/null +++ b/pkgs/code_builder/analysis_options.yaml @@ -0,0 +1,54 @@ +analyzer: + strong-mode: + implicit-casts: false + implicit-dynamic: false + +linter: + rules: + # Error Rules + - avoid_empty_else + - comment_references + - control_flow_in_finally + - empty_statements + - hash_and_equals + - invariant_booleans + - iterable_contains_unrelated_type + - list_remove_unrelated_type + - no_adjacent_strings_in_list + - no_duplicate_case_values + - test_types_in_equals + - throw_in_finally + - unrelated_type_equality_checks + - valid_regexps + + # Style Rules + - annotate_overrides + - avoid_init_to_null + - avoid_return_types_on_setters + - camel_case_types + - cascade_invocations + - constant_identifier_names + - directives_ordering + - empty_catches + - empty_constructor_bodies + - implementation_imports + - library_names + - library_prefixes + - non_constant_identifier_names + - omit_local_variable_types + - only_throw_errors + - prefer_adjacent_string_concatenation + - prefer_collection_literals + - prefer_const_constructors + - prefer_contains + - prefer_final_fields + - prefer_final_locals + - prefer_initializing_formals + - prefer_interpolation_to_compose_strings + - prefer_is_empty + - prefer_is_not_empty + - recursive_getters + - slash_for_doc_comments + - type_init_formals + - unnecessary_brace_in_string_interps + - unnecessary_this diff --git a/pkgs/code_builder/doc/SHORT_LINKS.md b/pkgs/code_builder/doc/SHORT_LINKS.md deleted file mode 100644 index fc7063175..000000000 --- a/pkgs/code_builder/doc/SHORT_LINKS.md +++ /dev/null @@ -1,10 +0,0 @@ -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 - \ No newline at end of file diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 8fd41c75b..85b644e2c 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -1,58 +1,16 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. -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, list, map, ExpressionBuilder, InvocationBuilder; -export 'src/builders/field.dart' - show varConst, varField, varFinal, FieldBuilder; -export 'src/builders/file.dart' - show - ExportBuilder, - ImportBuilder, - LibraryBuilder, - PartBuilder, - PartOfBuilder, - UriDirectiveBuilder; -export 'src/builders/method.dart' - show - constructor, - constructorNamed, - getter, - setter, - thisField, - lambda, - method, - named, - ConstructorBuilder, - MethodBuilder, - MethodModifier, - ValidMethodMember; -export 'src/builders/parameter.dart' - show parameter, FunctionParameterBuilder, 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 - breakStatement, - ifThen, - elseIf, - elseThen, - returnVoid, - switchCase, - switchDefault, - switchStatement, - ForStatementBuilder, - IfStatementBuilder, - StatementBuilder, - SwitchCaseBuilder, - SwitchDefaultCaseBuilder, - SwitchStatementBuilder, - WhileStatementBuilder; -export 'src/builders/type.dart' - show NewInstanceBuilder, TypeBuilder, TypeDefBuilder; +export 'src/base.dart' show 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 Code, CodeBuilder; +export 'src/specs/constructor.dart' show Constructor, ConstructorBuilder; +export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; +export 'src/specs/method.dart' + show Method, MethodBuilder, MethodType, Parameter, ParameterBuilder; +export 'src/specs/reference.dart' show Reference; +export 'src/specs/type_reference.dart' show TypeReference, TypeReferenceBuilder; diff --git a/pkgs/code_builder/lib/dart/async.dart b/pkgs/code_builder/lib/dart/async.dart deleted file mode 100644 index 68d0b27db..000000000 --- a/pkgs/code_builder/lib/dart/async.dart +++ /dev/null @@ -1,47 +0,0 @@ -// 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'); - - /// References [dart_async.Stream]. - final ReferenceBuilder Stream = _ref('Stream'); - - /// References [dart_async.StreamSubscription]. - final ReferenceBuilder StreamSubscription = _ref('StreamSubscription'); - - DartAsync._(); - - static ReferenceBuilder _ref(String name) => reference(name, 'dart:async'); -} diff --git a/pkgs/code_builder/lib/dart/core.dart b/pkgs/code_builder/lib/dart/core.dart deleted file mode 100644 index 5066e2cfe..000000000 --- a/pkgs/code_builder/lib/dart/core.dart +++ /dev/null @@ -1,234 +0,0 @@ -// 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:core` 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/core.dart'; -/// -/// All references are _namespaced_ under [lib$core]. Try it: -/// // Outputs: print('Hello World') -/// core.print.call([literal('Hello World')]); -/// -/// If you are [missing a reference from `dart:core`](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.core; - -import 'dart:core' as dart_core; - -import 'package:code_builder/code_builder.dart'; - -/// A namespace for references in `dart:core`. -final DartCore lib$core = new DartCore._(); - -/// References to the `dart:core` library for code generation. See [lib$core]. -class DartCore { - /// References [dart_core.bool]. - final ReferenceBuilder bool = _ref('bool'); - - /// References [dart_core.identical]. - final ReferenceBuilder identical = _ref('identical'); - - /// References [dart_core.deprecated]. - final ReferenceBuilder deprecated = _ref('deprecated'); - - /// References [dart_core.override]. - final ReferenceBuilder override = _ref('override'); - - /// References [dart_core.print]. - final ReferenceBuilder print = _ref('print'); - - /// References [dart_core.identityHashCode]. - final ReferenceBuilder identityHashCode = _ref('identityHashCode'); - - /// References [dart_core.int]. - final ReferenceBuilder int = _ref('int'); - - /// References [dart_core.num]. - final ReferenceBuilder num = _ref('num'); - - /// References [dart_core.AbstractClassInstantiationError]. - final ReferenceBuilder AbstractClassInstantiationError = - _ref('AbstractClassInstantiationError'); - - /// References [dart_core.ArgumentError]. - final ReferenceBuilder ArgumentError = _ref('ArgumentError'); - - /// References [dart_core.AssertionError]. - final ReferenceBuilder AssertionError = _ref('AssertionError'); - - /// References [dart_core.BidirectionalIterator]. - final ReferenceBuilder BidirectionalIterator = _ref('BidirectionalIterator'); - - /// References [dart_core.CastError]. - final ReferenceBuilder CastError = _ref('CastError'); - - /// References [dart_core.Comparable]. - final ReferenceBuilder Comparable = _ref('Comparable'); - - /// References [dart_core.Comparator] - final ReferenceBuilder Comparator = _ref('Comparator'); - - /// References [dart_core.ConcurrentModificationError]. - final ReferenceBuilder ConcurrentModificationError = - _ref('ConcurrentModificationError'); - - /// References [dart_core.CyclicInitializationError]. - final ReferenceBuilder CyclicInitializationError = - _ref('CyclicInitializationError'); - - /// References [dart_core.DateTime]. - final ReferenceBuilder DateTime = _ref('DateTime'); - - /// References [dart_core.Deprecated]. - final ReferenceBuilder Deprecated = _ref('Deprecated'); - - /// References [dart_core.Duration]. - final ReferenceBuilder Duration = _ref('Duration'); - - /// References [dart_core.Error]. - final ReferenceBuilder Error = _ref('Error'); - - /// References [dart_core.Exception]. - final ReferenceBuilder Exception = _ref('Exception'); - - /// References [dart_core.Expando]. - final ReferenceBuilder Expando = _ref('Expando'); - - /// References [dart_core.FallThroughError]. - final ReferenceBuilder FallThroughError = _ref('FallThroughError'); - - /// References [dart_core.FormatException]. - final ReferenceBuilder FormatException = _ref('FormatException'); - - /// References [dart_core.Function]. - final ReferenceBuilder Function = _ref('Function'); - - /// References [dart_core.IndexError]. - final ReferenceBuilder IndexError = _ref('IndexError'); - - /// References [dart_core.IntegerDivisionByZeroException]. - final ReferenceBuilder IntegerDivisionByZeroException = - _ref('IntegerDivisionByZeroException'); - - /// References [dart_core.Invocation]. - final ReferenceBuilder Invocation = _ref('Invocation'); - - /// References [dart_core.Iterable]. - final ReferenceBuilder Iterable = _ref('Iterable'); - - /// References [dart_core.Iterator]. - final ReferenceBuilder Iterator = _ref('Iterator'); - - /// References [dart_core.List]. - final ReferenceBuilder List = _ref('List'); - - /// References [dart_core.Map]. - final ReferenceBuilder Map = _ref('Map'); - - /// References [dart_core.Match]. - final ReferenceBuilder Match = _ref('Match'); - - /// References [dart_core.NoSuchMethodError]. - final ReferenceBuilder NoSuchMethodError = _ref('NoSuchMethodError'); - - /// References [dart_core.Null]. - final ReferenceBuilder Null = _ref('Null'); - - /// References [dart_core.NullThrownError]. - final ReferenceBuilder NullThrownError = _ref('NullThrownError'); - - /// References [dart_core.Object]. - final ReferenceBuilder Object = _ref('Object'); - - /// References [dart_core.OutOfMemoryError]. - final ReferenceBuilder OutOfMemoryError = _ref('OutOfMemoryError'); - - /// References [dart_core.Pattern]. - final ReferenceBuilder Pattern = _ref('Pattern'); - - /// References [dart_core.RangeError]. - final ReferenceBuilder RangeError = _ref('RangeError'); - - /// References [dart_core.RegExp]. - final ReferenceBuilder RegExp = _ref('RegExp'); - - /// References [dart_core.RuneIterator]. - final ReferenceBuilder RuneIterator = _ref('RuneIterator'); - - /// References [dart_core.Runes]. - final ReferenceBuilder Runes = _ref('Runes'); - - /// References [dart_core.Set]. - final ReferenceBuilder Set = _ref('Set'); - - /// References [dart_core.Sink]. - final ReferenceBuilder Sink = _ref('Sink'); - - /// References [dart_core.StackOverflowError]. - final ReferenceBuilder StackOverflowError = _ref('StackOverflowError'); - - /// References [dart_core.StackTrace]. - final ReferenceBuilder StackTrace = _ref('StackTrace'); - - /// References [dart_core.StateError]. - final ReferenceBuilder StateError = _ref('StateError'); - - /// References [dart_core.Stopwatch]. - final ReferenceBuilder Stopwatch = _ref('Stopwatch'); - - /// References [dart_core.String]. - final ReferenceBuilder String = _ref('String'); - - /// References [dart_core.StringBuffer]. - final ReferenceBuilder StringBuffer = _ref('StringBuffer'); - - /// References [dart_core.StringSink]. - final ReferenceBuilder StringSink = _ref('StringSink'); - - /// References [dart_core.Symbol]. - final ReferenceBuilder Symbol = _ref('Symbol'); - - /// References [dart_core.Type]. - final ReferenceBuilder Type = _ref('Type'); - - /// References [dart_core.TypeError]. - final ReferenceBuilder TypeError = _ref('TypeError'); - - /// References [dart_core.UnimplementedError]. - final ReferenceBuilder UnimplementedError = _ref('UnimplementedError'); - - /// References [dart_core.UnsupportedError]. - final ReferenceBuilder UnsupportedError = _ref('UnsupportedError'); - - /// References [dart_core.Uri]. - final ReferenceBuilder Uri = _ref('Uri'); - - /// References [dart_core.UriData]. - final ReferenceBuilder UriData = _ref('UriData'); - - /// References `dynamic` type for returning any in a method. - /// - /// **NOTE**: As a language limitation, this cannot be named `dynamic`. - final TypeBuilder $dynamic = new TypeBuilder('dynamic'); - - /// References `void` type for returning nothing in a method. - /// - /// **NOTE**: As a language limitation, this cannot be named `void`. - final TypeBuilder $void = new TypeBuilder('void'); - - DartCore._(); - - static ReferenceBuilder _ref(dart_core.String name) { - return reference(name, 'dart:core'); - } -} diff --git a/pkgs/code_builder/lib/src/analyzer_patch.dart b/pkgs/code_builder/lib/src/analyzer_patch.dart deleted file mode 100644 index b4a71495a..000000000 --- a/pkgs/code_builder/lib/src/analyzer_patch.dart +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -import 'package:analyzer/src/generated/java_core.dart'; - -/// Implements both old-API [PrintWriter] and new-API [StringBuffer]. -/// -/// This makes it easier to re-use our `pretty_printer` until analyzer updates. -class PrintBuffer implements PrintWriter, StringBuffer { - final StringBuffer _impl = new StringBuffer(); - - @override - bool get isEmpty => _impl.isEmpty; - - @override - bool get isNotEmpty => _impl.isNotEmpty; - - @override - int get length => _impl.length; - - @override - void clear() {} - - @override - void newLine() { - _impl.writeln(); - } - - @override - void print(x) { - _impl.write(x); - } - - @override - void printf(String fmt, List args) => throw new UnimplementedError(); - - @override - void println(String s) { - _impl.writeln(s); - } - - @override - String toString() => _impl.toString(); - - @override - void write(Object obj) { - _impl.write(obj); - } - - @override - void writeAll(Iterable objects, [String separator = ""]) { - _impl.writeAll(objects); - } - - @override - void writeCharCode(int charCode) { - _impl.writeCharCode(charCode); - } - - @override - void writeln([Object obj = ""]) { - _impl.writeln(obj); - } -} diff --git a/pkgs/code_builder/lib/src/base.dart b/pkgs/code_builder/lib/src/base.dart new file mode 100644 index 000000000..9bd91bc3f --- /dev/null +++ b/pkgs/code_builder/lib/src/base.dart @@ -0,0 +1,9 @@ +// 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 'visitors.dart'; + +abstract class Spec { + R accept(SpecVisitor visitor); +} diff --git a/pkgs/code_builder/lib/src/builders/annotation.dart b/pkgs/code_builder/lib/src/builders/annotation.dart deleted file mode 100644 index 404088af3..000000000 --- a/pkgs/code_builder/lib/src/builders/annotation.dart +++ /dev/null @@ -1,49 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:code_builder/src/builders/class.dart'; -import 'package:code_builder/src/builders/parameter.dart'; -import 'package:code_builder/src/builders/shared.dart'; - -/// Builds an [Annotation] AST when [buildAnnotation] is invoked. -abstract class AnnotationBuilder - implements ValidClassMember, ValidParameterMember { - /// Returns an [Annotation] AST representing the builder. - Annotation buildAnnotation([Scope scope]); -} - -/// An [AstBuilder] that can be annotated with [AnnotationBuilder]. -abstract class HasAnnotations implements AstBuilder { - /// Adds [annotation] to the builder. - void addAnnotation(AnnotationBuilder annotation); - - /// Adds [annotations] to the builder. - void addAnnotations(Iterable annotations); -} - -/// Implements [HasAnnotations]. -abstract class HasAnnotationsMixin implements HasAnnotations { - final List _annotations = []; - - @override - void addAnnotation(AnnotationBuilder annotation) { - _annotations.add(annotation); - } - - @override - void addAnnotations(Iterable annotations) { - _annotations.addAll(annotations); - } - - /// Returns a [List] of all built [Annotation]s. - List buildAnnotations([Scope scope]) => _annotations - .map/**/((a) => a.buildAnnotation(scope)) - .toList(); - - /// Clones all annotations to [clone]. - void copyAnnotationsTo(HasAnnotations clone) { - clone.addAnnotations(_annotations); - } -} diff --git a/pkgs/code_builder/lib/src/builders/class.dart b/pkgs/code_builder/lib/src/builders/class.dart deleted file mode 100644 index c3aa9ecb7..000000000 --- a/pkgs/code_builder/lib/src/builders/class.dart +++ /dev/null @@ -1,295 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/src/builders/annotation.dart'; -import 'package:code_builder/src/builders/expression.dart'; -import 'package:code_builder/src/builders/field.dart'; -import 'package:code_builder/src/builders/file.dart'; -import 'package:code_builder/src/builders/method.dart'; -import 'package:code_builder/src/builders/reference.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/type.dart'; -import 'package:code_builder/src/tokens.dart'; - -/// A more short-hand way of constructing a [ClassBuilder]. -ClassBuilder clazz( - String name, [ - Iterable members = const [], -]) { - final clazz = new ClassBuilder(name); - for (final member in members) { - if (member is AnnotationBuilder) { - clazz.addAnnotation(member); - } else if (member is _TypeNameWrapper) { - if (member.extend) { - clazz.setExtends(member.type); - } else if (member.mixin) { - clazz.addMixin(member.type); - } else { - clazz.addImplement(member.type); - } - } else if (member is ConstructorBuilder) { - clazz.addConstructor(member); - } else if (member is _StaticFieldWrapper) { - var wrapped = member._member; - if (wrapped is MethodBuilder) { - clazz.addMethod(wrapped, asStatic: true); - } else { - clazz.addField(wrapped as FieldBuilder, asStatic: true); - } - } else if (member is FieldBuilder) { - clazz.addField(member); - } else if (member is MethodBuilder) { - clazz.addMethod(member); - } else { - throw new StateError('Invalid AST type: ${member.runtimeType}'); - } - } - return clazz; -} - -/// Wrap [member] to be emitted as a `static` method or field. -ValidClassMember asStatic(ValidClassMember member) { - return new _StaticFieldWrapper(member); -} - -class _StaticFieldWrapper implements ValidClassMember { - final ValidClassMember _member; - - _StaticFieldWrapper(this._member); - - @override - AstNode buildAst([Scope scope]) => - throw new UnsupportedError('Use inside varField'); -} - -/// Returns a wrapper around [type] for use with [clazz]. -_TypeNameWrapper extend(TypeBuilder type) { - return new _TypeNameWrapper( - type, - extend: true, - ); -} - -/// Returns a wrapper around [type] for use with [clazz]. -_TypeNameWrapper implement(TypeBuilder type) { - return new _TypeNameWrapper( - type, - implement: true, - ); -} - -/// Returns a wrapper around [type] for use with [clazz]. -_TypeNameWrapper mixin(TypeBuilder type) { - return new _TypeNameWrapper( - type, - mixin: true, - ); -} - -/// Lazily builds an [ClassDeclaration] AST when [buildClass] is invoked. -abstract class ClassBuilder - implements AstBuilder, HasAnnotations, TypeBuilder { - /// Returns a new [ClassBuilder] with [name]. - factory ClassBuilder( - String name, { - bool asAbstract, - TypeBuilder asExtends, - Iterable asWith, - Iterable asImplements, - }) = _ClassBuilderImpl; - - /// Adds a [constructor]. - void addConstructor(ConstructorBuilder constructor); - - /// Adds a [field]. - void addField(FieldBuilder field, {bool asStatic: false}); - - /// Adds an [interface] to implement. - void addImplement(TypeBuilder interface); - - /// Adds [interfaces] to implement. - void addImplements(Iterable interfaces); - - /// Adds a [method]. - void addMethod(MethodBuilder method, {bool asStatic: false}); - - /// Adds a [mixin]. - void addMixin(TypeBuilder mixin); - - /// Adds [mixins]. - void addMixins(Iterable mixins); - - /// Returns an [ClassDeclaration] AST representing the builder. - ClassDeclaration buildClass([Scope scope]); - - /// Sets [extend]. - void setExtends(TypeBuilder extend); -} - -/// A marker interface for an AST that could be added to [ClassBuilder]. -abstract class ValidClassMember implements AstBuilder {} - -class _ClassBuilderImpl extends Object - with AbstractExpressionMixin, AbstractTypeBuilderMixin, HasAnnotationsMixin - implements ClassBuilder { - final _constructors = []; - final _fields = {}; - final _methods = {}; - - TypeBuilder _extends; - final List _with; - final List _implements; - - final bool _asAbstract; - final String _name; - - _ClassBuilderImpl( - this._name, { - bool asAbstract: false, - TypeBuilder asExtends, - Iterable asWith: const [], - Iterable asImplements: const [], - }) - : _asAbstract = asAbstract, - _extends = asExtends, - _with = asWith.toList(), - _implements = asImplements.toList(); - - @override - void addConstructor(ConstructorBuilder constructor) { - _constructors.add(constructor); - } - - @override - void addField(FieldBuilder field, {bool asStatic: false}) { - _fields[field] = asStatic; - } - - @override - void addImplement(TypeBuilder interface) { - _implements.add(interface); - } - - @override - void addImplements(Iterable interfaces) { - _implements.addAll(interfaces); - } - - @override - void addMethod(MethodBuilder method, {bool asStatic: false}) { - _methods[method] = asStatic; - } - - @override - void addMixin(TypeBuilder mixin) { - _with.add(mixin); - } - - @override - void addMixins(Iterable mixins) { - _with.addAll(mixins); - } - - @override - ClassDeclaration buildAst([Scope scope]) => buildClass(scope); - - @override - ClassDeclaration buildClass([Scope scope]) { - var extend = _extends; - if (extend == null && _with.isNotEmpty) { - extend = lib$core.Object; - } - final clazz = astFactory.classDeclaration( - null, - buildAnnotations(scope), - _asAbstract ? $abstract : null, - $class, - stringIdentifier(_name), - null, - extend != null - ? astFactory.extendsClause( - $extends, - extend.buildType(scope), - ) - : null, - _with.isNotEmpty - ? astFactory.withClause( - $with, - _with.map/**/((w) => w.buildType(scope)).toList(), - ) - : null, - _implements.isNotEmpty - ? astFactory.implementsClause( - $implements, - _implements.map/**/((i) => i.buildType(scope)).toList(), - ) - : null, - null, - null, - null, - ); - _fields.forEach((field, static) { - clazz.members.add(field.buildField(static, scope)); - }); - _constructors.forEach((constructor) { - clazz.members.add(constructor.buildConstructor( - this, - scope, - )); - }); - _methods.forEach((method, static) { - clazz.members.add(method.buildMethod(static, scope)); - }); - return clazz; - } - - @override - TypeName buildType([Scope scope]) { - return new TypeBuilder(_name).buildType(scope); - } - - @override - void setExtends(TypeBuilder extend) { - _extends = extend; - } - - @override - ExportBuilder toExportBuilder() { - throw new UnsupportedError('Not supported for ClassBuilder'); - } - - @override - ImportBuilder toImportBuilder({bool deferred: false, String prefix}) { - throw new UnsupportedError('Not supported for ClassBuilder'); - } - - @override - Expression buildExpression([Scope scope]) { - return reference(_name).buildExpression(scope); - } - - @override - CompilationUnitMember buildTopLevelAst([Scope scope]) => buildClass(scope); -} - -class _TypeNameWrapper implements ValidClassMember { - final bool extend; - final bool implement; - final bool mixin; - final TypeBuilder type; - - _TypeNameWrapper( - this.type, { - this.extend: false, - this.implement: false, - this.mixin: false, - }); - - @override - AstNode buildAst([_]) => throw new UnsupportedError('Use within clazz'); -} diff --git a/pkgs/code_builder/lib/src/builders/expression.dart b/pkgs/code_builder/lib/src/builders/expression.dart deleted file mode 100644 index faa80ef0b..000000000 --- a/pkgs/code_builder/lib/src/builders/expression.dart +++ /dev/null @@ -1,689 +0,0 @@ -// 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. -library code_builder.src.builders.expression; - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/token.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:analyzer/src/dart/ast/token.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/src/builders/method.dart'; -import 'package:code_builder/src/builders/parameter.dart'; -import 'package:code_builder/src/builders/reference.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/expression/raw.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/builders/statement/if.dart'; -import 'package:code_builder/src/builders/statement/while.dart'; -import 'package:code_builder/src/builders/type.dart'; -import 'package:code_builder/src/tokens.dart'; - -part 'expression/assert.dart'; -part 'expression/assign.dart'; -part 'expression/await.dart'; -part 'expression/cascade.dart'; -part 'expression/cast.dart'; -part 'expression/index.dart'; -part 'expression/invocation.dart'; -part 'expression/is_instance_of.dart'; -part 'expression/negate.dart'; -part 'expression/operators.dart'; -part 'expression/return.dart'; -part 'expression/ternary.dart'; -part 'expression/throw.dart'; -part 'expression/yield.dart'; - -final _false = - astFactory.booleanLiteral(new KeywordToken(Keyword.FALSE, 0), true); - -final _null = astFactory.nullLiteral(new KeywordToken(Keyword.NULL, 0)); - -final _true = - astFactory.booleanLiteral(new KeywordToken(Keyword.TRUE, 0), true); - -/// A reference to `super`. -ExpressionBuilder get superRef => new _SuperExpression(); - -/// Returns a pre-defined literal expression of [value]. -/// -/// Only primitive values are allowed. -ExpressionBuilder literal(value) { - if (value is List) { - return list(value); - } - if (value is Map) { - return map(value); - } - return new _LiteralExpression(_literal(value)); -} - -/// Returns a literal `List` expression from [values]. -/// -/// Optionally specify [asConst] or with a generic [type]. -ExpressionBuilder list( - Iterable values, { - bool asConst: false, - TypeBuilder type, -}) => - new _TypedListExpression(values, asConst: asConst, type: type); - -/// Returns a literal `Map` expression from [values]. -/// -/// Optionally specify [asConst] or with a generic [keyType] or [valueType]. -ExpressionBuilder map( - Map values, { - bool asConst: false, - TypeBuilder keyType, - TypeBuilder valueType, -}) => - new _TypedMapExpression(values, - asConst: asConst, keyType: keyType, valueType: valueType); - -Literal _literal(value) { - if (value == null) { - return _null; - } else if (value is bool) { - return value ? _true : _false; - } else if (value is String) { - return astFactory.simpleStringLiteral(stringToken(_quote(value)), value); - } else if (value is int) { - return astFactory.integerLiteral(stringToken('$value'), value); - } else if (value is double) { - return astFactory.doubleLiteral(stringToken('$value'), value); - } - throw new ArgumentError.value(value, 'Unsupported'); -} - -/// Quotes the string literal. It is assumed that the [value] is meant to be -/// the raw string, so all `\` are escaped. -String _quote(String value) { - value = value.replaceAll(r'\', r'\\').replaceAll(r"'", r"\'"); - if (value.contains('\n')) { - return "'''$value'''"; - } - return "'$value'"; -} - -/// Implements much of [ExpressionBuilder]. -abstract class AbstractExpressionMixin implements ExpressionBuilder { - @override - ExpressionBuilder operator *(ExpressionBuilder other) { - return new _AsBinaryExpression( - this, - other, - $multiply, - ); - } - - @override - ExpressionBuilder operator +(ExpressionBuilder other) { - return new _AsBinaryExpression( - this, - other, - $plus, - ); - } - - @override - ExpressionBuilder operator -(ExpressionBuilder other) { - return new _AsBinaryExpression( - this, - other, - $minus, - ); - } - - @override - ExpressionBuilder operator /(ExpressionBuilder other) { - return new _AsBinaryExpression( - this, - other, - $divide, - ); - } - - @override - ExpressionBuilder operator >(ExpressionBuilder other) { - return new _AsBinaryExpression( - this, - other, - $gt, - ); - } - - @override - ExpressionBuilder operator <(ExpressionBuilder other) { - return new _AsBinaryExpression( - this, - other, - $lt, - ); - } - - @override - ExpressionBuilder operator [](ExpressionBuilder index) { - return new _IndexExpression(this, index); - } - - @override - ExpressionBuilder and(ExpressionBuilder other) { - return new _AsBinaryExpression( - this, - other, - $and, - ); - } - - @override - StatementBuilder asAssert() => new _AsAssert(this); - - @override - StatementBuilder asAssign( - ExpressionBuilder target, { - bool nullAware: false, - }) => - new _AsAssign(this, nullAware, target); - - @override - ExpressionBuilder asAwait() => new _AsAwait(this); - - @override - StatementBuilder asConst(String variable, [TypeBuilder type]) { - return new _AsAssignNew(this, variable, type, $const); - } - - @override - StatementBuilder asFinal(String variable, [TypeBuilder type]) { - return new _AsAssignNew(this, variable, type, $final); - } - - @override - IfStatementBuilder asIf() => new IfStatementBuilder(this); - - @override - StatementBuilder asReturn() => new _AsReturn(this); - - @override - StatementBuilder asStatement() => new _AsStatement(this); - - @override - StatementBuilder asVar(String variable, [TypeBuilder type]) { - return new _AsAssignNew(this, variable, type, $var); - } - - @override - StatementBuilder asYield() => new _AsYield(this, false); - - @override - StatementBuilder asYieldStar() => new _AsYield(this, true); - - @override - ExpressionBuilder asThrow() => new _ThrowExpression(this); - - @override - WhileStatementBuilder asWhile({bool asDo: false}) { - return new WhileStatementBuilder(asDo, this); - } - - @override - Statement buildStatement([Scope scope]) { - return asStatement().buildStatement(scope); - } - - @override - InvocationBuilder call( - Iterable positionalArguments, { - Map namedArguments: const {}, - }) { - final invocation = new InvocationBuilder._(this); - positionalArguments.forEach(invocation.addPositionalArgument); - namedArguments.forEach(invocation.addNamedArgument); - return invocation; - } - - @override - ExpressionBuilder castAs(TypeBuilder type) => new _AsCast(this, type); - - @override - ExpressionBuilder cascade( - Iterable create(ExpressionBuilder self), - ) { - // Sorry for the huge hack. Need to think more clearly about this in future. - return new _CascadeExpression(this, create(reference('.'))); - } - - @override - ExpressionBuilder decrement() => new _DecrementExpression(this); - - @override - ExpressionBuilder equals(ExpressionBuilder other) { - return new _AsBinaryExpression( - this, - other, - $equalsEquals, - ); - } - - @override - ExpressionBuilder increment([bool prefix = false]) { - return new _IncrementExpression(this, prefix); - } - - @override - ExpressionBuilder identical(ExpressionBuilder other) { - return lib$core.identical.call([ - this, - other, - ]); - } - - @override - InvocationBuilder invoke( - String method, - Iterable positionalArguments, { - Iterable genericTypes: const [], - Map namedArguments: const {}, - }) { - final invocation = new InvocationBuilder._on( - this, - method, - genericTypes.toList(), - ); - positionalArguments.forEach(invocation.addPositionalArgument); - namedArguments.forEach(invocation.addNamedArgument); - return invocation; - } - - @override - ExpressionBuilder isInstanceOf(TypeBuilder type) => - new _IsInstanceOfExpression(this, type); - - @override - ExpressionBuilder negate() => new _NegateExpression(this); - - @override - ExpressionBuilder negative() => new _NegativeExpression(this); - - @override - ExpressionBuilder notEquals(ExpressionBuilder other) { - return new _AsBinaryExpression( - this, - other, - $notEquals, - ); - } - - @override - ExpressionBuilder or(ExpressionBuilder other) { - return new _AsBinaryExpression( - this, - other, - $or, - ); - } - - @override - ExpressionBuilder parentheses() => new _ParenthesesExpression(this); - - @override - ExpressionBuilder property(String name) => new _MemberExpression(this, name); - - @override - ExpressionBuilder ternary( - ExpressionBuilder ifTrue, - ExpressionBuilder ifFalse, - ) => - new _TernaryExpression(this, ifTrue, ifFalse); -} - -/// Builds an [Expression] AST when [buildExpression] is invoked. -abstract class ExpressionBuilder - implements AstBuilder, StatementBuilder, ValidParameterMember { - /// Create an expression builder that parses and emits a [raw] expression. - factory ExpressionBuilder.raw(String raw(Scope scope)) = RawExpressionBuilder; - - /// Returns as an [ExpressionBuilder] multiplying by [other]. - ExpressionBuilder operator *(ExpressionBuilder other); - - /// Returns as an [ExpressionBuilder] adding [other]. - ExpressionBuilder operator +(ExpressionBuilder other); - - /// Returns as an [ExpressionBuilder] subtracting [other]. - ExpressionBuilder operator -(ExpressionBuilder other); - - /// Returns as an [ExpressionBuilder] dividing by [other]. - ExpressionBuilder operator /(ExpressionBuilder other); - - /// Returns as an [ExpressionBuilder] `<` by [other]. - ExpressionBuilder operator <(ExpressionBuilder other); - - /// Returns as an [ExpressionBuilder] `>` by [other]. - ExpressionBuilder operator >(ExpressionBuilder other); - - /// Returns as an [ExpressionBuilder] reading the `[]` property with [index]. - ExpressionBuilder operator [](ExpressionBuilder index); - - /// Returns as an [ExpressionBuilder] `&&` [other]. - ExpressionBuilder and(ExpressionBuilder other); - - /// Return as a [StatementBuilder] that `assert`s this expression. - StatementBuilder asAssert(); - - /// Returns as a [StatementBuilder] that assigns to [target]. - StatementBuilder asAssign( - ExpressionBuilder target, { - bool nullAware, - }); - - /// Returns as an expression `await`-ing this one. - ExpressionBuilder asAwait() => new _AsAwait(this); - - /// Returns as a [StatementBuilder] that assigns to a new `const` [variable]. - StatementBuilder asConst(String variable, [TypeBuilder type]); - - /// Returns as a [StatementBuilder] that assigns to a new `final` [variable]. - StatementBuilder asFinal(String variable, [TypeBuilder type]); - - /// Returns as a [StatementBuilder] that builds an `if` statement. - IfStatementBuilder asIf(); - - /// Returns as a [StatementBuilder] that `return`s this expression. - StatementBuilder asReturn(); - - /// Returns _explicitly_ as a [StatementBuilder]. - /// - /// **NOTE**: [ExpressionBuilder] is _already_ usable as a [StatementBuilder] - /// directly; this API exists in order force [buildAst] to return a - /// [Statement] AST instead of an expression. - StatementBuilder asStatement(); - - /// Returns as an [ExpressionBuilder] that throws this expression as an error. - ExpressionBuilder asThrow(); - - /// Returns as a [StatementBuilder] that assigns to a new `var` [variable]. - /// - /// If [type] is supplied, the resulting statement is `{type} {variable} =`. - StatementBuilder asVar(String variable, [TypeBuilder type]); - - /// Returns as a [StatementBuilder] yielding this one. - StatementBuilder asYield(); - - /// Returns as a [StatementBuilder] yielding this one. - StatementBuilder asYieldStar(); - - /// Returns as a [WhileStatementBuilder] with this as the condition. - WhileStatementBuilder asWhile({bool asDo: false}); - - /// Returns an [Expression] AST representing the builder. - Expression buildExpression([Scope scope]); - - /// Returns as an [InvocationBuilder] with arguments added. - InvocationBuilder call( - Iterable positionalArguments, { - Map namedArguments, - }); - - /// Returns the expression casted as [type]. - ExpressionBuilder castAs(TypeBuilder type); - - /// Return as an [ExpressionBuilder] with `..` appended. - ExpressionBuilder cascade( - Iterable create(ExpressionBuilder self), - ); - - /// Returns as an [ExpressionBuilder] decrementing this expression. - ExpressionBuilder decrement(); - - /// Returns as an [ExpressionBuilder] comparing using `==` against [other]. - ExpressionBuilder equals(ExpressionBuilder other); - - /// Returns as an [ExpressionBuilder] comparing using `identical`. - ExpressionBuilder identical(ExpressionBuilder other); - - /// Returns as an [ExpressionBuilder] incrementing this expression. - ExpressionBuilder increment([bool prefix = false]); - - /// Returns as an [InvocationBuilder] on [method] of this expression. - InvocationBuilder invoke( - String method, - Iterable positionalArguments, { - Iterable genericTypes, - Map namedArguments, - }); - - /// Returns as an [ExpressionBuilder] indicating whether this expression is an instance of [type], using the `is` operator. - ExpressionBuilder isInstanceOf(TypeBuilder type); - - /// Returns as an [ExpressionBuilder] negating using the `!` operator. - ExpressionBuilder negate(); - - /// Returns as an [ExpressionBuilder] negating the value, - ExpressionBuilder negative(); - - /// Returns as an [ExpressionBuilder] comparing using `!=` against [other]. - ExpressionBuilder notEquals(ExpressionBuilder other); - - /// Returns as an [ExpressionBuilder] `||` [other]. - ExpressionBuilder or(ExpressionBuilder other); - - /// Returns as an [ExpressionBuilder] wrapped in parentheses. - ExpressionBuilder parentheses(); - - /// Returns {{this}}.{{name}}. - ExpressionBuilder property(String name); - - /// Returns {{this}} ? {{ifTrue}} : {{ifFalse}}. - ExpressionBuilder ternary( - ExpressionBuilder ifTrue, - ExpressionBuilder ifFalse, - ); -} - -/// An [AstBuilder] that can add [ExpressionBuilder]. -abstract class HasExpressions implements AstBuilder { - final List _expressions = []; - - /// Adds [expression] to the builder. - void addExpression(ExpressionBuilder expression) { - _expressions.add(expression); - } - - /// Adds [expressions] to the builder. - void addExpressions(Iterable expressions) { - _expressions.addAll(expressions); - } -} - -/// Implements [HasExpressions]. -abstract class HasExpressionsMixin extends HasExpressions { - /// Returns a [List] of all built [Expression]s. - List buildExpressions([Scope scope]) => _expressions - .map/**/((e) => e.buildExpression(scope)) - .toList(); - - /// Clones all expressions to [clone]. - void cloneExpressionsTo(HasExpressions clone) { - clone.addExpressions(_expressions); - } -} - -class _AsStatement extends TopLevelMixin implements StatementBuilder { - final ExpressionBuilder _expression; - - _AsStatement(this._expression); - - @override - Statement buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) { - return astFactory.expressionStatement( - _expression.buildExpression(scope), - $semicolon, - ); - } -} - -class _MemberExpression extends Object - with AbstractExpressionMixin, TopLevelMixin { - final String _name; - final ExpressionBuilder _target; - - _MemberExpression(this._target, this._name); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.propertyAccess( - _target.buildExpression(scope), - $period, - stringIdentifier(_name), - ); - } -} - -class _LiteralExpression extends Object - with AbstractExpressionMixin, TopLevelMixin { - final Literal _literal; - - _LiteralExpression(this._literal); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([_]) => _literal; -} - -class _ParenthesesExpression extends Object - with AbstractExpressionMixin, TopLevelMixin { - final ExpressionBuilder _expression; - - _ParenthesesExpression(this._expression); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.parenthesizedExpression( - $openParen, - _expression.buildExpression(scope), - $closeParen, - ); - } -} - -ExpressionBuilder _expressionify(v) { - if (v == null || v is bool || v is String || v is int || v is double) { - return new _LiteralExpression(_literal(v)); - } - if (v is ExpressionBuilder) { - return v; - } - throw new ArgumentError('Could not expressionify $v'); -} - -class _SuperExpression extends Object - with AbstractExpressionMixin, TopLevelMixin { - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([_]) => astFactory.superExpression($super); -} - -class _TypedListExpression extends Object - with AbstractExpressionMixin, TopLevelMixin { - static List _toExpression(Iterable values) { - return values.map(_expressionify).toList(); - } - - final bool _asConst; - final TypeBuilder _type; - final List _values; - - _TypedListExpression(Iterable values, {bool asConst, TypeBuilder type}) - : _values = _toExpression(values), - _asConst = asConst, - _type = type; - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.listLiteral( - _asConst ? $const : null, - _type != null - ? astFactory.typeArgumentList( - $openBracket, - [_type.buildType(scope)], - $closeBracket, - ) - : null, - $openBracket, - _values.map((v) => v.buildExpression(scope)).toList(), - $closeBracket, - ); - } -} - -class _TypedMapExpression extends Object - with AbstractExpressionMixin, TopLevelMixin { - static Map _toExpression(Map values) { - return new Map.fromIterable( - values.keys, - key: (k) => _expressionify(k), - value: (k) => _expressionify(values[k]), - ); - } - - final bool _asConst; - final TypeBuilder _keyType; - final TypeBuilder _valueType; - final Map _values; - - _TypedMapExpression(Map values, - {bool asConst, TypeBuilder keyType, TypeBuilder valueType}) - : _values = _toExpression(values), - _asConst = asConst, - _keyType = keyType != null - ? keyType - : valueType != null ? lib$core.$dynamic : null, - _valueType = valueType != null - ? valueType - : keyType != null ? lib$core.$dynamic : null; - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.mapLiteral( - _asConst ? $const : null, - _keyType != null - ? astFactory.typeArgumentList( - $openBracket, - [ - _keyType.buildType(scope), - _valueType.buildType(scope), - ], - $closeBracket, - ) - : null, - $openBracket, - _values.keys.map((k) { - return astFactory.mapLiteralEntry( - k.buildExpression(scope), - $colon, - _values[k].buildExpression(scope), - ); - }).toList(), - $closeBracket, - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/assert.dart b/pkgs/code_builder/lib/src/builders/expression/assert.dart deleted file mode 100644 index 0428b6f85..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/assert.dart +++ /dev/null @@ -1,27 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _AsAssert extends TopLevelMixin implements StatementBuilder { - final ExpressionBuilder _expression; - - _AsAssert(this._expression); - - @override - Statement buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) { - return astFactory.assertStatement( - $assert, - $openParen, - _expression.buildExpression(scope), - null, - null, - $closeParen, - null, - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/assign.dart b/pkgs/code_builder/lib/src/builders/expression/assign.dart deleted file mode 100644 index 20b4dc90f..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/assign.dart +++ /dev/null @@ -1,79 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _AsAssign extends AbstractExpressionMixin with TopLevelMixin { - final bool _nullAware; - final ExpressionBuilder _value; - final ExpressionBuilder _target; - - _AsAssign(this._value, this._nullAware, this._target); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.assignmentExpression( - _target.buildExpression(scope), - _nullAware ? $nullAwareEquals : $equals, - _value.buildExpression(scope), - ); - } -} - -class _AsAssignNew extends TopLevelMixin implements StatementBuilder { - final ExpressionBuilder _value; - final String _name; - final TypeBuilder _type; - final Token _modifier; - - _AsAssignNew(this._value, this._name, this._type, this._modifier); - - @override - Statement buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) { - return astFactory.variableDeclarationStatement( - astFactory.variableDeclarationList( - null, - null, - _type == null || _modifier != $var ? _modifier : null, - _type?.buildType(scope), - [ - astFactory.variableDeclaration( - stringIdentifier(_name), - $equals, - _value.buildExpression(scope), - ), - ], - ), - $semicolon, - ); - } - - @override - CompilationUnitMember buildTopLevelAst([Scope scope]) { - return astFactory.topLevelVariableDeclaration( - null, - null, - astFactory.variableDeclarationList( - null, - null, - _type == null || _modifier != $var ? _modifier : null, - _type?.buildType(scope), - [ - astFactory.variableDeclaration( - stringIdentifier(_name), - $equals, - _value.buildExpression(scope), - ), - ], - ), - $semicolon, - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/await.dart b/pkgs/code_builder/lib/src/builders/expression/await.dart deleted file mode 100644 index 011cf45be..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/await.dart +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _AsAwait extends AbstractExpressionMixin with TopLevelMixin { - final ExpressionBuilder _expression; - - _AsAwait(this._expression); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.awaitExpression( - $await, - _expression.buildExpression(scope), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/cascade.dart b/pkgs/code_builder/lib/src/builders/expression/cascade.dart deleted file mode 100644 index d99e15f77..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/cascade.dart +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _CascadeExpression extends TopLevelMixin with AbstractExpressionMixin { - final List _cascades; - final ExpressionBuilder _target; - - _CascadeExpression(this._target, this._cascades); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.cascadeExpression( - _target.buildExpression(scope), - _cascades.map((e) => e.buildExpression(scope)).toList(), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/cast.dart b/pkgs/code_builder/lib/src/builders/expression/cast.dart deleted file mode 100644 index e18ecfaeb..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/cast.dart +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _AsCast extends TopLevelMixin with AbstractExpressionMixin { - final ExpressionBuilder _target; - final TypeBuilder _type; - - _AsCast(this._target, this._type); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.asExpression( - _target.buildExpression(scope), - $as, - _type.buildType(scope), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/index.dart b/pkgs/code_builder/lib/src/builders/expression/index.dart deleted file mode 100644 index 2591e2c40..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/index.dart +++ /dev/null @@ -1,25 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _IndexExpression extends AbstractExpressionMixin with TopLevelMixin { - final ExpressionBuilder _target; - final ExpressionBuilder _index; - - _IndexExpression(this._target, this._index); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.indexExpressionForTarget( - _target.buildExpression(scope), - $openBracket, - _index.buildExpression(scope), - $closeBracket, - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/invocation.dart b/pkgs/code_builder/lib/src/builders/expression/invocation.dart deleted file mode 100644 index 9805fd7ab..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/invocation.dart +++ /dev/null @@ -1,114 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -/// Partial implementation of [InvocationBuilder]. -abstract class AbstractInvocationBuilderMixin implements InvocationBuilder { - final List _positional = []; - final Map _named = {}; - - @override - void addNamedArgument(String name, ExpressionBuilder argument) { - _named[name] = argument; - } - - @override - void addPositionalArgument(ExpressionBuilder argument) { - _positional.add(argument); - } - - /// Returns an [ArgumentList] AST. - ArgumentList buildArgumentList({ - Scope scope, - }) { - final allArguments = []; - allArguments.addAll( - _positional.map/**/((e) => e.buildExpression(scope)), - ); - _named.forEach((name, e) { - allArguments.add(astFactory.namedExpression( - astFactory.label( - stringIdentifier(name), - $colon, - ), - e.buildExpression(scope), - )); - }); - return astFactory.argumentList( - $openParen, - allArguments, - $closeParen, - ); - } - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); -} - -/// Builds an invocation AST. -abstract class InvocationBuilder - implements ExpressionBuilder, StatementBuilder, ValidMethodMember { - factory InvocationBuilder._(ExpressionBuilder target) { - return new _FunctionInvocationBuilder(target); - } - - factory InvocationBuilder._on( - ExpressionBuilder target, - String method, - List generics, - ) { - return new _MethodInvocationBuilder(target, method, generics); - } - - /// Adds [argument] as a [name]d argument to this method call. - void addNamedArgument(String name, ExpressionBuilder argument); - - /// Adds [argument] as a positional argument to this method call. - void addPositionalArgument(ExpressionBuilder argument); -} - -class _FunctionInvocationBuilder extends Object - with AbstractInvocationBuilderMixin, AbstractExpressionMixin, TopLevelMixin - implements InvocationBuilder { - final ExpressionBuilder _target; - - _FunctionInvocationBuilder(this._target); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.functionExpressionInvocation( - _target.buildExpression(scope), - null, - buildArgumentList(scope: scope), - ); - } -} - -class _MethodInvocationBuilder extends Object - with AbstractInvocationBuilderMixin, AbstractExpressionMixin, TopLevelMixin - implements InvocationBuilder { - final List _generics; - final String _method; - final ExpressionBuilder _target; - - _MethodInvocationBuilder(this._target, this._method, this._generics); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.methodInvocation( - _target.buildExpression(scope), - $period, - stringIdentifier(_method), - _generics.isNotEmpty - ? astFactory.typeArgumentList( - $openBracket, - _generics.map((t) => t.buildType(scope)).toList(), - $closeBracket, - ) - : null, - buildArgumentList(scope: scope), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/is_instance_of.dart b/pkgs/code_builder/lib/src/builders/expression/is_instance_of.dart deleted file mode 100644 index 9fd38fbfe..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/is_instance_of.dart +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _IsInstanceOfExpression extends AbstractExpressionMixin - with TopLevelMixin { - final ExpressionBuilder _expression; - final TypeBuilder _type; - - _IsInstanceOfExpression(this._expression, this._type); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.isExpression( - _expression.buildExpression(scope), $is, null, _type.buildType(scope)); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/negate.dart b/pkgs/code_builder/lib/src/builders/expression/negate.dart deleted file mode 100644 index 979d2c04f..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/negate.dart +++ /dev/null @@ -1,39 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _NegateExpression extends AbstractExpressionMixin with TopLevelMixin { - final ExpressionBuilder _expression; - - _NegateExpression(this._expression); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.prefixExpression( - $not, - _expression.parentheses().buildExpression(scope), - ); - } -} - -class _NegativeExpression extends AbstractExpressionMixin with TopLevelMixin { - final ExpressionBuilder _expression; - - _NegativeExpression(this._expression); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.prefixExpression( - $minus, - _expression.parentheses().buildExpression(scope), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/operators.dart b/pkgs/code_builder/lib/src/builders/expression/operators.dart deleted file mode 100644 index 99bf9eaa4..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/operators.dart +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _AsBinaryExpression extends Object - with AbstractExpressionMixin, TopLevelMixin { - final ExpressionBuilder _left; - final ExpressionBuilder _right; - final Token _operator; - - _AsBinaryExpression(this._left, this._right, this._operator); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.binaryExpression( - _left.buildExpression(scope), - _operator, - _right.buildExpression(scope), - ); - } -} - -class _DecrementExpression extends Object - with AbstractExpressionMixin, TopLevelMixin { - final ExpressionBuilder _expression; - - _DecrementExpression(this._expression); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.postfixExpression( - _expression.buildExpression(scope), - $minusMinus, - ); - } -} - -class _IncrementExpression extends Object - with AbstractExpressionMixin, TopLevelMixin { - final ExpressionBuilder _expression; - final bool _prefix; - - _IncrementExpression(this._expression, this._prefix); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - if (_prefix) { - return astFactory.prefixExpression( - $plusPlus, - _expression.buildExpression(scope), - ); - } - return astFactory.postfixExpression( - _expression.buildExpression(scope), - $plusPlus, - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/raw.dart b/pkgs/code_builder/lib/src/builders/expression/raw.dart deleted file mode 100644 index 1dff88564..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/raw.dart +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:code_builder/src/builders/expression.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:func/func.dart'; - -class RawExpressionBuilder extends Object - with AbstractExpressionMixin, TopLevelMixin - implements ExpressionBuilder { - final Func1 _raw; - - RawExpressionBuilder(this._raw); - - @override - AstNode buildAst([Scope scope]) { - FunctionDeclaration d = - parseCompilationUnit('main() => ${_raw(scope)};').declarations.first; - ExpressionFunctionBody f = d.functionExpression.body; - return f.expression; - } - - @override - Expression buildExpression([Scope scope]) => buildAst(scope); -} diff --git a/pkgs/code_builder/lib/src/builders/expression/return.dart b/pkgs/code_builder/lib/src/builders/expression/return.dart deleted file mode 100644 index 2a0af2981..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/return.dart +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _AsReturn extends TopLevelMixin implements StatementBuilder { - final ExpressionBuilder _value; - - _AsReturn(this._value); - - @override - AstNode buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) { - return astFactory.returnStatement( - $return, - _value.buildExpression(scope), - $semicolon, - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/ternary.dart b/pkgs/code_builder/lib/src/builders/expression/ternary.dart deleted file mode 100644 index 5a93a3cf5..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/ternary.dart +++ /dev/null @@ -1,31 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _TernaryExpression extends TopLevelMixin with AbstractExpressionMixin { - final ExpressionBuilder _target; - final ExpressionBuilder _ifTrue; - final ExpressionBuilder _ifFalse; - - _TernaryExpression( - this._target, - this._ifTrue, - this._ifFalse, - ); - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.conditionalExpression( - _target.buildExpression(scope), - $question, - _ifTrue.buildExpression(scope), - $colon, - _ifFalse.buildExpression(scope), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/throw.dart b/pkgs/code_builder/lib/src/builders/expression/throw.dart deleted file mode 100644 index 5db07c6fe..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/throw.dart +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _ThrowExpression extends AbstractExpressionMixin with TopLevelMixin { - final ExpressionBuilder _value; - - _ThrowExpression(this._value); - - @override - ExpressionBuilder asThrow() => this; - - @override - AstNode buildAst([Scope scope]) => buildExpression(scope); - - @override - Expression buildExpression([Scope scope]) { - return astFactory.throwExpression($throw, _value.buildExpression(scope)); - } -} diff --git a/pkgs/code_builder/lib/src/builders/expression/yield.dart b/pkgs/code_builder/lib/src/builders/expression/yield.dart deleted file mode 100644 index decbcfb35..000000000 --- a/pkgs/code_builder/lib/src/builders/expression/yield.dart +++ /dev/null @@ -1,25 +0,0 @@ -// 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. - -part of code_builder.src.builders.expression; - -class _AsYield extends TopLevelMixin implements StatementBuilder { - final ExpressionBuilder _expression; - final bool _isStar; - - _AsYield(this._expression, this._isStar); - - @override - Statement buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) { - return astFactory.yieldStatement( - $yield, - _isStar ? $star : null, - _expression.buildExpression(scope), - $semicolon, - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/field.dart b/pkgs/code_builder/lib/src/builders/field.dart deleted file mode 100644 index 14244638a..000000000 --- a/pkgs/code_builder/lib/src/builders/field.dart +++ /dev/null @@ -1,178 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/token.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:analyzer/src/dart/ast/token.dart'; -import 'package:code_builder/src/builders/annotation.dart'; -import 'package:code_builder/src/builders/class.dart'; -import 'package:code_builder/src/builders/expression.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/builders/type.dart'; -import 'package:code_builder/src/tokens.dart'; - -/// Short-hand for [FieldBuilder]. -FieldBuilder varField( - String name, { - TypeBuilder type, - ExpressionBuilder value, -}) { - return new FieldBuilder( - name, - type: type, - value: value, - ); -} - -/// Short-hand for [FieldBuilder.asFinal]. -FieldBuilder varFinal( - String name, { - TypeBuilder type, - ExpressionBuilder value, -}) { - return new FieldBuilder.asFinal( - name, - type: type, - value: value, - ); -} - -/// Short-hand for [FieldBuilder.asConst]. -FieldBuilder varConst( - String name, { - TypeBuilder type, - ExpressionBuilder value, -}) { - return new FieldBuilder.asConst( - name, - type: type, - value: value, - ); -} - -/// Lazily builds an field AST when builder is invoked. -abstract class FieldBuilder - implements - AstBuilder, - HasAnnotations, - StatementBuilder, - ValidClassMember { - /// Creates a new [FieldBuilder] defining a new `var`. - factory FieldBuilder( - String name, { - TypeBuilder type, - ExpressionBuilder value, - }) => - new _FieldBuilderImpl( - name, - keyword: type == null ? Keyword.VAR : null, - type: type, - value: value, - ); - - /// Creates a new [FieldBuilder] defining a new `const`. - factory FieldBuilder.asConst( - String name, { - TypeBuilder type, - ExpressionBuilder value, - }) => - new _FieldBuilderImpl( - name, - keyword: Keyword.CONST, - type: type, - value: value, - ); - - /// Creates a new [FieldBuilder] defining a new `final`. - factory FieldBuilder.asFinal( - String name, { - TypeBuilder type, - ExpressionBuilder value, - }) => - new _FieldBuilderImpl( - name, - keyword: Keyword.FINAL, - type: type, - value: value, - ); - - /// Returns as a [FieldDeclaration] AST. - FieldDeclaration buildField(bool static, [Scope scope]); - - /// Returns as a [TopLevelVariableDeclaration] AST. - TopLevelVariableDeclaration buildTopLevel([Scope scope]); -} - -class _FieldBuilderImpl extends HasAnnotationsMixin implements FieldBuilder { - final Keyword _keyword; - final String _name; - final TypeBuilder _type; - final ExpressionBuilder _value; - - _FieldBuilderImpl( - String name, { - Keyword keyword, - TypeBuilder type, - ExpressionBuilder value, - }) - : _keyword = keyword, - _name = name, - _type = type, - _value = value; - - @override - TopLevelVariableDeclaration buildAst([Scope scope]) => buildTopLevel(scope); - - @override - FieldDeclaration buildField(bool static, [Scope scope]) { - return astFactory.fieldDeclaration( - null, - buildAnnotations(scope), - static ? $static : null, - _buildVariableList(scope), - $semicolon, - ); - } - - @override - Statement buildStatement([Scope scope]) { - return astFactory.variableDeclarationStatement( - _buildVariableList(scope), - $semicolon, - ); - } - - @override - TopLevelVariableDeclaration buildTopLevel([Scope scope]) { - return astFactory.topLevelVariableDeclaration( - null, - null, - _buildVariableList(scope), - $semicolon, - ); - } - - @override - CompilationUnitMember buildTopLevelAst([Scope scope]) { - return buildTopLevel(scope); - } - - VariableDeclarationList _buildVariableList([Scope scope]) { - return astFactory.variableDeclarationList( - null, - null, - _keyword != null ? new KeywordToken(_keyword, 0) : null, - _type?.buildType(scope), - [ - astFactory.variableDeclaration( - stringIdentifier(_name), - _value != null ? $equals : null, - _value?.buildExpression(scope), - ) - ], - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/file.dart b/pkgs/code_builder/lib/src/builders/file.dart deleted file mode 100644 index 915dc64ef..000000000 --- a/pkgs/code_builder/lib/src/builders/file.dart +++ /dev/null @@ -1,301 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/src/builders/annotation.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/tokens.dart'; - -/// Builds a file of Dart source code. -/// -/// See [LibraryBuilder] and [PartOfBuilder] for concrete implementations. -abstract class FileBuilder implements AstBuilder { - final List _members = []; - - FileBuilder._(); - - /// Adds a top-level field or class [member]. - void addMember(AstBuilder member) { - _members.add(member); - } - - /// Adds top-level field or class [members]. - void addMembers(Iterable members) { - _members.addAll(members); - } -} - -/// Builds a standalone file (library) of Dart source code. -class LibraryBuilder extends FileBuilder with HasAnnotationsMixin { - final List> _directives = >[]; - final String _name; - final Scope _scope; - - /// Creates a new standalone Dart library, optionally with [name]. - factory LibraryBuilder([String name]) => - new LibraryBuilder._(name, Scope.identity); - - /// Creates a new standalone Dart library, optionally with [name]. - /// - /// Uses the default [Scope] implementation unless [scope] is set. - factory LibraryBuilder.scope({String name, Scope scope}) { - return new LibraryBuilder._(name, scope ?? new Scope()); - } - - LibraryBuilder._(this._name, this._scope) : super._(); - - /// Adds a file [directive]. - void addDirective(AstBuilder directive) { - _directives.add(directive); - } - - /// Add file [directives]. - void addDirectives(Iterable> directives) { - _directives.addAll(directives); - } - - @override - CompilationUnit buildAst([Scope scope]) { - var members = _members.map((m) { - if (m is TopLevelMixin) { - return (m as TopLevelMixin).buildTopLevelAst(_scope); - } - return m.buildAst(_scope); - }).toList(); - var directives = []; - if (_name != null) { - directives.add(new _LibraryDirectiveBuilder(_name, this).buildAst(scope)); - } - directives - ..addAll(_scope.toImports().map((d) => d.buildAst())) - ..addAll(_directives.map((d) => d.buildAst())); - return astFactory.compilationUnit( - null, - null, - directives, - members, - null, - ); - } -} - -/// Lazily builds a partial file (part of) Dart source code. -class PartOfBuilder extends FileBuilder with HasAnnotationsMixin { - final String _uri; - final Scope _scope; - - /// Creates a partial Dart file. - factory PartOfBuilder(String uri, [Scope scope]) = PartOfBuilder._; - - PartOfBuilder._(this._uri, [this._scope]) : super._(); - - @override - CompilationUnit buildAst([Scope scope]) { - scope ??= _scope; - return astFactory.compilationUnit( - null, - null, - [ - astFactory.partOfDirective( - null, - buildAnnotations(scope), - $part, - $of, - null, - astFactory.libraryIdentifier([ - astFactory.simpleIdentifier(stringToken("'$_uri'")), - ]), - $semicolon, - ) - ], - _members.map((m) { - if (m is TopLevelMixin) { - return (m as TopLevelMixin).buildTopLevelAst(); - } - return m.buildAst(); - }).toList(), - null, - ); - } -} - -class _LibraryDirectiveBuilder implements AstBuilder { - final LibraryBuilder _library; - final String _name; - - _LibraryDirectiveBuilder(this._name, this._library); - - @override - LibraryDirective buildAst([Scope scope]) { - return astFactory.libraryDirective( - null, - _library.buildAnnotations(scope), - $library, - astFactory.libraryIdentifier([ - astFactory.simpleIdentifier( - stringToken(_name), - ), - ]), - $semicolon, - ); - } -} - -/// A builder that has a reference to a [uri]. -abstract class UriDirectiveBuilder implements AstBuilder { - String get uri; -} - -/// Lazily builds a [PartDirective] AST when built. -class PartBuilder extends Object - with HasAnnotationsMixin - implements AstBuilder, UriDirectiveBuilder { - @override - final String uri; - - factory PartBuilder(String uri) = PartBuilder._; - PartBuilder._(this.uri); - - @override - PartDirective buildAst([Scope scope]) { - return astFactory.partDirective( - null, - buildAnnotations(scope), - $part, - astFactory.simpleStringLiteral(stringToken("'$uri'"), uri), - $semicolon, - ); - } -} - -/// Lazily builds an [ImportDirective] AST when built. -class ImportBuilder extends Object - with HasAnnotationsMixin - implements AstBuilder, UriDirectiveBuilder { - final String _prefix; - @override - final String uri; - final bool _deferred; - - final Set _show = new Set(); - final Set _hide = new Set(); - - factory ImportBuilder(String path, {bool deferred: false, String prefix}) { - return new ImportBuilder._(path, prefix, deferred); - } - - ImportBuilder._(this.uri, this._prefix, this._deferred); - - void hide(String identifier) { - _hide.add(identifier); - } - - void hideAll(Iterable identifiers) { - _hide.addAll(identifiers); - } - - void show(String identifier) { - _show.add(identifier); - } - - void showAll(Iterable identifier) { - _show.addAll(identifier); - } - - @override - ImportDirective buildAst([Scope scope]) { - var combinators = []; - if (_show.isNotEmpty) { - combinators.add( - astFactory.showCombinator( - $show, - _show.map(stringIdentifier).toList(), - ), - ); - } - if (_hide.isNotEmpty) { - combinators.add( - astFactory.hideCombinator( - $hide, - _hide.map(stringIdentifier).toList(), - ), - ); - } - return astFactory.importDirective( - null, - buildAnnotations(scope), - null, - astFactory.simpleStringLiteral(stringToken("'$uri'"), uri), - null, - _deferred ? $deferred : null, - _prefix != null ? $as : null, - _prefix != null ? stringIdentifier(_prefix) : null, - combinators, - $semicolon, - ); - } -} - -/// Lazily builds an [ExportDirective] AST when built. -class ExportBuilder extends Object - with HasAnnotationsMixin - implements AstBuilder, UriDirectiveBuilder { - @override - final String uri; - - final Set _show = new Set(); - final Set _hide = new Set(); - - factory ExportBuilder(String path) = ExportBuilder._; - - ExportBuilder._(this.uri); - - void hide(String identifier) { - _hide.add(identifier); - } - - void hideAll(Iterable identifiers) { - _hide.addAll(identifiers); - } - - void show(String identifier) { - _show.add(identifier); - } - - void showAll(Iterable identifier) { - _show.addAll(identifier); - } - - @override - ExportDirective buildAst([Scope scope]) { - var combinators = []; - if (_show.isNotEmpty) { - combinators.add( - astFactory.showCombinator( - $show, - _show.map(stringIdentifier).toList(), - ), - ); - } - if (_hide.isNotEmpty) { - combinators.add( - astFactory.hideCombinator( - $hide, - _hide.map(stringIdentifier).toList(), - ), - ); - } - return astFactory.exportDirective( - null, - buildAnnotations(scope), - null, - astFactory.simpleStringLiteral(stringToken("'$uri'"), uri), - null, - combinators, - $semicolon, - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/method.dart b/pkgs/code_builder/lib/src/builders/method.dart deleted file mode 100644 index 270bc995c..000000000 --- a/pkgs/code_builder/lib/src/builders/method.dart +++ /dev/null @@ -1,756 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/token.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:analyzer/src/dart/ast/token.dart'; -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/src/builders/annotation.dart'; -import 'package:code_builder/src/builders/class.dart'; -import 'package:code_builder/src/builders/expression.dart'; -import 'package:code_builder/src/builders/parameter.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/builders/type.dart'; -import 'package:code_builder/src/tokens.dart'; - -/// Short-hand for `new ConstructorBuilder(...)`. -ConstructorBuilder constructor([ - Iterable members = const [], -]) { - return _constructorImpl(members: members); -} - -/// Short-hand for `new ConstructorBuilder(name)`. -ConstructorBuilder constructorNamed( - String name, [ - Iterable members = const [], -]) { - return _constructorImpl(name: name, members: members); -} - -/// Various types of modifiers for methods. -class MethodModifier implements ValidMethodMember { - static const MethodModifier asAsync = const MethodModifier._( - Keyword.ASYNC, - false, - ); - static const MethodModifier asAsyncStar = const MethodModifier._( - Keyword.ASYNC, - true, - ); - static const MethodModifier asSyncStar = const MethodModifier._( - Keyword.SYNC, - true, - ); - - final Keyword _keyword; - - const MethodModifier._(this._keyword, this.isStar); - - @override - buildAst([_]) => throw new UnsupportedError('Not an AST'); - - final bool isStar; - - Token keyword() => new KeywordToken(_keyword, 0); -} - -/// Short-hand for `new MethodBuilder.getter(...)`. -MethodBuilder getter( - String name, { - MethodModifier modifier, - Iterable statements, - ExpressionBuilder returns, - TypeBuilder returnType, -}) { - if (returns != null) { - return new MethodBuilder.getter( - name, - modifier: modifier, - returnType: returnType, - returns: returns, - ); - } else { - return new MethodBuilder.getter( - name, - modifier: modifier, - returnType: returnType, - )..addStatements(statements); - } -} - -/// A more short-hand way of constructing a Lambda [MethodBuilder]. -MethodBuilder lambda( - String name, - ExpressionBuilder value, { - MethodModifier modifier, - TypeBuilder returnType, -}) { - return new MethodBuilder( - name, - modifier: modifier, - returns: value, - returnType: returnType, - ); -} - -/// A more short-hand way of constructing a [MethodBuilder]. -MethodBuilder method( - String name, [ - Iterable members = const [], -]) { - final List positional = []; - final List<_NamedParameterWrapper> named = <_NamedParameterWrapper>[]; - final List statements = []; - MethodModifier modifier; - TypeBuilder returnType; - for (final member in members) { - if (member is TypeBuilder) { - returnType = member; - } else if (member is ParameterBuilder) { - positional.add(member); - } else if (member is _NamedParameterWrapper) { - named.add(member); - } else if (member is StatementBuilder) { - statements.add(member); - } else if (member is MethodModifier) { - modifier = member; - } else { - throw new StateError('Invalid AST type: ${member.runtimeType}'); - } - } - final method = new _MethodBuilderImpl( - name, - modifier: modifier, - returns: returnType, - ); - positional.forEach(method.addPositional); - named.forEach((p) => method.addNamed(p._parameter)); - statements.forEach(method.addStatement); - return method; -} - -/// Returns a wrapper around [parameter] for use with [method]. -_NamedParameterWrapper named(ParameterBuilder parameter) { - return new _NamedParameterWrapper(parameter); -} - -/// Short-hand for `new MethodBuilder.setter(...)`. -MethodBuilder setter( - String name, - ParameterBuilder value, - Iterable statements, -) { - return new MethodBuilder.setter(name) - ..addPositional(value) - ..addStatements(statements); -} - -/// Returns a wrapper around [parameter] for use with [constructor]. -_FieldParameterWrapper thisField(Object parameter) { - assert(parameter is ParameterBuilder || parameter is _NamedParameterWrapper); - return new _FieldParameterWrapper(parameter); -} - -ConstructorBuilder _constructorImpl({ - Iterable members, - String name, -}) { - final List<_AddParameter> _addFunctions = <_AddParameter>[]; - for (final member in members) { - if (member is ParameterBuilder) { - _addFunctions.add((c) => c.addPositional(member)); - } else if (member is _NamedParameterWrapper) { - _addFunctions.add((c) => c.addNamed(member._parameter)); - } else if (member is _FieldParameterWrapper) { - if (member._parameter is _NamedParameterWrapper) { - _NamedParameterWrapper p = member._parameter; - _addFunctions.add((c) => c.addNamed(p._parameter, asField: true)); - } else if (member._parameter is ParameterBuilder) { - _addFunctions - .add((c) => c.addPositional(member._parameter, asField: true)); - } - } else if (member is StatementBuilder) { - _addFunctions.add((c) => c.addStatement(member)); - } else { - throw new StateError('Invalid AST type: ${member.runtimeType}'); - } - } - final constructor = new ConstructorBuilder(name: name); - _addFunctions.forEach((a) => a(constructor)); - return constructor; -} - -typedef void _AddParameter(ConstructorBuilder constructor); - -/// Lazily builds an [ConstructorBuilder] AST when built. -abstract class ConstructorBuilder - implements - AstBuilder, - HasAnnotations, - HasParameters, - HasStatements, - ValidClassMember { - /// Create a new [ConstructorBuilder], optionally with a [name]. - /// - /// Can invoke `super` if [invokeSuper] is set, using super.[superName]. - factory ConstructorBuilder({ - String name, - String superName, - List invokeSuper, - bool asConst, - bool asFactory, - }) = _NormalConstructorBuilder; - - /// Create a new [ConstructorBuilder] that redirects to another constructor. - factory ConstructorBuilder.redirectTo( - String name, - TypeBuilder redirectToClass, { - String constructor, - bool asConst, - }) = _RedirectingConstructorBuilder; - - /// Adds a field initializer to this constructor. - void addInitializer( - String fieldName, { - ExpressionBuilder toExpression, - String toParameter, - }); - - @override - void addNamed(ParameterBuilder parameter, {bool asField: false}); - - @override - void addPositional(ParameterBuilder parameter, {bool asField: false}); - - /// Returns an [ConstructorDeclaration] AST representing the builder. - ConstructorDeclaration buildConstructor( - TypeBuilder returnType, [ - Scope scope, - ]); -} - -/// Lazily builds a method/function AST when the builder is invoked. -abstract class MethodBuilder - implements - ExpressionBuilder, - HasAnnotations, - HasParameters, - HasStatements, - ValidClassMember { - /// Creates a new [MethodBuilder]. - factory MethodBuilder( - String name, { - bool asAbstract: false, - MethodModifier modifier, - ExpressionBuilder returns, - TypeBuilder returnType, - }) { - if (returns != null) { - return new _LambdaMethodBuilder( - name, - returns, - returnType, - null, - modifier, - asAbstract, - ); - } else { - return new _MethodBuilderImpl( - name, - modifier: modifier, - returns: returnType, - asAbstract: asAbstract, - ); - } - } - - /// Creates a new [MethodBuilder] that returns an anonymous closure. - factory MethodBuilder.closure({ - MethodModifier modifier, - ExpressionBuilder returns, - TypeBuilder returnType, - bool asAbstract: false, - }) { - if (returns != null) { - return new _LambdaMethodBuilder( - null, - returns, - returnType, - null, - modifier, - asAbstract, - ); - } else { - return new _MethodBuilderImpl( - null, - modifier: modifier, - returns: returnType, - asAbstract: asAbstract, - ); - } - } - - /// Creates a getter. - factory MethodBuilder.getter( - String name, { - MethodModifier modifier, - TypeBuilder returnType, - ExpressionBuilder returns, - bool asAbstract: false, - }) { - if (returns == null) { - return new _MethodBuilderImpl( - name, - modifier: modifier, - returns: returnType, - property: Keyword.GET, - asAbstract: asAbstract, - ); - } else { - return new _LambdaMethodBuilder( - name, - returns, - returnType, - Keyword.GET, - modifier, - asAbstract, - ); - } - } - - /// Creates a new [MethodBuilder] that returns `void`. - factory MethodBuilder.returnVoid( - String name, { - ExpressionBuilder returns, - bool asAbstract: false, - }) { - if (returns == null) { - return new _MethodBuilderImpl( - name, - returns: lib$core.$void, - asAbstract: asAbstract, - ); - } - return new _LambdaMethodBuilder( - name, - returns, - lib$core.$void, - null, - null, - asAbstract, - ); - } - - /// Creates a setter. - factory MethodBuilder.setter( - String name, { - ExpressionBuilder returns, - bool asAbstract: false, - }) { - if (returns == null) { - return new _MethodBuilderImpl( - name, - property: Keyword.SET, - asAbstract: asAbstract, - ); - } else { - return new _LambdaMethodBuilder( - name, - returns, - null, - Keyword.SET, - null, - asAbstract, - ); - } - } - - /// Returns a [FunctionDeclaration] AST representing the builder. - FunctionDeclaration buildFunction([Scope scope]); - - /// Returns an [MethodDeclaration] AST representing the builder. - MethodDeclaration buildMethod(bool static, [Scope scope]); -} - -/// A marker interface for an AST that could be added to [ConstructorBuilder]. -abstract class ValidConstructorMember implements ValidMethodMember {} - -/// A marker interface for an AST that could be added to [MethodBuilder]. -abstract class ValidMethodMember implements AstBuilder {} - -class _FieldParameterWrapper - implements ValidConstructorMember, ValidMethodMember { - final Object /*ParameterBuilder|_NamedParameterWrapper*/ _parameter; - - _FieldParameterWrapper(this._parameter); - - @override - AstNode buildAst([_]) => throw new UnsupportedError('Use within method'); -} - -class _LambdaMethodBuilder extends Object - with - AbstractExpressionMixin, - HasAnnotationsMixin, - HasParametersMixin, - TopLevelMixin - implements MethodBuilder { - final ExpressionBuilder _expression; - final MethodModifier _modifier; - final String _name; - final TypeBuilder _returnType; - final Keyword _property; - final bool _asAbstract; - - _LambdaMethodBuilder( - this._name, - this._expression, - this._returnType, - this._property, - this._modifier, - this._asAbstract, - ); - - @override - void addStatement(StatementBuilder statement) { - throw new UnsupportedError('Cannot add statement on a Lambda method'); - } - - @override - void addStatements(Iterable statements) { - throw new UnsupportedError('Cannot add statement on a Lambda method'); - } - - @override - AstNode buildAst([Scope scope]) { - if (_name != null) { - return buildFunction(scope); - } - return buildExpression(scope); - } - - @override - Expression buildExpression([Scope scope]) { - return _buildExpression(scope, isStatement: false); - } - - FunctionExpression _buildExpression(Scope scope, {bool isStatement}) { - return astFactory.functionExpression( - null, - _property != Keyword.GET ? buildParameterList(scope) : null, - astFactory.expressionFunctionBody( - _modifier?.keyword(), - null, - _expression.buildExpression(scope), - isStatement ? $semicolon : null, - ), - ); - } - - @override - FunctionDeclaration buildFunction([Scope scope]) { - return astFactory.functionDeclaration( - null, - buildAnnotations(scope), - null, - _returnType?.buildType(scope), - _property != null ? new KeywordToken(_property, 0) : null, - _name != null ? stringIdentifier(_name) : null, - _asAbstract - ? astFactory.emptyFunctionBody($semicolon) - : _buildExpression(scope, isStatement: true), - ); - } - - @override - MethodDeclaration buildMethod(bool static, [Scope scope]) { - return astFactory.methodDeclaration( - null, - buildAnnotations(scope), - null, - static ? $static : null, - _returnType?.buildType(scope), - _property != null ? new KeywordToken(_property, 0) : null, - null, - stringIdentifier(_name), - null, - _property != Keyword.GET ? buildParameterList(scope) : null, - _asAbstract - ? astFactory.emptyFunctionBody($semicolon) - : astFactory.expressionFunctionBody( - _modifier?.keyword(), - null, - _expression.buildExpression(scope), - $semicolon, - ), - ); - } - - @override - CompilationUnitMember buildTopLevelAst([Scope scope]) => buildFunction(scope); -} - -class _MethodBuilderImpl extends Object - with - AbstractExpressionMixin, - HasAnnotationsMixin, - HasParametersMixin, - HasStatementsMixin, - TopLevelMixin - implements MethodBuilder { - final MethodModifier _modifier; - final String _name; - final TypeBuilder _returnType; - final Keyword _property; - final bool asAbstract; - - _MethodBuilderImpl( - this._name, { - MethodModifier modifier, - TypeBuilder returns, - Keyword property, - this.asAbstract: false, - }) - : _modifier = modifier, - _returnType = returns, - _property = property; - - @override - AstNode buildAst([Scope scope]) { - if (_name != null) { - return buildFunction(scope); - } - return buildExpression(scope); - } - - @override - Expression buildExpression([Scope scope]) { - return astFactory.functionExpression( - null, - _property != Keyword.GET ? buildParameterList(scope) : null, - asAbstract - ? astFactory.emptyFunctionBody($semicolon) - : astFactory.blockFunctionBody( - _modifier?.keyword(), - _modifier?.isStar == true ? $star : null, - buildBlock(scope), - ), - ); - } - - @override - FunctionDeclaration buildFunction([Scope scope]) { - return astFactory.functionDeclaration( - null, - buildAnnotations(scope), - null, - _returnType?.buildType(scope), - _property != null ? new KeywordToken(_property, 0) : null, - stringIdentifier(_name), - buildExpression(scope), - ); - } - - @override - MethodDeclaration buildMethod(bool static, [Scope scope]) { - return astFactory.methodDeclaration( - null, - buildAnnotations(scope), - null, - static ? $static : null, - _returnType?.buildType(scope), - _property != null ? new KeywordToken(_property, 0) : null, - null, - identifier(scope, _name), - null, - _property != Keyword.GET ? buildParameterList(scope) : null, - asAbstract - ? astFactory.emptyFunctionBody($semicolon) - : astFactory.blockFunctionBody( - _modifier?.keyword(), - _modifier?.isStar == true ? $star : null, - buildBlock(scope), - ), - ); - } - - @override - CompilationUnitMember buildTopLevelAst([Scope scope]) => buildFunction(scope); -} - -class _NamedParameterWrapper - implements ValidConstructorMember, ValidMethodMember { - final ParameterBuilder _parameter; - - _NamedParameterWrapper(this._parameter); - - @override - AstNode buildAst([_]) => throw new UnsupportedError('Use within method'); -} - -class _RedirectingConstructorBuilder extends Object - with HasAnnotationsMixin, HasParametersMixin - implements ConstructorBuilder { - final String name; - final TypeBuilder redirectToClass; - final bool asConst; - final String constructor; - - _RedirectingConstructorBuilder( - this.name, - this.redirectToClass, { - this.asConst: false, - this.constructor, - }); - - @override - void addInitializer( - String fieldName, { - ExpressionBuilder toExpression, - String toParameter, - }) { - throw new UnsupportedError('Not valid for redirect constructors'); - } - - @override - void addStatement(StatementBuilder statement) { - throw new UnsupportedError('Not valid for redirect constructors'); - } - - @override - void addStatements(Iterable statements) { - throw new UnsupportedError('Not valid for redirect constructors'); - } - - @override - ConstructorDeclaration buildAst([_]) { - throw new UnsupportedError('Can only be built as part of a class.'); - } - - @override - ConstructorDeclaration buildConstructor( - TypeBuilder returnType, [ - Scope scope, - ]) { - return astFactory.constructorDeclaration( - null, - buildAnnotations(scope), - null, - asConst ? $const : null, - $factory, - returnType.buildType(scope).name, - name != null ? $period : null, - name != null ? stringIdentifier(name) : null, - buildParameterList(scope), - null, - null, - astFactory.constructorName( - redirectToClass.buildType(scope), - constructor != null ? $period : null, - constructor != null ? stringIdentifier(constructor) : null, - ), - astFactory.emptyFunctionBody($semicolon), - ); - } -} - -class _NormalConstructorBuilder extends Object - with HasAnnotationsMixin, HasParametersMixin, HasStatementsMixin - implements ConstructorBuilder { - final _initializers = {}; - final bool _asFactory; - final bool _asConst; - final String _name; - final String _superName; - final List _superInvocation; - - _NormalConstructorBuilder({ - List invokeSuper, - String name, - String superName, - bool asConst: false, - bool asFactory: false, - }) - : _name = name, - _superInvocation = invokeSuper, - _superName = superName, - _asConst = asConst, - _asFactory = asFactory; - - @override - void addInitializer( - String fieldName, { - ExpressionBuilder toExpression, - String toParameter, - }) { - _initializers[fieldName] = toExpression ?? reference(toParameter); - } - - @override - ConstructorDeclaration buildAst([Scope scope]) { - throw new UnsupportedError('Can only be built as part of a class.'); - } - - @override - ConstructorDeclaration buildConstructor( - TypeBuilder returnType, [ - Scope scope, - ]) { - List initializers; - if (_initializers.isNotEmpty) { - initializers ??= []; - initializers.addAll( - _initializers.keys.map((fieldName) { - return astFactory.constructorFieldInitializer( - null, - null, - astFactory.simpleIdentifier(stringToken(fieldName)), - $equals, - _initializers[fieldName].buildExpression(scope), - ); - }), - ); - } - if (_superInvocation != null) { - initializers ??= []; - initializers.add(astFactory.superConstructorInvocation( - $super, - _superName != null ? $period : null, - _superName != null - ? astFactory.simpleIdentifier(stringToken(_superName)) - : null, - astFactory.argumentList( - $openParen, - _superInvocation.map((e) => e.buildExpression(scope)).toList(), - $closeParen, - ), - )); - } - return astFactory.constructorDeclaration( - null, - buildAnnotations(scope), - null, - _asConst ? $const : null, - _asFactory ? $factory : null, - returnType.buildType(scope).name, - _name != null ? $period : null, - _name != null ? stringIdentifier(_name) : null, - buildParameterList(scope), - initializers != null && initializers.isNotEmpty ? $semicolon : null, - initializers, - null, - !hasStatements - ? astFactory.emptyFunctionBody($semicolon) - : astFactory.blockFunctionBody( - null, - null, - buildBlock(scope), - ), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/parameter.dart b/pkgs/code_builder/lib/src/builders/parameter.dart deleted file mode 100644 index c4bbf162d..000000000 --- a/pkgs/code_builder/lib/src/builders/parameter.dart +++ /dev/null @@ -1,260 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/src/builders/annotation.dart'; -import 'package:code_builder/src/builders/method.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/type.dart'; -import 'package:code_builder/src/tokens.dart'; - -/// A short-hand way of constructing a [ParameterBuilder]. -ParameterBuilder parameter( - String name, [ - Iterable members = const [], -]) { - final List annotations = []; - ExpressionBuilder defaultTo; - bool defaultToSet = false; - TypeBuilder type; - for (final member in members) { - if (member is TypeBuilder) { - type = member; - } else if (member is AnnotationBuilder) { - annotations.add(member); - } else if (member is ExpressionBuilder) { - defaultTo = member; - defaultToSet = true; - } else { - throw new StateError('Invalid AST type: ${member.runtimeType}'); - } - } - var builder = new ParameterBuilder( - name, - type: type, - )..addAnnotations(annotations); - if (defaultToSet) { - builder = builder.asOptional(defaultTo); - } - return builder; -} - -/// An [AstBuilder] that can be built up using [ParameterBuilder]. -abstract class HasParameters implements AstBuilder { - /// Adds [parameter] to the builder. - void addNamed(ParameterBuilder parameter); - - /// Adds [parameter] to the builder. - void addPositional(ParameterBuilder parameter); -} - -/// Implements [HasParameters]. -abstract class HasParametersMixin implements HasParameters { - final List<_ParameterPair> _parameters = <_ParameterPair>[]; - - @override - void addNamed(ParameterBuilder parameter, {bool asField: false}) { - _parameters.add(new _ParameterPair.named(parameter, field: asField)); - } - - @override - void addPositional(ParameterBuilder parameter, {bool asField: false}) { - _parameters.add(new _ParameterPair(parameter, field: asField)); - } - - /// Builds a [FormalParameterList]. - FormalParameterList buildParameterList([Scope scope]) { - return astFactory.formalParameterList( - $openParen, - _parameters - .map/**/((p) => p.buildParameter(scope)) - .toList(), - null, - null, - $closeParen, - ); - } -} - -/// Lazily builds an [FormalParameter] AST the builder is invoked. -abstract class ParameterBuilder - implements - AstBuilder, - HasAnnotations, - ValidConstructorMember, - ValidMethodMember { - /// Create a new builder for parameter [name]. - factory ParameterBuilder( - String name, { - TypeBuilder type, - }) = _SimpleParameterBuilder; - - /// Returns as an optional [ParameterBuilder] set to [defaultTo]. - ParameterBuilder asOptional([ExpressionBuilder defaultTo]); - - /// Returns a positional [FormalParameter] AST representing the builder. - FormalParameter buildNamed(bool field, [Scope scope]); - - /// Returns a positional [FormalParameter] AST representing the builder. - FormalParameter buildPositional(bool field, [Scope scope]); - - /// Name of the parameter. - String get name; -} - -/// A marker interface for an AST that could be added to [ParameterBuilder]. -abstract class ValidParameterMember implements AstBuilder {} - -class _OptionalParameterBuilder extends Object - with HasAnnotationsMixin - implements ParameterBuilder { - final ParameterBuilder _parameter; - final ExpressionBuilder _expression; - - _OptionalParameterBuilder(this._parameter, [this._expression]); - - @override - ParameterBuilder asOptional([ExpressionBuilder defaultTo]) { - return new _OptionalParameterBuilder(_parameter, defaultTo); - } - - @override - FormalParameter buildAst([Scope scope]) => buildPositional(false, scope); - - @override - FormalParameter buildNamed(bool field, [Scope scope]) { - return astFactory.defaultFormalParameter( - _parameter.buildPositional(field, scope), - ParameterKind.NAMED, - _expression != null ? $colon : null, - _expression?.buildExpression(scope), - ); - } - - @override - FormalParameter buildPositional(bool field, [Scope scope]) { - return astFactory.defaultFormalParameter( - _parameter.buildPositional(field, scope), - ParameterKind.POSITIONAL, - _expression != null ? $equals : null, - _expression?.buildExpression(scope), - ); - } - - @override - String get name => _parameter.name; -} - -class _ParameterPair { - final bool _isField; - final bool _isNamed; - final ParameterBuilder _parameter; - - _ParameterPair(this._parameter, {bool field: false}) - : _isNamed = false, - _isField = field; - - _ParameterPair.named(this._parameter, {bool field: false}) - : _isNamed = true, - _isField = field; - - FormalParameter buildParameter([Scope scope]) { - return _isNamed - ? _parameter.buildNamed(_isField, scope) - : _parameter.buildPositional(_isField, scope); - } -} - -class _SimpleParameterBuilder extends Object - with HasAnnotationsMixin - implements ParameterBuilder { - @override - final String name; - final TypeBuilder _type; - - _SimpleParameterBuilder( - this.name, { - TypeBuilder type, - }) - : _type = type; - - @override - ParameterBuilder asOptional([ExpressionBuilder defaultTo]) { - return new _OptionalParameterBuilder(this, defaultTo); - } - - @override - FormalParameter buildAst([Scope scope]) => buildPositional(false, scope); - - @override - FormalParameter buildNamed(bool field, [Scope scope]) { - return asOptional().buildNamed(field, scope); - } - - @override - FormalParameter buildPositional(bool field, [Scope scope]) { - if (field) { - return astFactory.fieldFormalParameter( - null, - buildAnnotations(scope), - null, - _type?.buildType(scope), - $this, - $period, - stringIdentifier(name), - null, - null, - ); - } - return astFactory.simpleFormalParameter( - null, - buildAnnotations(scope), - null, - _type?.buildType(scope), - stringIdentifier(name), - ); - } -} - -/// A parameter type that represents a function definition. -class FunctionParameterBuilder extends Object - with HasAnnotationsMixin, HasParametersMixin - implements ParameterBuilder { - @override - final String name; - final TypeBuilder returnType; - - FunctionParameterBuilder( - this.name, { - this.returnType, - }); - - @override - ParameterBuilder asOptional([ExpressionBuilder defaultTo]) { - return new _OptionalParameterBuilder(this, defaultTo); - } - - @override - FunctionTypedFormalParameter buildAst([Scope scope]) => - buildPositional(false, scope); - - @override - FunctionTypedFormalParameter buildNamed(bool field, [Scope scope]) { - return asOptional().buildNamed(field, scope); - } - - @override - FunctionTypedFormalParameter buildPositional(bool field, [Scope scope]) { - return astFactory.functionTypedFormalParameter( - null, - buildAnnotations(scope), - returnType?.buildType(scope), - stringIdentifier(name), - null, - buildParameterList(scope), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/reference.dart b/pkgs/code_builder/lib/src/builders/reference.dart deleted file mode 100644 index 07400946b..000000000 --- a/pkgs/code_builder/lib/src/builders/reference.dart +++ /dev/null @@ -1,122 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/src/builders/annotation.dart'; -import 'package:code_builder/src/builders/expression.dart'; -import 'package:code_builder/src/builders/file.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/builders/type.dart'; -import 'package:code_builder/src/tokens.dart'; - -/// An explicit reference to `this`. -final ReferenceBuilder explicitThis = reference('this'); - -/// Creates a reference called [name]. -/// -/// **NOTE**: To refer to a _generic_ type, use [TypeBuilder] instead: -/// // Refer to `List` -/// new TypeBuilder( -/// 'List', -/// genericTypes: [reference('String')], -/// ) -ReferenceBuilder reference(String name, [String importUri]) { - return new ReferenceBuilder._(name, importUri); -} - -/// An abstract way of representing other types of [AstBuilder]. -class ReferenceBuilder extends Object - with AbstractExpressionMixin, AbstractTypeBuilderMixin, TopLevelMixin - implements AnnotationBuilder, ExpressionBuilder, TypeBuilder { - final String _importFrom; - - /// Name of the reference. - final String name; - - ReferenceBuilder._(this.name, [this._importFrom]); - - @override - Annotation buildAnnotation([Scope scope]) { - return astFactory.annotation( - $at, - identifier(scope, name, _importFrom), - null, - null, - null, - ); - } - - @override - AstNode buildAst([Scope scope]) => buildType(scope); - - @override - Expression buildExpression([Scope scope]) { - return identifier( - scope, - name, - _importFrom, - ); - } - - @override - TypeName buildType([Scope scope]) { - return new TypeBuilder(name, importFrom: _importFrom).buildType(scope); - } - - @override - ExportBuilder toExportBuilder() { - if (_importFrom == null) { - throw new StateError('Cannot create an import - no URI provided'); - } - return new ExportBuilder(_importFrom)..show(name); - } - - @override - ImportBuilder toImportBuilder({bool deferred: false, String prefix}) { - if (_importFrom == null) { - throw new StateError('Cannot create an import - no URI provided'); - } - return new ImportBuilder( - _importFrom, - deferred: deferred, - prefix: prefix, - )..show(name); - } - - /// Returns a new [ReferenceBuilder] with [genericTypes]. - /// - /// Example use: - /// // List - /// reference('List').toTyped([reference('String')]) - ReferenceBuilder toTyped(Iterable genericTypes) { - return new _TypedReferenceBuilder( - genericTypes.toList(), - name, - _importFrom, - ); - } -} - -class _TypedReferenceBuilder extends ReferenceBuilder { - final List _genericTypes; - - _TypedReferenceBuilder( - this._genericTypes, - String name, - String importFrom, - ) - : super._(name, importFrom); - - @override - TypeName buildType([Scope scope]) { - return new TypeBuilder( - name, - importFrom: _importFrom, - genericTypes: _genericTypes, - ) - .buildType(scope); - } -} diff --git a/pkgs/code_builder/lib/src/builders/shared.dart b/pkgs/code_builder/lib/src/builders/shared.dart deleted file mode 100644 index 772759fab..000000000 --- a/pkgs/code_builder/lib/src/builders/shared.dart +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/src/scope.dart'; -import 'package:code_builder/src/tokens.dart'; - -export 'package:code_builder/src/scope.dart'; - -/// Returns a string [Literal] from [value]. -Identifier stringIdentifier(String value) => - astFactory.simpleIdentifier(stringToken(value)); - -/// Lazily builds an analyzer [AstNode] when [buildAst] is invoked. -/// -/// Most builders should also have specific typed methods for returning their -/// type of AST node, such as `buildExpression` for returning an `Expression` -/// AST. -abstract class AstBuilder { - /// Returns an [AstNode] representing the state of the current builder. - /// - /// If [scope] is provided then identifiers are automatically prefixed and - /// imports are collected in order to emit a final File AST that does not - /// have conflicting or missing imports. - T buildAst([Scope scope]); -} diff --git a/pkgs/code_builder/lib/src/builders/statement.dart b/pkgs/code_builder/lib/src/builders/statement.dart deleted file mode 100644 index 9c36211cd..000000000 --- a/pkgs/code_builder/lib/src/builders/statement.dart +++ /dev/null @@ -1,120 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/src/builders/method.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement/if.dart'; -import 'package:code_builder/src/builders/statement/raw.dart'; -import 'package:code_builder/src/tokens.dart'; - -export 'package:code_builder/src/builders/statement/break.dart' - show breakStatement; -export 'package:code_builder/src/builders/statement/for.dart' - show ForStatementBuilder; -export 'package:code_builder/src/builders/statement/if.dart' - show IfStatementBuilder, elseIf, elseThen, ifThen; -export 'package:code_builder/src/builders/statement/switch.dart' - show - SwitchCaseBuilder, - SwitchDefaultCaseBuilder, - SwitchStatementBuilder, - switchDefault, - switchCase, - switchStatement; -export 'package:code_builder/src/builders/statement/while.dart' - show WhileStatementBuilder; - -/// An [AstBuilder] that can add [StatementBuilder]. -abstract class HasStatements implements AstBuilder { - /// Adds [statement] to the builder. - void addStatement(StatementBuilder statement); - - /// Adds [statements] to the builder. - void addStatements(Iterable statements); -} - -/// Implements [HasStatements]. -abstract class HasStatementsMixin implements HasStatements { - final List _statements = []; - - @override - void addStatement(StatementBuilder statement) { - _statements.add(statement); - } - - @override - void addStatements(Iterable statements) { - _statements.addAll(statements); - } - - /// Returns a [Block] statement. - Block buildBlock([Scope scope]) { - return astFactory.block( - $openCurly, - buildStatements(scope), - $closeCurly, - ); - } - - /// Returns a [List] of all built [Statement]s. - List buildStatements([Scope scope]) { - return _statements - .map/**/((e) => e.buildStatement(scope)) - .toList(); - } - - /// Clones all expressions to [clone]. - void cloneStatementsTo(HasStatements clone) { - clone.addStatements(_statements); - } - - /// Whether at least one statement was added. - bool get hasStatements => _statements.isNotEmpty; -} - -/// Lazily builds an [Statement] AST when [buildStatement] is invoked. -abstract class StatementBuilder - implements - AstBuilder, - TopLevelMixin, - ValidIfStatementMember, - ValidConstructorMember, - ValidMethodMember { - factory StatementBuilder.raw(String raw(Scope scope)) = RawStatementBuilder; - - /// Returns an [Statement] AST representing the builder. - Statement buildStatement([Scope scope]); -} - -/// Implements [buildTopLevelAst]. -abstract class TopLevelMixin { - /// Returns a [Statement] suitable for a top-level expression. - /// - /// May throw [UnsupportedError]. - CompilationUnitMember buildTopLevelAst([Scope scope]) { - throw new UnsupportedError('$runtimeType does not work in the top-level'); - } -} - -/// Just the `return;` statement, for `void` methods. -const StatementBuilder returnVoid = const _ReturnStatementBuilder(); - -class _ReturnStatementBuilder extends Object implements StatementBuilder { - const _ReturnStatementBuilder(); - - @override - Statement buildAst([_]) => buildStatement(); - - @override - Statement buildStatement([_]) { - return astFactory.returnStatement($return, null, $semicolon); - } - - @override - CompilationUnitMember buildTopLevelAst([Scope scope]) { - throw new UnsupportedError('$runtimeType does not work in the top-level'); - } -} diff --git a/pkgs/code_builder/lib/src/builders/statement/block.dart b/pkgs/code_builder/lib/src/builders/statement/block.dart deleted file mode 100644 index 284440b7e..000000000 --- a/pkgs/code_builder/lib/src/builders/statement/block.dart +++ /dev/null @@ -1,32 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/tokens.dart'; - -/// Represents a series of [StatementBuilder]s as a block statement AST. -abstract class BlockStatementBuilder - implements HasStatements, StatementBuilder { - /// Creates a new [BlockStatementBuilder]. - factory BlockStatementBuilder() = _BlockStatementBuilder; -} - -class _BlockStatementBuilder extends Object - with HasStatementsMixin, TopLevelMixin - implements BlockStatementBuilder { - @override - AstNode buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) { - return astFactory.block( - $openCurly, - buildStatements(scope), - $closeCurly, - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/statement/break.dart b/pkgs/code_builder/lib/src/builders/statement/break.dart deleted file mode 100644 index e2da27535..000000000 --- a/pkgs/code_builder/lib/src/builders/statement/break.dart +++ /dev/null @@ -1,30 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/tokens.dart'; - -/// Represents a break statement AST. -const breakStatement = const _BreakStatementBuilder(); - -class _BreakStatementBuilder extends Object implements StatementBuilder { - const _BreakStatementBuilder(); - - @override - AstNode buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) => buildBreakStatement(scope); - - BreakStatement buildBreakStatement([Scope scope]) => - astFactory.breakStatement($break, null, $semicolon); - - @override - CompilationUnitMember buildTopLevelAst([Scope scope]) { - throw new UnsupportedError('$runtimeType does not work in the top-level'); - } -} diff --git a/pkgs/code_builder/lib/src/builders/statement/for.dart b/pkgs/code_builder/lib/src/builders/statement/for.dart deleted file mode 100644 index 58bf8d869..000000000 --- a/pkgs/code_builder/lib/src/builders/statement/for.dart +++ /dev/null @@ -1,121 +0,0 @@ -// 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. - -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/src/builders/expression.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/tokens.dart'; - -abstract class ForStatementBuilder implements HasStatements, StatementBuilder { - factory ForStatementBuilder( - String identifier, - ExpressionBuilder initializer, - ExpressionBuilder condition, - List updaters, - ) = _ForLoopStatementBuilder; - - factory ForStatementBuilder.forEach( - String identifier, - ExpressionBuilder iterable, { - bool asAwait: false, - bool asFinal: false, - }) { - return new _ForIteratorStatementBuilder( - asAwait, - asFinal, - identifier, - iterable, - ); - } -} - -class _ForIteratorStatementBuilder extends Object - with HasStatementsMixin, TopLevelMixin - implements ForStatementBuilder { - final bool _asAwait; - final bool _asFinal; - final String _identifier; - final ExpressionBuilder _iterable; - - _ForIteratorStatementBuilder( - this._asAwait, - this._asFinal, - this._identifier, - this._iterable, - ); - - @override - AstNode buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) { - return astFactory.forEachStatementWithDeclaration( - _asAwait ? $await : null, - $for, - $openParen, - astFactory.declaredIdentifier( - null, - null, - _asFinal ? $final : $var, - null, - astFactory.simpleIdentifier(stringToken(_identifier)), - ), - $in, - _iterable.buildExpression(scope), - $closeParen, - buildBlock(scope), - ); - } -} - -class _ForLoopStatementBuilder extends Object - with HasStatementsMixin, TopLevelMixin - implements ForStatementBuilder { - final String _identifier; - final ExpressionBuilder _initializer; - final ExpressionBuilder _condition; - final List _updaters; - - _ForLoopStatementBuilder( - this._identifier, - this._initializer, - this._condition, - this._updaters, - ); - - @override - AstNode buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) { - return astFactory.forStatement( - $for, - $openParen, - astFactory.variableDeclarationList( - null, - null, - $var, - null, - [ - astFactory.variableDeclaration( - astFactory.simpleIdentifier( - stringToken(_identifier), - ), - $equals, - _initializer.buildExpression(scope), - ), - ], - ), - null, - $semicolon, - _condition.buildExpression(scope), - $semicolon, - _updaters.map((e) => e.buildExpression(scope)).toList(), - $closeParen, - buildBlock(scope), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/statement/if.dart b/pkgs/code_builder/lib/src/builders/statement/if.dart deleted file mode 100644 index 875ee8cfb..000000000 --- a/pkgs/code_builder/lib/src/builders/statement/if.dart +++ /dev/null @@ -1,101 +0,0 @@ -// 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. - -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/src/builders/expression.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/builders/statement/block.dart'; -import 'package:code_builder/src/tokens.dart'; - -/// Denotes an [ifStmt] that should be added as an `else if` in [ifThen]. -_IfStatementBuilderWrapper elseIf(IfStatementBuilder ifStmt) { - return new _IfStatementBuilderWrapper(ifStmt, null); -} - -/// Denotes a series of [statements] added to a final `else` in [ifThen]. -_IfStatementBuilderWrapper elseThen(Iterable statements) { - return new _IfStatementBuilderWrapper(null, statements); -} - -/// Short-hand syntax for `new IfStatementBuilder(...)`. -IfStatementBuilder ifThen( - ExpressionBuilder condition, [ - Iterable members = const [], -]) { - final ifStmt = new IfStatementBuilder(condition); - IfStatementBuilder current = ifStmt; - for (final member in members) { - if (member is _IfStatementBuilderWrapper) { - if (member._ifStmt != null) { - current.setElse(member._ifStmt); - current = member._ifStmt; - } else { - current.setElse( - new BlockStatementBuilder()..addStatements(member._elseStmts)); - current = null; - } - } else if (member is StatementBuilder) { - ifStmt.addStatement(member); - } else { - throw new UnsupportedError('Invalid type: ${member.runtimeType}'); - } - } - return ifStmt; -} - -/// Builds an [IfStatement] AST. -abstract class IfStatementBuilder implements HasStatements, StatementBuilder { - /// Returns a new [IfStatementBuilder] where `if (condition) {`. - factory IfStatementBuilder(ExpressionBuilder condition) { - return new _BlockIfStatementBuilder(condition); - } - - /// Adds an `else` block that evaluates [statements]. - void setElse(StatementBuilder statements); -} - -/// Marker interface for builders valid for use with [ifThen]. -abstract class ValidIfStatementMember implements AstBuilder {} - -class _BlockIfStatementBuilder extends Object - with HasStatementsMixin, TopLevelMixin - implements IfStatementBuilder { - final ExpressionBuilder _condition; - StatementBuilder _elseBlock; - - _BlockIfStatementBuilder(this._condition); - - @override - AstNode buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) { - return astFactory.ifStatement( - $if, - $openParen, - _condition.buildExpression(scope), - $closeParen, - buildBlock(scope), - _elseBlock != null ? $else : null, - _elseBlock?.buildStatement(scope), - ); - } - - @override - void setElse(StatementBuilder statements) { - _elseBlock = statements; - } -} - -class _IfStatementBuilderWrapper implements ValidIfStatementMember { - final IfStatementBuilder _ifStmt; - final Iterable _elseStmts; - - _IfStatementBuilderWrapper(this._ifStmt, this._elseStmts); - - @override - AstNode buildAst([_]) => throw new UnsupportedError('Use within ifThen.'); -} diff --git a/pkgs/code_builder/lib/src/builders/statement/raw.dart b/pkgs/code_builder/lib/src/builders/statement/raw.dart deleted file mode 100644 index ed489d03a..000000000 --- a/pkgs/code_builder/lib/src/builders/statement/raw.dart +++ /dev/null @@ -1,29 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:func/func.dart'; - -class RawStatementBuilder implements StatementBuilder { - final Func1 _raw; - - const RawStatementBuilder(this._raw); - - @override - AstNode buildAst([Scope scope]) { - FunctionDeclaration d = - parseCompilationUnit('raw() { ${_raw(scope)} }').declarations.first; - BlockFunctionBody f = d.functionExpression.childEntities.elementAt(1); - Block b = f.childEntities.first; - return b.statements.first; - } - - @override - Statement buildStatement([Scope scope]) => buildAst(scope); - - @override - CompilationUnitMember buildTopLevelAst([Scope scope]) => buildAst(scope); -} diff --git a/pkgs/code_builder/lib/src/builders/statement/switch.dart b/pkgs/code_builder/lib/src/builders/statement/switch.dart deleted file mode 100644 index f8e49cb85..000000000 --- a/pkgs/code_builder/lib/src/builders/statement/switch.dart +++ /dev/null @@ -1,169 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/expression.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/tokens.dart'; - -/// Short-hand syntax for `new SwitchCaseBuilder(...)`. -SwitchCaseBuilder switchCase( - ExpressionBuilder condition, [ - Iterable statements = const [], -]) => - new SwitchCaseBuilder(condition)..addStatements(statements ?? []); - -/// Short-hand syntax for `new SwitchDefaultCaseBuilder(...)`. -SwitchDefaultCaseBuilder switchDefault([ - Iterable statements = const [], -]) => - new SwitchDefaultCaseBuilder()..addStatements(statements ?? []); - -/// Short-hand syntax for `new SwitchStatementBuilder(...)`. -SwitchStatementBuilder switchStatement( - ExpressionBuilder expression, { - Iterable cases: const [], - SwitchDefaultCaseBuilder defaultCase, -}) => - new SwitchStatementBuilder(expression) - ..setDefaultCase(defaultCase) - ..addCases(cases ?? []); - -/// Represents an [ExpressionBuilder] switches as an AST. -abstract class SwitchStatementBuilder implements StatementBuilder { - /// Creates a new [SwitchStatementBuilder]. - factory SwitchStatementBuilder( - ExpressionBuilder expression, [ - Iterable members = const [], - ]) => - new _SwitchStatementBuilder(expression, members); - - /// Adds a [switchCase] to the builder. - void addCase(SwitchCaseBuilder switchCase); - - /// Adds a [switchCase]s to the builder. - void addCases(Iterable switchCases); - - /// Returns an [SwitchStatement] AST representing the builder. - SwitchStatement buildSwitchStatement(); - - /// Sets the `default` cases of the builder. - void setDefaultCase(SwitchDefaultCaseBuilder defaultCase); -} - -/// A marker interface for an AST usable within a [SwitchStatementBuilder]. -/// -/// This can be either a [SwitchCaseBuilder] or a [SwitchDefaultCaseBuilder]. -abstract class ValidSwitchMember {} - -/// Represents an [ExpressionBuilder] and statements as a switch case AST. -abstract class SwitchCaseBuilder implements HasStatements, ValidSwitchMember { - /// Creates a new [SwitchCaseBuilder]. - factory SwitchCaseBuilder(ExpressionBuilder condition) = _SwitchCaseBuilder; - - /// Returns an [SwitchMember] AST representing the builder. - SwitchMember buildSwitchMember([Scope scope]); -} - -/// Represents a series of [Statement]s as a default switch case AST. -abstract class SwitchDefaultCaseBuilder - implements HasStatements, ValidSwitchMember { - factory SwitchDefaultCaseBuilder() = _SwitchDefaultCaseBuilder; - - /// Returns an [SwitchMember] AST representing the builder. - SwitchMember buildSwitchMember([Scope scope]); -} - -class _SwitchStatementBuilder extends Object - with TopLevelMixin - implements SwitchStatementBuilder { - final ExpressionBuilder _expression; - final List _cases = []; - SwitchDefaultCaseBuilder _defaultCase; - - _SwitchStatementBuilder( - this._expression, [ - Iterable members = const [], - ]) { - for (final member in members) { - if (member is SwitchDefaultCaseBuilder) { - _defaultCase = member; - } else if (member is SwitchCaseBuilder) { - _cases.add(member); - } - } - } - - @override - void addCase(SwitchCaseBuilder switchCase) => _cases.add(switchCase); - - @override - void addCases(Iterable switchCases) => - _cases.addAll(switchCases); - - @override - void setDefaultCase(SwitchDefaultCaseBuilder defaultCase) { - _defaultCase = defaultCase; - } - - @override - AstNode buildAst([Scope scope]) => buildStatement(); - - @override - SwitchStatement buildSwitchStatement([Scope scope]) { - var members = _cases.map((c) => c.buildSwitchMember(scope)).toList(); - if (_defaultCase != null) { - members.add(_defaultCase.buildSwitchMember(scope)); - } - return astFactory.switchStatement( - $switch, - $openBracket, - _expression.buildExpression(), - $closeParen, - $openBracket, - members, - $closeBracket, - ); - } - - @override - Statement buildStatement([Scope scope]) => buildSwitchStatement(scope); -} - -class _SwitchCaseBuilder extends Object - with HasStatementsMixin - implements SwitchCaseBuilder { - final ExpressionBuilder _condition; - - _SwitchCaseBuilder(this._condition); - - @override - AstNode buildAst([Scope scope]) => buildSwitchMember(scope); - - @override - SwitchMember buildSwitchMember([Scope scope]) => astFactory.switchCase( - null, - $case, - _condition.buildExpression(), - $colon, - buildStatements(scope), - ); -} - -class _SwitchDefaultCaseBuilder extends Object - with HasStatementsMixin - implements SwitchDefaultCaseBuilder { - @override - AstNode buildAst([Scope scope]) => buildSwitchMember(scope); - - @override - SwitchMember buildSwitchMember([Scope scope]) => astFactory.switchDefault( - null, - $default, - $colon, - buildStatements(), - ); -} diff --git a/pkgs/code_builder/lib/src/builders/statement/while.dart b/pkgs/code_builder/lib/src/builders/statement/while.dart deleted file mode 100644 index ba1cb622c..000000000 --- a/pkgs/code_builder/lib/src/builders/statement/while.dart +++ /dev/null @@ -1,44 +0,0 @@ -// 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. - -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:code_builder/src/builders/expression.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/tokens.dart'; - -class WhileStatementBuilder extends HasStatementsMixin - with TopLevelMixin - implements StatementBuilder { - final bool _asDo; - final ExpressionBuilder _condition; - - WhileStatementBuilder(this._asDo, this._condition); - - @override - AstNode buildAst([Scope scope]) => buildStatement(scope); - - @override - Statement buildStatement([Scope scope]) { - if (_asDo) { - return astFactory.doStatement( - $do, - buildBlock(scope), - $while, - $openParen, - _condition.buildExpression(scope), - $closeParen, - $semicolon, - ); - } - return astFactory.whileStatement( - $while, - $openParen, - _condition.buildExpression(scope), - $closeParen, - buildBlock(scope), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/type.dart b/pkgs/code_builder/lib/src/builders/type.dart deleted file mode 100644 index e39de77bd..000000000 --- a/pkgs/code_builder/lib/src/builders/type.dart +++ /dev/null @@ -1,152 +0,0 @@ -// 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. - -library code_builder.src.builders.type; - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/token.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; -import 'package:analyzer/src/dart/ast/token.dart'; -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/src/builders/annotation.dart'; -import 'package:code_builder/src/builders/expression.dart'; -import 'package:code_builder/src/builders/method.dart'; -import 'package:code_builder/src/builders/parameter.dart'; -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/builders/statement.dart'; -import 'package:code_builder/src/tokens.dart'; - -part 'type/new_instance.dart'; -part 'type/type_def.dart'; - -/// Implements the `new` and `const` constructor calls. -abstract class AbstractTypeBuilderMixin { - /// Invokes `const` on this type. - NewInstanceBuilder constInstance( - Iterable positionalArguments, { - String constructor, - Map namedArguments: const {}, - }) { - final builder = new NewInstanceBuilder._const( - this, - constructor: constructor, - ); - _addArguments(builder, positionalArguments, namedArguments); - return builder; - } - - /// Invokes `new` on this type. - NewInstanceBuilder newInstance( - Iterable positional, { - String constructor, - Map named: const {}, - }) { - final builder = new NewInstanceBuilder._new( - this, - constructor: constructor, - ); - _addArguments(builder, positional, named); - return builder; - } - - /// Returns as an import to this reference. - ImportBuilder toImportBuilder({bool deferred: false, String prefix}); - - /// Returns as an export to the reference. - ExportBuilder toExportBuilder(); - - static void _addArguments( - NewInstanceBuilder builder, - Iterable positional, - Map named, - ) { - positional.forEach(builder.addPositionalArgument); - named.forEach(builder.addNamedArgument); - } -} - -/// Lazily builds an [TypeName] AST when [buildType] is invoked. -class TypeBuilder extends Object - with AbstractExpressionMixin, AbstractTypeBuilderMixin, TopLevelMixin - implements - AstBuilder, - ExpressionBuilder, - ValidMethodMember, - ValidParameterMember { - final List _generics; - final String _importFrom; - final String _name; - - /// Creates a new [TypeBuilder]. - /// - /// Can be made generic by passing one or more [genericTypes]. - /// - /// Optionally specify the source to [importFrom] to resolve this type. - factory TypeBuilder( - String name, { - Iterable genericTypes: const [], - String importFrom, - }) { - return new TypeBuilder._( - name, - importFrom, - genericTypes.toList(growable: false), - ); - } - - TypeBuilder._( - this._name, - this._importFrom, - this._generics, - ); - - @override - AstNode buildAst([Scope scope]) => buildType(scope); - - /// Returns an [TypeName] AST representing the builder. - TypeName buildType([Scope scope]) { - return astFactory.typeName( - identifier( - scope, - _name, - _importFrom, - ), - _generics.isEmpty - ? null - : astFactory.typeArgumentList( - $openBracket, - _generics.map((t) => t.buildType(scope)).toList(), - $closeBracket, - ), - ); - } - - @override - ExportBuilder toExportBuilder() { - if (_importFrom == null) { - throw new StateError('Cannot create an import - no URI provided'); - } - return new ExportBuilder(_importFrom)..show(_name); - } - - @override - ImportBuilder toImportBuilder({bool deferred: false, String prefix}) { - if (_importFrom == null) { - throw new StateError('Cannot create an import - no URI provided'); - } - return new ImportBuilder( - _importFrom, - deferred: deferred, - prefix: prefix, - )..show(_name); - } - - @override - Expression buildExpression([Scope scope]) { - if (_generics.isNotEmpty) { - throw new StateError('Cannot refer to a type with generic parameters'); - } - return reference(_name, _importFrom).buildExpression(scope); - } -} diff --git a/pkgs/code_builder/lib/src/builders/type/new_instance.dart b/pkgs/code_builder/lib/src/builders/type/new_instance.dart deleted file mode 100644 index e1ac8f5cf..000000000 --- a/pkgs/code_builder/lib/src/builders/type/new_instance.dart +++ /dev/null @@ -1,77 +0,0 @@ -// 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. - -part of code_builder.src.builders.type; - -/// Lazily builds an [InstanceCreationExpression] AST when built. -/// -/// See [TypeBuilder]: -/// - [TypeBuilder.constInstance] -/// - [TypeBuilder.newInstance] -abstract class NewInstanceBuilder - implements AnnotationBuilder, InvocationBuilder { - factory NewInstanceBuilder._const( - TypeBuilder type, { - String constructor, - }) { - return new _NewInvocationBuilderImpl( - Keyword.CONST, - type, - constructor, - ); - } - - factory NewInstanceBuilder._new( - TypeBuilder type, { - String constructor, - }) { - return new _NewInvocationBuilderImpl( - Keyword.NEW, - type, - constructor, - ); - } -} - -class _NewInvocationBuilderImpl extends Object - with AbstractExpressionMixin, AbstractInvocationBuilderMixin, TopLevelMixin - implements NewInstanceBuilder { - final String _constructor; - final Keyword _keyword; - final TypeBuilder _type; - - _NewInvocationBuilderImpl( - this._keyword, - this._type, - this._constructor, - ); - - @override - Annotation buildAnnotation([Scope scope]) { - return astFactory.annotation( - $at, - _type.buildType(scope).name, - $period, - _constructor != null && _constructor.isNotEmpty - ? stringIdentifier(_constructor) - : null, - buildArgumentList(scope: scope), - ); - } - - @override - Expression buildExpression([Scope scope]) { - return astFactory.instanceCreationExpression( - new KeywordToken(_keyword, 0), - astFactory.constructorName( - _type.buildType(scope), - _constructor != null && _constructor.isNotEmpty ? $period : null, - _constructor != null && _constructor.isNotEmpty - ? stringIdentifier(_constructor) - : null, - ), - buildArgumentList(scope: scope), - ); - } -} diff --git a/pkgs/code_builder/lib/src/builders/type/type_def.dart b/pkgs/code_builder/lib/src/builders/type/type_def.dart deleted file mode 100644 index 3be307b01..000000000 --- a/pkgs/code_builder/lib/src/builders/type/type_def.dart +++ /dev/null @@ -1,61 +0,0 @@ -// 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. - -part of code_builder.src.builders.type; - -TypeParameterList typeParameters(Scope scope, Map types) { - if (types.isEmpty) { - return null; - } - return astFactory.typeParameterList( - $openBracket, - types.keys.map((name) { - final type = types[name]; - return astFactory.typeParameter( - null, - null, - stringIdentifier(name), - type != null ? $extends : null, - type?.buildType(scope), - ); - }).toList(), - $closeBracket, - ); -} - -/// Lazily build a `typedef`, or [FunctionTypeAlias] AST. -class TypeDefBuilder extends AstBuilder - with HasAnnotationsMixin, HasParametersMixin, TopLevelMixin { - /// Optional generic type parameters. - final Map genericTypes; - - /// Name of the `typedef`. - final String name; - - /// Return type; if `null` defaults to implicitly dynamic. - final TypeBuilder returnType; - - TypeDefBuilder( - this.name, { - this.genericTypes: const {}, - this.returnType, - }); - - @override - FunctionTypeAlias buildAst([Scope scope]) { - return astFactory.functionTypeAlias( - null, - buildAnnotations(scope), - null, - returnType?.buildType(scope), - stringIdentifier(name), - typeParameters(scope, genericTypes), - buildParameterList(scope), - $semicolon, - ); - } - - @override - CompilationUnitMember buildTopLevelAst([Scope scope]) => buildAst(scope); -} diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart new file mode 100644 index 000000000..9de6f7f0d --- /dev/null +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -0,0 +1,322 @@ +// 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 'specs/annotation.dart'; +import 'specs/class.dart'; +import 'specs/code.dart'; +import 'specs/constructor.dart'; +import 'specs/field.dart'; +import 'specs/method.dart'; +import 'specs/reference.dart'; +import 'specs/type_reference.dart'; +import 'visitors.dart'; + +class DartEmitter extends GeneralizingSpecVisitor { + const DartEmitter(); + + @override + visitAnnotation(Annotation spec, [StringSink output]) { + (output ??= new StringBuffer()).write('@'); + visitCode(spec.code, output); + output.write(' '); + return output; + } + + @override + visitClass(Class spec, [StringSink output]) { + output ??= new StringBuffer(); + spec.docs.forEach(output.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, output)); + if (spec.abstract) { + output.write('abstract '); + } + output.write('class ${spec.name}'); + visitTypeParameters(spec.types, output); + if (spec.extend != null) { + output.write(' extends '); + visitType(spec.extend, output); + } + if (spec.mixins.isNotEmpty) { + output + ..write(' with ') + ..writeAll(spec.mixins.map(visitType), ','); + } + if (spec.implements.isNotEmpty) { + output + ..write(' implements ') + ..writeAll(spec.implements.map(visitType), ','); + } + output.write(' {'); + spec.constructors.forEach((c) => visitConstructor(c, spec.name, output)); + spec.fields.forEach((f) => visitField(f, output)); + spec.methods.forEach((m) => visitMethod(m, output)); + output.write(' }'); + return output; + } + + @override + visitConstructor(Constructor spec, String clazz, [StringSink output]) { + output ??= new StringBuffer(); + spec.docs.forEach(output.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, output)); + if (spec.external) { + output.write('external '); + } + if (spec.factory) { + output.write('factory '); + } + if (spec.constant) { + output.write('const '); + } + output.write(clazz); + if (spec.name != null) { + output..write('.')..write(spec.name); + } + output.write('('); + if (spec.requiredParameters.isNotEmpty) { + var count = 0; + for (final p in spec.requiredParameters) { + count++; + _visitParameter(p, output); + if (spec.requiredParameters.length != count || + spec.optionalParameters.isNotEmpty) { + output.write(', '); + } + } + } + if (spec.optionalParameters.isNotEmpty) { + final named = spec.optionalParameters.any((p) => p.named); + if (named) { + output.write('{'); + } else { + output.write('['); + } + var count = 0; + for (final p in spec.optionalParameters) { + count++; + _visitParameter(p, output, optional: true, named: named); + if (spec.optionalParameters.length != count) { + output.write(', '); + } + } + if (named) { + output.write('}'); + } else { + output.write(']'); + } + } + output.write(')'); + if (spec.initializers.isNotEmpty) { + output.write(' : '); + var count = 0; + for (final initializer in spec.initializers) { + count++; + visitCode(initializer, output); + if (count != spec.initializers.length) { + output.write(', '); + } + } + } + if (spec.redirect != null) { + output.write(' = '); + visitType(spec.redirect.toType(), output); + output.write(';'); + } else if (spec.body != null) { + if (spec.lambda) { + output.write(' => '); + visitCode(spec.body, output); + output.write(';'); + } else { + output.write(' { '); + visitCode(spec.body, output); + output.write(' }'); + } + } else { + output.write(';'); + } + return output; + } + + static final Pattern _refReplace = new RegExp(r'{{([^{}]*)}}'); + + @override + visitCode(Code spec, [StringSink output]) { + output ??= new StringBuffer(); + var code = spec.code; + if (spec.specs.isNotEmpty) { + code = code.replaceAllMapped(_refReplace, (match) { + // ignore: strong_mode_implicit_dynamic_variable + final lazy = spec.specs[match.group(1)]; + return lazy().accept(this).toString(); + }); + } + return output..write(code); + } + + @override + visitField(Field spec, [StringSink output]) { + output ??= new StringBuffer(); + spec.docs.forEach(output.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, output)); + if (spec.static) { + output.write('static '); + } + switch (spec.modifier) { + case FieldModifier.var$: + if (spec.type == null) { + output.write('var '); + } + break; + case FieldModifier.final$: + output.write('final '); + break; + case FieldModifier.constant: + output.write('const '); + break; + } + if (spec.type != null) { + visitType(spec.type, output); + output.write(' '); + } + output.write(spec.name); + if (spec.assignment != null) { + output.write(' = '); + visitCode(spec.assignment, output); + } + output.write(';'); + return output; + } + + @override + visitMethod(Method spec, [StringSink output]) { + output ??= new StringBuffer(); + spec.docs.forEach(output.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, output)); + if (spec.external) { + output.write('external '); + } + if (spec.static) { + output.write('static '); + } + if (spec.returns != null) { + visitType(spec.returns, output); + output.write(' '); + } + if (spec.type == MethodType.getter) { + output..write('get ')..write(spec.name); + } else { + if (spec.type == MethodType.setter) { + output.write('set '); + } + output.write(spec.name); + visitTypeParameters(spec.types, output); + output.write('('); + if (spec.requiredParameters.isNotEmpty) { + var count = 0; + for (final p in spec.requiredParameters) { + count++; + _visitParameter(p, output); + if (spec.requiredParameters.length != count || + spec.optionalParameters.isNotEmpty) { + output.write(', '); + } + } + } + if (spec.optionalParameters.isNotEmpty) { + final named = spec.optionalParameters.any((p) => p.named); + if (named) { + output.write('{'); + } else { + output.write('['); + } + var count = 0; + for (final p in spec.optionalParameters) { + count++; + _visitParameter(p, output, optional: true, named: named); + if (spec.optionalParameters.length != count) { + output.write(', '); + } + } + if (named) { + output.write('}'); + } else { + output.write(']'); + } + } + output.write(')'); + } + if (spec.body != null) { + if (spec.lambda) { + output.write(' => '); + } else { + output.write(' { '); + } + visitCode(spec.body, output); + if (spec.lambda) { + output.write(';'); + } else { + output.write(' } '); + } + } else { + output.write(';'); + } + return output; + } + + // Expose as a first-class visit function only if needed. + void _visitParameter( + Parameter spec, + StringSink output, { + bool optional: false, + bool named: false, + }) { + spec.docs.forEach(output.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, output)); + if (spec.type != null) { + visitType(spec.type, output); + output.write(' '); + } + if (spec.toThis) { + output.write('this.'); + } + output.write(spec.name); + if (optional && spec.defaultTo != null) { + if (spec.named) { + output.write(': '); + } else { + output.write(' = '); + } + visitCode(spec.defaultTo, output); + } + } + + @override + visitReference(Reference spec, [StringSink output]) { + return (output ??= new StringBuffer())..write(spec.symbol); + } + + @override + visitType(TypeReference spec, [StringSink output]) { + output ??= new StringBuffer(); + visitReference(spec, output); + if (spec.bound != null) { + output.write(' extends '); + visitType(spec.bound, output); + } + visitTypeParameters(spec.types, output); + return output; + } + + @override + visitTypeParameters(Iterable specs, [StringSink output]) { + output ??= new StringBuffer(); + if (specs.isNotEmpty) { + output + ..write('<') + ..writeAll(specs.map(visitType), ',') + ..write('>'); + } + return output; + } +} diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart new file mode 100644 index 000000000..d0849094a --- /dev/null +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -0,0 +1,50 @@ +// 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:dart_style/dart_style.dart'; +import 'package:matcher/matcher.dart'; + +import 'base.dart'; +import 'emitter.dart'; + +final _formatter = new DartFormatter(); + +/// Runs dartfmt. +String _dartfmt(String source) { + try { + return _formatter.format(source); + } on FormatException catch (_) { + return _formatter.formatStatement(source); + } catch (_) { + return source.replaceAll(' ', ' ').replaceAll('\n', '').trim(); + } +} + +/// Encodes [spec] as Dart source code. +String _dart(Spec spec) => + _dartfmt(spec.accept(const DartEmitter()).toString()); + +/// Returns a matcher for Dart source code. +Matcher equalsDart(String source) => new _EqualsDart(_dartfmt(source)); + +class _EqualsDart extends Matcher { + final String _source; + + const _EqualsDart(this._source); + + @override + Description describe(Description description) => description.add(_source); + + @override + Description describeMismatch( + covariant Spec item, + Description mismatchDescription, + _, + __, + ) => + mismatchDescription.add(_dart(item)); + + @override + bool matches(covariant Spec item, _) => _dart(item) == _source; +} diff --git a/pkgs/code_builder/lib/src/mixins/annotations.dart b/pkgs/code_builder/lib/src/mixins/annotations.dart new file mode 100644 index 000000000..05d41fe67 --- /dev/null +++ b/pkgs/code_builder/lib/src/mixins/annotations.dart @@ -0,0 +1,15 @@ +// 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:built_collection/built_collection.dart'; + +import '../specs/annotation.dart'; + +abstract class HasAnnotations { + BuiltList get annotations; +} + +abstract class HasAnnotationsBuilder { + ListBuilder annotations; +} diff --git a/pkgs/code_builder/lib/src/mixins/dartdoc.dart b/pkgs/code_builder/lib/src/mixins/dartdoc.dart new file mode 100644 index 000000000..ae44bd17a --- /dev/null +++ b/pkgs/code_builder/lib/src/mixins/dartdoc.dart @@ -0,0 +1,15 @@ +// 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:built_collection/built_collection.dart'; + +abstract class HasDartDocs { + /// Dart docs. + BuiltList get docs; +} + +abstract class HasDartDocsBuilder { + /// Dart docs. + ListBuilder docs; +} diff --git a/pkgs/code_builder/lib/src/mixins/generics.dart b/pkgs/code_builder/lib/src/mixins/generics.dart new file mode 100644 index 000000000..aff26e1c9 --- /dev/null +++ b/pkgs/code_builder/lib/src/mixins/generics.dart @@ -0,0 +1,17 @@ +// 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:built_collection/built_collection.dart'; + +import '../specs/type_reference.dart'; + +abstract class HasGenerics { + /// Generic type parameters. + BuiltList get types; +} + +abstract class HasGenericsBuilder { + /// Generic type parameters. + ListBuilder types; +} diff --git a/pkgs/code_builder/lib/src/pretty_printer.dart b/pkgs/code_builder/lib/src/pretty_printer.dart deleted file mode 100644 index 5aef4dc04..000000000 --- a/pkgs/code_builder/lib/src/pretty_printer.dart +++ /dev/null @@ -1,122 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/token.dart'; -import 'package:dart_style/dart_style.dart'; - -import 'analyzer_patch.dart'; - -final _dartFmt = new DartFormatter(); - -/// Returns [source] formatted by `dartfmt`. -String dartfmt(String source) { - try { - return _dartFmt.format(source); - } on FormatterException catch (_) { - return _dartFmt.formatStatement(source); - } -} - -/// Augments [AstNode.toSource] by adding some whitespace/line breaks. -/// -/// The final result is run through `dartfmt`. -/// -/// This is the _recommended_ output (but not required) when comparing ASTs -/// to expected golden files/text blobs. -String prettyToSource(AstNode astNode) { - var buffer = new PrintBuffer(); - var visitor = new _PrettyToSourceVisitor(buffer); - astNode.accept(visitor); - var source = buffer.toString(); - try { - return dartfmt(source); - } on FormatterException catch (_) { - return source; - } -} - -// https://github.com/dart-lang/code_builder/issues/16 -class _PrettyToSourceVisitor extends ToSourceVisitor { - final StringBuffer _buffer; - - _PrettyToSourceVisitor(PrintBuffer buffer) - : _buffer = buffer, - super(buffer); - - @override - Object visitClassDeclaration(ClassDeclaration node) { - _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " "); - _visitTokenWithSuffix(node.abstractKeyword, " "); - _buffer.write("class "); - _visitNode(node.name); - _visitNode(node.typeParameters); - _visitNodeWithPrefix(" ", node.extendsClause); - _visitNodeWithPrefix(" ", node.withClause); - _visitNodeWithPrefix(" ", node.implementsClause); - _buffer.write(" {"); - _visitNodeListWithSeparator(node.members, "\n\n"); - _buffer.write("}"); - return null; - } - - // Safely visit the given [node]. - void _visitNode(AstNode node) { - if (node != null) { - node.accept(this); - } - } - - // Write a list of [nodes], separated by the given [separator]. - void _visitNodeListWithSeparator(NodeList nodes, String separator) { - if (nodes != null) { - int size = nodes.length; - for (int i = 0; i < size; i++) { - if (i > 0) { - _buffer.write(separator); - } - nodes[i].accept(this); - } - } - } - - // Write a list of [nodes], separated by the given [separator], followed by - // the given [suffix] if the list is not empty. - void _visitNodeListWithSeparatorAndSuffix( - NodeList nodes, - String separator, - String suffix, - ) { - if (nodes != null) { - int size = nodes.length; - if (size > 0) { - for (int i = 0; i < size; i++) { - if (i > 0) { - _buffer.write(separator); - } - nodes[i].accept(this); - } - _buffer.write(suffix); - } - } - } - - // Safely visit the given [node], writing the [prefix] before the node if it - // is non-`null`. - void _visitNodeWithPrefix(String prefix, AstNode node) { - if (node != null) { - _buffer.write(prefix); - node.accept(this); - } - } - - // Safely visit the given [token], writing the [suffix] after the token if it - // is non-`null`. - void _visitTokenWithSuffix(Token token, String suffix) { - if (token != null) { - _buffer.write(token.lexeme); - _buffer.write(suffix); - } - } -} diff --git a/pkgs/code_builder/lib/src/scope.dart b/pkgs/code_builder/lib/src/scope.dart deleted file mode 100644 index d1edcf181..000000000 --- a/pkgs/code_builder/lib/src/scope.dart +++ /dev/null @@ -1,117 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:analyzer/dart/ast/standard_ast_factory.dart'; - -import 'builders/file.dart'; -import 'tokens.dart'; - -/// Returns an identifier for [name], using [scope] to enforce prefixing. -/// -/// It is _required_ within `code_builder` to use this API instead of creating -/// identifeirs manually in places where an obvious API collision could occur -/// (i.e. imported references). -/// -/// If [scope] is null, no prefixing is applied. -/// -/// ## Example -/// // May output `hello.Hello`. -/// identifier(scope, 'Hello', 'pacakge:hello/hello.dart') -Identifier identifier(Scope scope, String name, [String importFrom]) { - return (scope ?? Scope.identity).identifier(name, importFrom); -} - -/// Maintains an imported reference scope to avoid conflicts in generated code. -/// -/// ## Example -/// void useContext(Scope scope) { -/// // May print 'i1.Foo'. -/// print(scope.identifier('Foo', 'package:foo/foo.dart')); -/// -/// // May print 'i1.Bar'. -/// print(scope.identifier('Bar', 'package:foo/foo.dart')); -/// -/// // May print 'i2.Bar'. -/// print(scope.getIdentifier('Baz', 'package:bar/bar.dart')); -/// } -abstract class Scope { - /// A no-op [Scope]. Ideal for use for tests or example cases. - /// - /// **WARNING**: Does not collect import statements. This is only really - /// advisable for use in tests but not production code. To use import - /// collection but not prefixing, see [Scope.dedupe]. - static const Scope identity = const _IdentityScope(); - - /// Create a new scoping context. - /// - /// Actual implementation of [Scope] is _not_ guaranteed, only that all - /// import prefixes will be unique in a given scope. - factory Scope() = _IncrementingScope; - - /// Create a context that just collects and de-duplicates imports. - /// - /// Prefixing is _not_ applied. - factory Scope.dedupe() => new _DeduplicatingScope(); - - /// Given a [name] and and import path, returns an [Identifier]. - Identifier identifier(String name, [String importFrom]); - - /// Return a list of import statements. - List toImports(); -} - -class _DeduplicatingScope extends _IdentityScope { - final Set _imports = new Set(); - - @override - Identifier identifier(String name, [String importFrom]) { - if (importFrom != null) { - _imports.add(importFrom); - } - return super.identifier(name); - } - - @override - List toImports() => - _imports.map((uri) => new ImportBuilder(uri)).toList(); -} - -class _IdentityScope implements Scope { - const _IdentityScope(); - - @override - Identifier identifier(String name, [_]) { - return astFactory.simpleIdentifier(stringToken(name)); - } - - @override - List toImports() => const []; -} - -class _IncrementingScope extends _IdentityScope { - final Map _imports = {}; - - int _counter = 1; - - @override - Identifier identifier(String name, [String importFrom]) { - if (importFrom == null) { - return super.identifier(name); - } - var newId = _imports.putIfAbsent(importFrom, () => _counter++); - return astFactory.prefixedIdentifier( - super.identifier('_i$newId'), - $period, - super.identifier(name), - ); - } - - @override - List toImports() { - return _imports.keys.map((uri) { - return new ImportBuilder(uri, prefix: '_i${_imports[uri]}'); - }).toList(); - } -} diff --git a/pkgs/code_builder/lib/src/specs/annotation.dart b/pkgs/code_builder/lib/src/specs/annotation.dart new file mode 100644 index 000000000..f6add9f41 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/annotation.dart @@ -0,0 +1,37 @@ +// 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. + +library code_builder.src.specs.annotation; + +import 'package:built_value/built_value.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../visitors.dart'; +import 'code.dart'; + +part 'annotation.g.dart'; + +@immutable +abstract class Annotation + implements Built, Spec { + factory Annotation([void updates(AnnotationBuilder b)]) = _$Annotation; + + Annotation._(); + + /// Part after the `@` in annotation. + Code get code; + + @override + R accept(SpecVisitor visitor) => visitor.visitAnnotation(this); +} + +abstract class AnnotationBuilder + implements Builder { + factory AnnotationBuilder() = _$AnnotationBuilder; + + AnnotationBuilder._(); + + Code code; +} diff --git a/pkgs/code_builder/lib/src/specs/annotation.g.dart b/pkgs/code_builder/lib/src/specs/annotation.g.dart new file mode 100644 index 000000000..13d3b4106 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/annotation.g.dart @@ -0,0 +1,89 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.annotation; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// Target: abstract class Annotation +// ************************************************************************** + +class _$Annotation extends Annotation { + @override + final Code code; + + factory _$Annotation([void updates(AnnotationBuilder b)]) => + (new AnnotationBuilder()..update(updates)).build() as _$Annotation; + + _$Annotation._({this.code}) : super._() { + if (code == null) throw new ArgumentError.notNull('code'); + } + + @override + Annotation rebuild(void updates(AnnotationBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$AnnotationBuilder toBuilder() => new _$AnnotationBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! Annotation) return false; + return code == other.code; + } + + @override + int get hashCode { + return $jf($jc(0, code.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Annotation')..add('code', code)) + .toString(); + } +} + +class _$AnnotationBuilder extends AnnotationBuilder { + _$Annotation _$v; + + @override + Code get code { + _$this; + return super.code; + } + + @override + set code(Code code) { + _$this; + super.code = code; + } + + _$AnnotationBuilder() : super._(); + + AnnotationBuilder get _$this { + if (_$v != null) { + super.code = _$v.code; + _$v = null; + } + return this; + } + + @override + void replace(Annotation other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$Annotation; + } + + @override + void update(void updates(AnnotationBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$Annotation build() { + final result = _$v ?? new _$Annotation._(code: code); + replace(result); + return result; + } +} diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart new file mode 100644 index 000000000..567d235c5 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -0,0 +1,122 @@ +// 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. + +library code_builder.src.specs.class_; + +import 'package:built_value/built_value.dart'; +import 'package:built_collection/built_collection.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../mixins/annotations.dart'; +import '../mixins/dartdoc.dart'; +import '../mixins/generics.dart'; +import '../visitors.dart'; +import 'annotation.dart'; +import 'constructor.dart'; +import 'field.dart'; +import 'method.dart'; +import 'type_reference.dart'; + +part 'class.g.dart'; + +@immutable +abstract class Class extends Object + with HasAnnotations, HasDartDocs, HasGenerics + implements Built, TypeReference, Spec { + factory Class([void updates(ClassBuilder b)]) = _$Class; + + Class._(); + + /// Whether the class is `abstract`. + bool get abstract; + + @override + BuiltList get annotations; + + @override + BuiltList get docs; + + @nullable + TypeReference get extend; + + BuiltList get implements; + + BuiltList get mixins; + + @override + BuiltList get types; + + BuiltList get constructors; + BuiltList get methods; + BuiltList get fields; + + /// Name of the class. + String get name; + + @override + TypeReference get bound => null; + + @override + String get url => null; + + @override + String get symbol => name; + + @override + R accept(SpecVisitor visitor) => visitor.visitClass(this); + + @override + TypeReference toType() => this; +} + +abstract class ClassBuilder extends Object + with HasAnnotationsBuilder, HasDartDocsBuilder, HasGenericsBuilder + implements Builder, TypeReferenceBuilder { + factory ClassBuilder() = _$ClassBuilder; + + ClassBuilder._(); + + /// Whether the class is `abstract`. + bool abstract = false; + + @override + ListBuilder annotations = new ListBuilder(); + + @override + ListBuilder docs = new ListBuilder(); + + TypeReference extend; + + ListBuilder implements = new ListBuilder(); + ListBuilder mixins = new ListBuilder(); + + @override + ListBuilder types = new ListBuilder(); + + ListBuilder constructors = new ListBuilder(); + ListBuilder methods = new ListBuilder(); + ListBuilder fields = new ListBuilder(); + + /// Name of the class. + String name; + + @override + TypeReference get bound => null; + + @override + set bound(TypeReference bound) => throw new UnsupportedError(''); + + @override + String get url => null; + + @override + set url(String url) => throw new UnsupportedError(''); + + @override + set symbol(String symbol) => name = symbol; + + @override + String get symbol => name; +} diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart new file mode 100644 index 000000000..8a6099663 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -0,0 +1,312 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.class_; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// Target: abstract class Class +// ************************************************************************** + +class _$Class extends Class { + @override + final bool abstract; + @override + final BuiltList annotations; + @override + final BuiltList docs; + @override + final TypeReference extend; + @override + final BuiltList implements; + @override + final BuiltList mixins; + @override + final BuiltList types; + @override + final BuiltList constructors; + @override + final BuiltList methods; + @override + final BuiltList fields; + @override + final String name; + + factory _$Class([void updates(ClassBuilder b)]) => + (new ClassBuilder()..update(updates)).build() as _$Class; + + _$Class._( + {this.abstract, + this.annotations, + this.docs, + this.extend, + this.implements, + this.mixins, + this.types, + this.constructors, + this.methods, + this.fields, + this.name}) + : super._() { + if (abstract == null) throw new ArgumentError.notNull('abstract'); + if (annotations == null) throw new ArgumentError.notNull('annotations'); + if (docs == null) throw new ArgumentError.notNull('docs'); + if (implements == null) throw new ArgumentError.notNull('implements'); + if (mixins == null) throw new ArgumentError.notNull('mixins'); + if (types == null) throw new ArgumentError.notNull('types'); + if (constructors == null) throw new ArgumentError.notNull('constructors'); + if (methods == null) throw new ArgumentError.notNull('methods'); + if (fields == null) throw new ArgumentError.notNull('fields'); + if (name == null) throw new ArgumentError.notNull('name'); + } + + @override + Class rebuild(void updates(ClassBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$ClassBuilder toBuilder() => new _$ClassBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! Class) return false; + return abstract == other.abstract && + annotations == other.annotations && + docs == other.docs && + extend == other.extend && + implements == other.implements && + mixins == other.mixins && + types == other.types && + constructors == other.constructors && + methods == other.methods && + fields == other.fields && + name == other.name; + } + + @override + int get hashCode { + return $jf($jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc($jc(0, abstract.hashCode), + annotations.hashCode), + docs.hashCode), + extend.hashCode), + implements.hashCode), + mixins.hashCode), + types.hashCode), + constructors.hashCode), + methods.hashCode), + fields.hashCode), + name.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Class') + ..add('abstract', abstract) + ..add('annotations', annotations) + ..add('docs', docs) + ..add('extend', extend) + ..add('implements', implements) + ..add('mixins', mixins) + ..add('types', types) + ..add('constructors', constructors) + ..add('methods', methods) + ..add('fields', fields) + ..add('name', name)) + .toString(); + } +} + +class _$ClassBuilder extends ClassBuilder { + _$Class _$v; + + @override + bool get abstract { + _$this; + return super.abstract; + } + + @override + set abstract(bool abstract) { + _$this; + super.abstract = abstract; + } + + @override + ListBuilder get annotations { + _$this; + return super.annotations ??= new ListBuilder(); + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs ??= new ListBuilder(); + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + @override + TypeReference get extend { + _$this; + return super.extend; + } + + @override + set extend(TypeReference extend) { + _$this; + super.extend = extend; + } + + @override + ListBuilder get implements { + _$this; + return super.implements ??= new ListBuilder(); + } + + @override + set implements(ListBuilder implements) { + _$this; + super.implements = implements; + } + + @override + ListBuilder get mixins { + _$this; + return super.mixins ??= new ListBuilder(); + } + + @override + set mixins(ListBuilder mixins) { + _$this; + super.mixins = mixins; + } + + @override + ListBuilder get types { + _$this; + return super.types ??= new ListBuilder(); + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + + @override + ListBuilder get constructors { + _$this; + return super.constructors ??= new ListBuilder(); + } + + @override + set constructors(ListBuilder constructors) { + _$this; + super.constructors = constructors; + } + + @override + ListBuilder get methods { + _$this; + return super.methods ??= new ListBuilder(); + } + + @override + set methods(ListBuilder methods) { + _$this; + super.methods = methods; + } + + @override + ListBuilder get fields { + _$this; + return super.fields ??= new ListBuilder(); + } + + @override + set fields(ListBuilder fields) { + _$this; + super.fields = fields; + } + + @override + String get name { + _$this; + return super.name; + } + + @override + set name(String name) { + _$this; + super.name = name; + } + + _$ClassBuilder() : super._(); + + ClassBuilder get _$this { + if (_$v != null) { + super.abstract = _$v.abstract; + super.annotations = _$v.annotations?.toBuilder(); + super.docs = _$v.docs?.toBuilder(); + super.extend = _$v.extend; + super.implements = _$v.implements?.toBuilder(); + super.mixins = _$v.mixins?.toBuilder(); + super.types = _$v.types?.toBuilder(); + super.constructors = _$v.constructors?.toBuilder(); + super.methods = _$v.methods?.toBuilder(); + super.fields = _$v.fields?.toBuilder(); + super.name = _$v.name; + _$v = null; + } + return this; + } + + @override + void replace(Class other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$Class; + } + + @override + void update(void updates(ClassBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$Class build() { + final result = _$v ?? + new _$Class._( + abstract: abstract, + annotations: annotations?.build(), + docs: docs?.build(), + extend: extend, + implements: implements?.build(), + mixins: mixins?.build(), + types: types?.build(), + constructors: constructors?.build(), + methods: methods?.build(), + fields: fields?.build(), + name: name); + replace(result); + return result; + } +} diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart new file mode 100644 index 000000000..00d095d1f --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -0,0 +1,41 @@ +// 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. + +library code_builder.src.specs.code; + +import 'package:built_value/built_value.dart'; +import 'package:built_collection/built_collection.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../visitors.dart'; + +part 'code.g.dart'; + +/// Returns a [Spec] to be created lazily on demand. +typedef Spec LazySpec(); + +@immutable +abstract class Code implements Built, Spec { + factory Code([void updates(CodeBuilder b)]) = _$Code; + + Code._(); + + String get code; + + BuiltMap get specs; + + @override + R accept(SpecVisitor visitor) => visitor.visitCode(this); +} + +abstract class CodeBuilder implements Builder { + factory CodeBuilder() = _$CodeBuilder; + + CodeBuilder._(); + + String code; + + MapBuilder specs = new MapBuilder(); +} diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart new file mode 100644 index 000000000..cacd4053b --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -0,0 +1,107 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.code; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// Target: abstract class Code +// ************************************************************************** + +class _$Code extends Code { + @override + final String code; + @override + final BuiltMap specs; + + factory _$Code([void updates(CodeBuilder b)]) => + (new CodeBuilder()..update(updates)).build() as _$Code; + + _$Code._({this.code, this.specs}) : super._() { + if (code == null) throw new ArgumentError.notNull('code'); + if (specs == null) throw new ArgumentError.notNull('specs'); + } + + @override + Code rebuild(void updates(CodeBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$CodeBuilder toBuilder() => new _$CodeBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! Code) return false; + return code == other.code && specs == other.specs; + } + + @override + int get hashCode { + return $jf($jc($jc(0, code.hashCode), specs.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Code') + ..add('code', code) + ..add('specs', specs)) + .toString(); + } +} + +class _$CodeBuilder extends CodeBuilder { + _$Code _$v; + + @override + String get code { + _$this; + return super.code; + } + + @override + set code(String code) { + _$this; + super.code = code; + } + + @override + MapBuilder get specs { + _$this; + return super.specs ??= new MapBuilder(); + } + + @override + set specs(MapBuilder specs) { + _$this; + super.specs = specs; + } + + _$CodeBuilder() : super._(); + + CodeBuilder get _$this { + if (_$v != null) { + super.code = _$v.code; + super.specs = _$v.specs?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(Code other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$Code; + } + + @override + void update(void updates(CodeBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$Code build() { + final result = _$v ?? new _$Code._(code: code, specs: specs?.build()); + replace(result); + return result; + } +} diff --git a/pkgs/code_builder/lib/src/specs/constructor.dart b/pkgs/code_builder/lib/src/specs/constructor.dart new file mode 100644 index 000000000..3256fd071 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/constructor.dart @@ -0,0 +1,111 @@ +// 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. + +library code_builder.src.specs.constructor; + +import 'package:built_value/built_value.dart'; +import 'package:built_collection/built_collection.dart'; +import 'package:meta/meta.dart'; + +import '../mixins/annotations.dart'; +import '../mixins/dartdoc.dart'; +import 'annotation.dart'; +import 'code.dart'; +import 'method.dart'; +import 'reference.dart'; + +part 'constructor.g.dart'; + +@immutable +abstract class Constructor extends Object + with HasAnnotations, HasDartDocs + implements Built { + factory Constructor([void updates(ConstructorBuilder b)]) = _$Constructor; + + Constructor._(); + + @override + BuiltList get annotations; + + @override + BuiltList get docs; + + /// Optional parameters. + BuiltList get optionalParameters; + + /// Required parameters. + BuiltList get requiredParameters; + + /// Constructor initializer statements. + BuiltList get initializers; + + /// Body of the method. + @nullable + Code get body; + + /// Whether the constructor should be prefixed with `external`. + bool get external; + + /// Whether the constructor should be prefixed with `const`. + bool get constant; + + /// Whether this constructor should be prefixed with `factory`. + bool get factory; + + /// Whether this constructor is a simple lambda expression. + bool get lambda; + + /// Name of the constructor - optional. + @nullable + String get name; + + /// If non-null, redirect to this constructor. + @nullable + Reference get redirect; +} + +abstract class ConstructorBuilder extends Object + with HasAnnotationsBuilder, HasDartDocsBuilder + implements Builder { + factory ConstructorBuilder() = _$ConstructorBuilder; + + ConstructorBuilder._(); + + @override + ListBuilder annotations = new ListBuilder(); + + @override + ListBuilder docs = new ListBuilder(); + + /// Optional parameters. + ListBuilder optionalParameters = new ListBuilder(); + + /// Required parameters. + ListBuilder requiredParameters = new ListBuilder(); + + /// Constructor initializer statements. + ListBuilder initializers = new ListBuilder(); + + /// Body of the constructor. + Code body; + + /// Whether the constructor should be prefixed with `const`. + bool constant = false; + + /// Whether the constructor should be prefixed with `external`. + bool external = false; + + /// Whether this constructor should be prefixed with `factory`. + bool factory = false; + + /// Whether this constructor is a simple lambda expression. + bool lambda = false; + + /// Name of the constructor - optional. + String name; + + /// If non-null, redirect to this constructor. + @nullable + Reference redirect; +} diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart new file mode 100644 index 000000000..cd72dfe51 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -0,0 +1,334 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.constructor; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// Target: abstract class Constructor +// ************************************************************************** + +class _$Constructor extends Constructor { + @override + final BuiltList annotations; + @override + final BuiltList docs; + @override + final BuiltList optionalParameters; + @override + final BuiltList requiredParameters; + @override + final BuiltList initializers; + @override + final Code body; + @override + final bool external; + @override + final bool constant; + @override + final bool factory; + @override + final bool lambda; + @override + final String name; + @override + final Reference redirect; + + factory _$Constructor([void updates(ConstructorBuilder b)]) => + (new ConstructorBuilder()..update(updates)).build() as _$Constructor; + + _$Constructor._( + {this.annotations, + this.docs, + this.optionalParameters, + this.requiredParameters, + this.initializers, + this.body, + this.external, + this.constant, + this.factory, + this.lambda, + this.name, + this.redirect}) + : super._() { + if (annotations == null) throw new ArgumentError.notNull('annotations'); + if (docs == null) throw new ArgumentError.notNull('docs'); + if (optionalParameters == null) + throw new ArgumentError.notNull('optionalParameters'); + if (requiredParameters == null) + throw new ArgumentError.notNull('requiredParameters'); + if (initializers == null) throw new ArgumentError.notNull('initializers'); + if (external == null) throw new ArgumentError.notNull('external'); + if (constant == null) throw new ArgumentError.notNull('constant'); + if (factory == null) throw new ArgumentError.notNull('factory'); + if (lambda == null) throw new ArgumentError.notNull('lambda'); + } + + @override + Constructor rebuild(void updates(ConstructorBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$ConstructorBuilder toBuilder() => new _$ConstructorBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! Constructor) return false; + return annotations == other.annotations && + docs == other.docs && + optionalParameters == other.optionalParameters && + requiredParameters == other.requiredParameters && + initializers == other.initializers && + body == other.body && + external == other.external && + constant == other.constant && + factory == other.factory && + lambda == other.lambda && + name == other.name && + redirect == other.redirect; + } + + @override + int get hashCode { + return $jf($jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc($jc(0, annotations.hashCode), + docs.hashCode), + optionalParameters.hashCode), + requiredParameters.hashCode), + initializers.hashCode), + body.hashCode), + external.hashCode), + constant.hashCode), + factory.hashCode), + lambda.hashCode), + name.hashCode), + redirect.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Constructor') + ..add('annotations', annotations) + ..add('docs', docs) + ..add('optionalParameters', optionalParameters) + ..add('requiredParameters', requiredParameters) + ..add('initializers', initializers) + ..add('body', body) + ..add('external', external) + ..add('constant', constant) + ..add('factory', factory) + ..add('lambda', lambda) + ..add('name', name) + ..add('redirect', redirect)) + .toString(); + } +} + +class _$ConstructorBuilder extends ConstructorBuilder { + _$Constructor _$v; + + @override + ListBuilder get annotations { + _$this; + return super.annotations ??= new ListBuilder(); + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs ??= new ListBuilder(); + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + @override + ListBuilder get optionalParameters { + _$this; + return super.optionalParameters ??= new ListBuilder(); + } + + @override + set optionalParameters(ListBuilder optionalParameters) { + _$this; + super.optionalParameters = optionalParameters; + } + + @override + ListBuilder get requiredParameters { + _$this; + return super.requiredParameters ??= new ListBuilder(); + } + + @override + set requiredParameters(ListBuilder requiredParameters) { + _$this; + super.requiredParameters = requiredParameters; + } + + @override + ListBuilder get initializers { + _$this; + return super.initializers ??= new ListBuilder(); + } + + @override + set initializers(ListBuilder initializers) { + _$this; + super.initializers = initializers; + } + + @override + Code get body { + _$this; + return super.body; + } + + @override + set body(Code body) { + _$this; + super.body = body; + } + + @override + bool get external { + _$this; + return super.external; + } + + @override + set external(bool external) { + _$this; + super.external = external; + } + + @override + bool get constant { + _$this; + return super.constant; + } + + @override + set constant(bool constant) { + _$this; + super.constant = constant; + } + + @override + bool get factory { + _$this; + return super.factory; + } + + @override + set factory(bool factory) { + _$this; + super.factory = factory; + } + + @override + bool get lambda { + _$this; + return super.lambda; + } + + @override + set lambda(bool lambda) { + _$this; + super.lambda = lambda; + } + + @override + String get name { + _$this; + return super.name; + } + + @override + set name(String name) { + _$this; + super.name = name; + } + + @override + Reference get redirect { + _$this; + return super.redirect; + } + + @override + set redirect(Reference redirect) { + _$this; + super.redirect = redirect; + } + + _$ConstructorBuilder() : super._(); + + ConstructorBuilder get _$this { + if (_$v != null) { + super.annotations = _$v.annotations?.toBuilder(); + super.docs = _$v.docs?.toBuilder(); + super.optionalParameters = _$v.optionalParameters?.toBuilder(); + super.requiredParameters = _$v.requiredParameters?.toBuilder(); + super.initializers = _$v.initializers?.toBuilder(); + super.body = _$v.body; + super.external = _$v.external; + super.constant = _$v.constant; + super.factory = _$v.factory; + super.lambda = _$v.lambda; + super.name = _$v.name; + super.redirect = _$v.redirect; + _$v = null; + } + return this; + } + + @override + void replace(Constructor other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$Constructor; + } + + @override + void update(void updates(ConstructorBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$Constructor build() { + final result = _$v ?? + new _$Constructor._( + annotations: annotations?.build(), + docs: docs?.build(), + optionalParameters: optionalParameters?.build(), + requiredParameters: requiredParameters?.build(), + initializers: initializers?.build(), + body: body, + external: external, + constant: constant, + factory: factory, + lambda: lambda, + name: name, + redirect: redirect); + replace(result); + return result; + } +} diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart new file mode 100644 index 000000000..30ce0f4d9 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -0,0 +1,99 @@ +// 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. + +library code_builder.src.specs.field; + +import 'package:built_value/built_value.dart'; +import 'package:built_collection/built_collection.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../mixins/annotations.dart'; +import '../mixins/dartdoc.dart'; +import '../visitors.dart'; +import 'annotation.dart'; +import 'code.dart'; +import 'reference.dart'; +import 'type_reference.dart'; + +part 'field.g.dart'; + +@immutable +abstract class Field extends Object + with HasAnnotations, HasDartDocs + implements Built, Reference, Spec { + factory Field([void updates(FieldBuilder b)]) = _$Field; + + Field._(); + + @override + BuiltList get annotations; + + @override + BuiltList get docs; + + /// Field assignment, if any. + @nullable + Code get assignment; + + /// Whether this field should be prefixed with `static`. + /// + /// This is only valid within classes. + bool get static; + + /// Name of the field. + String get name; + + @nullable + TypeReference get type; + + FieldModifier get modifier; + + @override + String get symbol => name; + + @override + String get url => null; + + @override + R accept(SpecVisitor visitor) => visitor.visitField(this); + + @override + TypeReference toType() => throw new UnsupportedError(''); +} + +enum FieldModifier { + var$, + final$, + constant, +} + +abstract class FieldBuilder extends Object + with HasAnnotationsBuilder, HasDartDocsBuilder + implements Builder { + factory FieldBuilder() = _$FieldBuilder; + + FieldBuilder._(); + + @override + ListBuilder annotations = new ListBuilder(); + + @override + ListBuilder docs = new ListBuilder(); + + /// Field assignment, if any. + Code assignment; + + /// Whether this field should be prefixed with `static`. + /// + /// This is only valid within classes. + bool static = false; + + /// Name of the field. + String name; + + TypeReference type; + + FieldModifier modifier = FieldModifier.var$; +} diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart new file mode 100644 index 000000000..355746bd2 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -0,0 +1,221 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.field; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// Target: abstract class Field +// ************************************************************************** + +class _$Field extends Field { + @override + final BuiltList annotations; + @override + final BuiltList docs; + @override + final Code assignment; + @override + final bool static; + @override + final String name; + @override + final TypeReference type; + @override + final FieldModifier modifier; + + factory _$Field([void updates(FieldBuilder b)]) => + (new FieldBuilder()..update(updates)).build() as _$Field; + + _$Field._( + {this.annotations, + this.docs, + this.assignment, + this.static, + this.name, + this.type, + this.modifier}) + : super._() { + if (annotations == null) throw new ArgumentError.notNull('annotations'); + if (docs == null) throw new ArgumentError.notNull('docs'); + if (static == null) throw new ArgumentError.notNull('static'); + if (name == null) throw new ArgumentError.notNull('name'); + if (modifier == null) throw new ArgumentError.notNull('modifier'); + } + + @override + Field rebuild(void updates(FieldBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$FieldBuilder toBuilder() => new _$FieldBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! Field) return false; + return annotations == other.annotations && + docs == other.docs && + assignment == other.assignment && + static == other.static && + name == other.name && + type == other.type && + modifier == other.modifier; + } + + @override + int get hashCode { + return $jf($jc( + $jc( + $jc( + $jc( + $jc($jc($jc(0, annotations.hashCode), docs.hashCode), + assignment.hashCode), + static.hashCode), + name.hashCode), + type.hashCode), + modifier.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Field') + ..add('annotations', annotations) + ..add('docs', docs) + ..add('assignment', assignment) + ..add('static', static) + ..add('name', name) + ..add('type', type) + ..add('modifier', modifier)) + .toString(); + } +} + +class _$FieldBuilder extends FieldBuilder { + _$Field _$v; + + @override + ListBuilder get annotations { + _$this; + return super.annotations ??= new ListBuilder(); + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs ??= new ListBuilder(); + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + @override + Code get assignment { + _$this; + return super.assignment; + } + + @override + set assignment(Code assignment) { + _$this; + super.assignment = assignment; + } + + @override + bool get static { + _$this; + return super.static; + } + + @override + set static(bool static) { + _$this; + super.static = static; + } + + @override + String get name { + _$this; + return super.name; + } + + @override + set name(String name) { + _$this; + super.name = name; + } + + @override + TypeReference get type { + _$this; + return super.type; + } + + @override + set type(TypeReference type) { + _$this; + super.type = type; + } + + @override + FieldModifier get modifier { + _$this; + return super.modifier; + } + + @override + set modifier(FieldModifier modifier) { + _$this; + super.modifier = modifier; + } + + _$FieldBuilder() : super._(); + + FieldBuilder get _$this { + if (_$v != null) { + super.annotations = _$v.annotations?.toBuilder(); + super.docs = _$v.docs?.toBuilder(); + super.assignment = _$v.assignment; + super.static = _$v.static; + super.name = _$v.name; + super.type = _$v.type; + super.modifier = _$v.modifier; + _$v = null; + } + return this; + } + + @override + void replace(Field other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$Field; + } + + @override + void update(void updates(FieldBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$Field build() { + final result = _$v ?? + new _$Field._( + annotations: annotations?.build(), + docs: docs?.build(), + assignment: assignment, + static: static, + name: name, + type: type, + modifier: modifier); + replace(result); + return result; + } +} diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart new file mode 100644 index 000000000..40455ac04 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -0,0 +1,202 @@ +// 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. + +library code_builder.src.specs.method; + +import 'package:built_value/built_value.dart'; +import 'package:built_collection/built_collection.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../mixins/annotations.dart'; +import '../mixins/dartdoc.dart'; +import '../mixins/generics.dart'; +import '../visitors.dart'; +import 'annotation.dart'; +import 'code.dart'; +import 'reference.dart'; +import 'type_reference.dart'; + +part 'method.g.dart'; + +@immutable +abstract class Method extends Object + with HasAnnotations, HasGenerics, HasDartDocs + implements Built, Reference, Spec { + factory Method([void updates(MethodBuilder b)]) = _$Method; + + Method._(); + + @override + BuiltList get annotations; + + @override + BuiltList get docs; + + @override + BuiltList get types; + + /// Optional parameters. + BuiltList get optionalParameters; + + /// Required parameters. + BuiltList get requiredParameters; + + /// Body of the method. + @nullable + Code get body; + + /// Whether the method should be prefixed with `external`. + bool get external; + + /// Whether this method is a simple lambda expression. + bool get lambda; + + /// Whether this method should be prefixed with `static`. + /// + /// This is only valid within classes. + bool get static; + + /// Name of the method or function. + String get name; + + /// Whether this is a getter or setter. + @nullable + MethodType get type; + + @nullable + TypeReference get returns; + + @override + String get symbol => name; + + @override + String get url => null; + + @override + R accept(SpecVisitor visitor) => visitor.visitMethod(this); + + @override + TypeReference toType() => throw new UnsupportedError(''); +} + +abstract class MethodBuilder extends Object + with HasAnnotationsBuilder, HasGenericsBuilder, HasDartDocsBuilder + implements Builder { + factory MethodBuilder() = _$MethodBuilder; + + MethodBuilder._(); + + @override + ListBuilder annotations = new ListBuilder(); + + @override + ListBuilder docs = new ListBuilder(); + + @override + ListBuilder types = new ListBuilder(); + + /// Optional parameters. + ListBuilder optionalParameters = new ListBuilder(); + + /// Required parameters. + ListBuilder requiredParameters = new ListBuilder(); + + /// Body of the method. + Code body; + + /// Whether the method should be prefixed with `external`. + bool external = false; + + /// Whether this method is a simple lambda expression. + bool lambda = false; + + /// Whether this method should be prefixed with `static`. + /// + /// This is only valid within classes. + bool static = false; + + /// Name of the method or function. + String name; + + /// Whether this is a getter or setter. + MethodType type; + + TypeReference returns; +} + +enum MethodType { + getter, + setter, +} + +abstract class Parameter extends Object + with HasAnnotations, HasGenerics, HasDartDocs + implements Built { + factory Parameter([void updates(ParameterBuilder b)]) = _$Parameter; + + Parameter._(); + + /// If not `null`, a default assignment if the parameter is optional. + @nullable + Code get defaultTo; + + /// Name of the parameter. + String get name; + + /// Whether this parameter should be named, if optional. + bool get named; + + /// Whether this parameter should be field formal (i.e. `this.`). + /// + /// This is only valid on constructors; + bool get toThis; + + @override + BuiltList get annotations; + + @override + BuiltList get docs; + + @override + BuiltList get types; + + /// Type of the parameter; + @nullable + TypeReference get type; +} + +abstract class ParameterBuilder extends Object + with HasAnnotationsBuilder, HasGenericsBuilder, HasDartDocsBuilder + implements Builder { + factory ParameterBuilder() = _$ParameterBuilder; + + ParameterBuilder._(); + + /// If not `null`, a default assignment if the parameter is optional. + Code defaultTo; + + /// Name of the parameter. + String name; + + /// Whether this parameter should be named, if optional. + bool named = false; + + /// Whether this parameter should be field formal (i.e. `this.`). + /// + /// This is only valid on constructors; + bool toThis = false; + + @override + ListBuilder annotations = new ListBuilder(); + + @override + ListBuilder docs = new ListBuilder(); + + @override + ListBuilder types = new ListBuilder(); + + /// Type of the parameter; + TypeReference type; +} diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart new file mode 100644 index 000000000..a4262740d --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -0,0 +1,574 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.method; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// Target: abstract class Method +// ************************************************************************** + +class _$Method extends Method { + @override + final BuiltList annotations; + @override + final BuiltList docs; + @override + final BuiltList types; + @override + final BuiltList optionalParameters; + @override + final BuiltList requiredParameters; + @override + final Code body; + @override + final bool external; + @override + final bool lambda; + @override + final bool static; + @override + final String name; + @override + final MethodType type; + @override + final TypeReference returns; + + factory _$Method([void updates(MethodBuilder b)]) => + (new MethodBuilder()..update(updates)).build() as _$Method; + + _$Method._( + {this.annotations, + this.docs, + this.types, + this.optionalParameters, + this.requiredParameters, + this.body, + this.external, + this.lambda, + this.static, + this.name, + this.type, + this.returns}) + : super._() { + if (annotations == null) throw new ArgumentError.notNull('annotations'); + if (docs == null) throw new ArgumentError.notNull('docs'); + if (types == null) throw new ArgumentError.notNull('types'); + if (optionalParameters == null) + throw new ArgumentError.notNull('optionalParameters'); + if (requiredParameters == null) + throw new ArgumentError.notNull('requiredParameters'); + if (external == null) throw new ArgumentError.notNull('external'); + if (lambda == null) throw new ArgumentError.notNull('lambda'); + if (static == null) throw new ArgumentError.notNull('static'); + if (name == null) throw new ArgumentError.notNull('name'); + } + + @override + Method rebuild(void updates(MethodBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$MethodBuilder toBuilder() => new _$MethodBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! Method) return false; + return annotations == other.annotations && + docs == other.docs && + types == other.types && + optionalParameters == other.optionalParameters && + requiredParameters == other.requiredParameters && + body == other.body && + external == other.external && + lambda == other.lambda && + static == other.static && + name == other.name && + type == other.type && + returns == other.returns; + } + + @override + int get hashCode { + return $jf($jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc($jc(0, annotations.hashCode), + docs.hashCode), + types.hashCode), + optionalParameters.hashCode), + requiredParameters.hashCode), + body.hashCode), + external.hashCode), + lambda.hashCode), + static.hashCode), + name.hashCode), + type.hashCode), + returns.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Method') + ..add('annotations', annotations) + ..add('docs', docs) + ..add('types', types) + ..add('optionalParameters', optionalParameters) + ..add('requiredParameters', requiredParameters) + ..add('body', body) + ..add('external', external) + ..add('lambda', lambda) + ..add('static', static) + ..add('name', name) + ..add('type', type) + ..add('returns', returns)) + .toString(); + } +} + +class _$MethodBuilder extends MethodBuilder { + _$Method _$v; + + @override + ListBuilder get annotations { + _$this; + return super.annotations ??= new ListBuilder(); + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs ??= new ListBuilder(); + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + @override + ListBuilder get types { + _$this; + return super.types ??= new ListBuilder(); + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + + @override + ListBuilder get optionalParameters { + _$this; + return super.optionalParameters ??= new ListBuilder(); + } + + @override + set optionalParameters(ListBuilder optionalParameters) { + _$this; + super.optionalParameters = optionalParameters; + } + + @override + ListBuilder get requiredParameters { + _$this; + return super.requiredParameters ??= new ListBuilder(); + } + + @override + set requiredParameters(ListBuilder requiredParameters) { + _$this; + super.requiredParameters = requiredParameters; + } + + @override + Code get body { + _$this; + return super.body; + } + + @override + set body(Code body) { + _$this; + super.body = body; + } + + @override + bool get external { + _$this; + return super.external; + } + + @override + set external(bool external) { + _$this; + super.external = external; + } + + @override + bool get lambda { + _$this; + return super.lambda; + } + + @override + set lambda(bool lambda) { + _$this; + super.lambda = lambda; + } + + @override + bool get static { + _$this; + return super.static; + } + + @override + set static(bool static) { + _$this; + super.static = static; + } + + @override + String get name { + _$this; + return super.name; + } + + @override + set name(String name) { + _$this; + super.name = name; + } + + @override + MethodType get type { + _$this; + return super.type; + } + + @override + set type(MethodType type) { + _$this; + super.type = type; + } + + @override + TypeReference get returns { + _$this; + return super.returns; + } + + @override + set returns(TypeReference returns) { + _$this; + super.returns = returns; + } + + _$MethodBuilder() : super._(); + + MethodBuilder get _$this { + if (_$v != null) { + super.annotations = _$v.annotations?.toBuilder(); + super.docs = _$v.docs?.toBuilder(); + super.types = _$v.types?.toBuilder(); + super.optionalParameters = _$v.optionalParameters?.toBuilder(); + super.requiredParameters = _$v.requiredParameters?.toBuilder(); + super.body = _$v.body; + super.external = _$v.external; + super.lambda = _$v.lambda; + super.static = _$v.static; + super.name = _$v.name; + super.type = _$v.type; + super.returns = _$v.returns; + _$v = null; + } + return this; + } + + @override + void replace(Method other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$Method; + } + + @override + void update(void updates(MethodBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$Method build() { + final result = _$v ?? + new _$Method._( + annotations: annotations?.build(), + docs: docs?.build(), + types: types?.build(), + optionalParameters: optionalParameters?.build(), + requiredParameters: requiredParameters?.build(), + body: body, + external: external, + lambda: lambda, + static: static, + name: name, + type: type, + returns: returns); + replace(result); + return result; + } +} + +// ************************************************************************** +// Generator: BuiltValueGenerator +// Target: abstract class Parameter +// ************************************************************************** + +class _$Parameter extends Parameter { + @override + final Code defaultTo; + @override + final String name; + @override + final bool named; + @override + final bool toThis; + @override + final BuiltList annotations; + @override + final BuiltList docs; + @override + final BuiltList types; + @override + final TypeReference type; + + factory _$Parameter([void updates(ParameterBuilder b)]) => + (new ParameterBuilder()..update(updates)).build() as _$Parameter; + + _$Parameter._( + {this.defaultTo, + this.name, + this.named, + this.toThis, + this.annotations, + this.docs, + this.types, + this.type}) + : super._() { + if (name == null) throw new ArgumentError.notNull('name'); + if (named == null) throw new ArgumentError.notNull('named'); + if (toThis == null) throw new ArgumentError.notNull('toThis'); + if (annotations == null) throw new ArgumentError.notNull('annotations'); + if (docs == null) throw new ArgumentError.notNull('docs'); + if (types == null) throw new ArgumentError.notNull('types'); + } + + @override + Parameter rebuild(void updates(ParameterBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$ParameterBuilder toBuilder() => new _$ParameterBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! Parameter) return false; + return defaultTo == other.defaultTo && + name == other.name && + named == other.named && + toThis == other.toThis && + annotations == other.annotations && + docs == other.docs && + types == other.types && + type == other.type; + } + + @override + int get hashCode { + return $jf($jc( + $jc( + $jc( + $jc( + $jc( + $jc($jc($jc(0, defaultTo.hashCode), name.hashCode), + named.hashCode), + toThis.hashCode), + annotations.hashCode), + docs.hashCode), + types.hashCode), + type.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Parameter') + ..add('defaultTo', defaultTo) + ..add('name', name) + ..add('named', named) + ..add('toThis', toThis) + ..add('annotations', annotations) + ..add('docs', docs) + ..add('types', types) + ..add('type', type)) + .toString(); + } +} + +class _$ParameterBuilder extends ParameterBuilder { + _$Parameter _$v; + + @override + Code get defaultTo { + _$this; + return super.defaultTo; + } + + @override + set defaultTo(Code defaultTo) { + _$this; + super.defaultTo = defaultTo; + } + + @override + String get name { + _$this; + return super.name; + } + + @override + set name(String name) { + _$this; + super.name = name; + } + + @override + bool get named { + _$this; + return super.named; + } + + @override + set named(bool named) { + _$this; + super.named = named; + } + + @override + bool get toThis { + _$this; + return super.toThis; + } + + @override + set toThis(bool toThis) { + _$this; + super.toThis = toThis; + } + + @override + ListBuilder get annotations { + _$this; + return super.annotations ??= new ListBuilder(); + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs ??= new ListBuilder(); + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + @override + ListBuilder get types { + _$this; + return super.types ??= new ListBuilder(); + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + + @override + TypeReference get type { + _$this; + return super.type; + } + + @override + set type(TypeReference type) { + _$this; + super.type = type; + } + + _$ParameterBuilder() : super._(); + + ParameterBuilder get _$this { + if (_$v != null) { + super.defaultTo = _$v.defaultTo; + super.name = _$v.name; + super.named = _$v.named; + super.toThis = _$v.toThis; + super.annotations = _$v.annotations?.toBuilder(); + super.docs = _$v.docs?.toBuilder(); + super.types = _$v.types?.toBuilder(); + super.type = _$v.type; + _$v = null; + } + return this; + } + + @override + void replace(Parameter other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$Parameter; + } + + @override + void update(void updates(ParameterBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$Parameter build() { + final result = _$v ?? + new _$Parameter._( + defaultTo: defaultTo, + name: name, + named: named, + toThis: toThis, + annotations: annotations?.build(), + docs: docs?.build(), + types: types?.build(), + type: type); + replace(result); + return result; + } +} diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart new file mode 100644 index 000000000..ced2f1428 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -0,0 +1,54 @@ +// 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. + +library code_builder.src.specs.reference; + +import 'package:built_value/built_value.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../visitors.dart'; +import 'type_reference.dart'; + +/// A reference to [symbol], such as a class, or top-level method or field. +/// +/// References can be collected and collated in order to automatically generate +/// `import` statements for all used symbols. +@immutable +class Reference implements Spec { + /// Relative, `package:` or `dart:` URL of the library. + /// + /// May be omitted (`null`) in order to express "same library". + final String url; + + /// Name of the class, method, or field. + final String symbol; + + /// Create a reference to [symbol] in [url]. + const Reference(this.symbol, this.url); + + /// Create a reference to [symbol] in the same library (no import statement). + const Reference.localScope(this.symbol) : url = null; + + @override + R accept(SpecVisitor visitor) => visitor.visitReference(this); + + @override + int get hashCode => '$url#$symbol'.hashCode; + + @override + bool operator ==(Object o) => + o is Reference && o.url == url && o.symbol == symbol; + + @override + String toString() => (newBuiltValueToStringHelper('Reference') + ..add('url', url) + ..add('symbol', symbol)) + .toString(); + + /// Returns as a [TypeReference], which allows adding generic type parameters. + TypeReference toType() => new TypeReference((b) => b + ..url = url + ..symbol = symbol); +} diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart new file mode 100644 index 000000000..855011b82 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -0,0 +1,65 @@ +// 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. + +library code_builder.src.specs.type_reference; + +import 'package:built_value/built_value.dart'; +import 'package:built_collection/built_collection.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../mixins/generics.dart'; +import '../visitors.dart'; +import 'reference.dart'; + +part 'type_reference.g.dart'; + +@immutable +abstract class TypeReference extends Object + with HasGenerics + implements Built, Reference, Spec { + factory TypeReference([ + void updates(TypeReferenceBuilder b), + ]) = _$TypeReference; + + TypeReference._(); + + @override + String get symbol; + + @override + @nullable + String get url; + + /// Optional bound generic. + @nullable + TypeReference get bound; + + @override + BuiltList get types; + + @override + R accept(SpecVisitor visitor) => visitor.visitType(this); + + @override + TypeReference toType() => this; +} + +abstract class TypeReferenceBuilder extends Object + with HasGenericsBuilder + implements Builder { + factory TypeReferenceBuilder() = _$TypeReferenceBuilder; + + TypeReferenceBuilder._(); + + String symbol; + + String url; + + /// Optional bound generic. + TypeReference bound; + + @override + ListBuilder types = new ListBuilder(); +} diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart new file mode 100644 index 000000000..c6bee1677 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -0,0 +1,148 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.type_reference; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// Target: abstract class TypeReference +// ************************************************************************** + +class _$TypeReference extends TypeReference { + @override + final String symbol; + @override + final String url; + @override + final TypeReference bound; + @override + final BuiltList types; + + factory _$TypeReference([void updates(TypeReferenceBuilder b)]) => + (new TypeReferenceBuilder()..update(updates)).build() as _$TypeReference; + + _$TypeReference._({this.symbol, this.url, this.bound, this.types}) + : super._() { + if (symbol == null) throw new ArgumentError.notNull('symbol'); + if (types == null) throw new ArgumentError.notNull('types'); + } + + @override + TypeReference rebuild(void updates(TypeReferenceBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$TypeReferenceBuilder toBuilder() => + new _$TypeReferenceBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! TypeReference) return false; + return symbol == other.symbol && + url == other.url && + bound == other.bound && + types == other.types; + } + + @override + int get hashCode { + return $jf($jc( + $jc($jc($jc(0, symbol.hashCode), url.hashCode), bound.hashCode), + types.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('TypeReference') + ..add('symbol', symbol) + ..add('url', url) + ..add('bound', bound) + ..add('types', types)) + .toString(); + } +} + +class _$TypeReferenceBuilder extends TypeReferenceBuilder { + _$TypeReference _$v; + + @override + String get symbol { + _$this; + return super.symbol; + } + + @override + set symbol(String symbol) { + _$this; + super.symbol = symbol; + } + + @override + String get url { + _$this; + return super.url; + } + + @override + set url(String url) { + _$this; + super.url = url; + } + + @override + TypeReference get bound { + _$this; + return super.bound; + } + + @override + set bound(TypeReference bound) { + _$this; + super.bound = bound; + } + + @override + ListBuilder get types { + _$this; + return super.types ??= new ListBuilder(); + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + + _$TypeReferenceBuilder() : super._(); + + TypeReferenceBuilder get _$this { + if (_$v != null) { + super.symbol = _$v.symbol; + super.url = _$v.url; + super.bound = _$v.bound; + super.types = _$v.types?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(TypeReference other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$TypeReference; + } + + @override + void update(void updates(TypeReferenceBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$TypeReference build() { + final result = _$v ?? + new _$TypeReference._( + symbol: symbol, url: url, bound: bound, types: types?.build()); + replace(result); + return result; + } +} diff --git a/pkgs/code_builder/lib/src/tokens.dart b/pkgs/code_builder/lib/src/tokens.dart deleted file mode 100644 index 65a620709..000000000 --- a/pkgs/code_builder/lib/src/tokens.dart +++ /dev/null @@ -1,215 +0,0 @@ -// 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. - -import 'package:analyzer/dart/ast/token.dart'; -import 'package:analyzer/src/dart/ast/token.dart'; - -/// The `abstract` token. -final Token $abstract = new KeywordToken(Keyword.ABSTRACT, 0); - -/// The `as` token. -final Token $as = new KeywordToken(Keyword.AS, 0); - -/// The `assert` token. -final Token $assert = new KeywordToken(Keyword.ASSERT, 0); - -/// The `async` token. -final Token $async = new KeywordToken(Keyword.ASYNC, 0); - -/// The `@` token. -final Token $at = new Token(TokenType.AT, 0); - -/// The `await` token. -final Token $await = new KeywordToken(Keyword.AWAIT, 0); - -/// The `break` token. -final Token $break = new KeywordToken(Keyword.BREAK, 0); - -/// The `case` token. -final Token $case = new KeywordToken(Keyword.CASE, 0); - -/// The `class` token. -final Token $class = new KeywordToken(Keyword.CLASS, 0); - -/// The `]` token. -final Token $closeBracket = new Token(TokenType.CLOSE_SQUARE_BRACKET, 0); - -/// The '}' token. -final Token $closeCurly = new Token(TokenType.CLOSE_CURLY_BRACKET, 0); - -/// The ')' token. -final Token $closeParen = new Token(TokenType.CLOSE_PAREN, 0); - -/// The ':' token. -final Token $colon = new Token(TokenType.COLON, 0); - -/// The `const` token. -final Token $const = new KeywordToken(Keyword.CONST, 0); - -/// The `default` token. -final Token $default = new KeywordToken(Keyword.DEFAULT, 0); - -/// The `deferred` token. -final Token $deferred = new KeywordToken(Keyword.DEFERRED, 0); - -/// The `/` token. -final Token $divide = new Token(TokenType.SLASH, 0); - -/// The `do` keyword. -final Token $do = new KeywordToken(Keyword.DO, 0); - -/// The `else` token. -final Token $else = new KeywordToken(Keyword.ELSE, 0); - -/// The '=' token. -final Token $equals = new Token(TokenType.EQ, 0); - -/// The `==` token. -final Token $equalsEquals = new Token(TokenType.EQ_EQ, 0); - -/// The `extends` token. -final Token $extends = new KeywordToken(Keyword.EXTENDS, 0); - -/// The `factory` token. -final Token $factory = new KeywordToken(Keyword.FACTORY, 0); - -/// The `false` token. -final Token $false = new KeywordToken(Keyword.FALSE, 0); - -/// The `final` token. -final Token $final = new KeywordToken(Keyword.FINAL, 0); - -/// The `for` keyword. -final Token $for = new KeywordToken(Keyword.FOR, 0); - -/// The `>` token. -final Token $gt = new Token(TokenType.GT, 0); - -/// The `if` token. -final Token $if = new KeywordToken(Keyword.IF, 0); - -/// The `switch` keyword. -final Token $switch = new KeywordToken(Keyword.SWITCH, 0); - -/// The `super` keyword. -final Token $super = new KeywordToken(Keyword.SUPER, 0); - -/// The `yield` token. -final Token $yield = new KeywordToken(Keyword.YIELD, 0); - -/// The `while` keyword. -final Token $while = new KeywordToken(Keyword.WHILE, 0); - -// Simple tokens - -/// The `&&` token. -final Token $and = new Token(TokenType.AMPERSAND_AMPERSAND, 0); - -/// The `*` token. -final Token $star = $multiply; - -/// The `hide` token. -final Token $hide = new KeywordToken(Keyword.HIDE, 0); - -/// The `implements` token. -final Token $implements = new KeywordToken(Keyword.IMPLEMENTS, 0); - -/// The `in` token. -final Token $in = new KeywordToken(Keyword.IN, 0); - -/// The `is` token. -final Token $is = new KeywordToken(Keyword.IS, 0); - -/// The `library` token. -final Token $library = new KeywordToken(Keyword.LIBRARY, 0); - -/// The `<` token. -final Token $lt = new Token(TokenType.LT, 0); - -/// The `-` token. -final Token $minus = new Token(TokenType.MINUS, 0); - -/// The `--` token. -final Token $minusMinus = new Token(TokenType.MINUS_MINUS, 0); - -/// The `*` token. -final Token $multiply = new Token(TokenType.STAR, 0); - -/// The `new` token. -final Token $new = new KeywordToken(Keyword.NEW, 0); - -/// The `!` token. -final Token $not = new Token(TokenType.BANG, 0); - -/// The `!=` token. -final Token $notEquals = new Token(TokenType.BANG_EQ, 0); - -/// The `null` token. -final Token $null = new KeywordToken(Keyword.NULL, 0); - -/// The '??=' token. -final Token $nullAwareEquals = new Token(TokenType.QUESTION_QUESTION_EQ, 0); - -/// The `of` token. -final Token $of = new KeywordToken(Keyword.OF, 0); - -/// The `||` token. -final Token $or = new Token(TokenType.BAR_BAR, 0); - -/// The '[` token. -final Token $openBracket = new Token(TokenType.OPEN_SQUARE_BRACKET, 0); - -/// The '{' token. -final Token $openCurly = new Token(TokenType.OPEN_CURLY_BRACKET, 0); - -/// The '(' token. -final Token $openParen = new Token(TokenType.OPEN_PAREN, 0); - -/// The `part` token. -final Token $part = new KeywordToken(Keyword.PART, 0); - -/// The '.' token. -final Token $period = new Token(TokenType.PERIOD, 0); - -/// The `+` token. -final Token $plus = new Token(TokenType.PLUS, 0); - -/// The `++` token. -final Token $plusPlus = new Token(TokenType.PLUS_PLUS, 0); - -/// The `return` token. -final Token $return = new KeywordToken(Keyword.RETURN, 0); - -/// The ';' token. -final Token $semicolon = new Token(TokenType.SEMICOLON, 0); - -/// The `show` token. -final Token $show = new KeywordToken(Keyword.SHOW, 0); - -/// The `static` token. -final Token $static = new KeywordToken(Keyword.STATIC, 0); - -/// The `this` token. -final Token $this = new KeywordToken(Keyword.THIS, 0); - -/// The `throw` token. -final Token $throw = new KeywordToken(Keyword.THROW, 0); - -/// The `true` token. -final Token $true = new KeywordToken(Keyword.TRUE, 0); - -/// The `var` token. -final Token $var = new KeywordToken(Keyword.VAR, 0); - -/// The `with` token. -final Token $with = new KeywordToken(Keyword.WITH, 0); - -/// The `?` token. -final Token $question = new Token(TokenType.QUESTION, 0); - -/// Returns an int token for the given int [value]. -StringToken intToken(int value) => new StringToken(TokenType.INT, '$value', 0); - -/// Returns a string token for the given string [s]. -StringToken stringToken(String s) => new StringToken(TokenType.STRING, s, 0); diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart new file mode 100644 index 000000000..2af0e66be --- /dev/null +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -0,0 +1,79 @@ +// 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 'base.dart'; +import 'specs/annotation.dart'; +import 'specs/class.dart'; +import 'specs/code.dart'; +import 'specs/constructor.dart'; +import 'specs/field.dart'; +import 'specs/method.dart'; +import 'specs/reference.dart'; +import 'specs/type_reference.dart'; + +abstract class SpecVisitor { + const SpecVisitor._(); + + T visitAnnotation(Annotation spec); + + T visitClass(Class spec); + + T visitCode(Code spec); + + T visitConstructor(Constructor spec, String clazz); + + T visitField(Field spec); + + T visitMethod(Method spec); + + T visitReference(Reference spec); + + T visitSpec(Spec spec); + + T visitType(TypeReference spec); + + T visitTypeParameters(Iterable specs); +} + +class SimpleSpecVisitor implements SpecVisitor { + const SimpleSpecVisitor(); + + @override + T visitAnnotation(Annotation spec) => null; + + @override + T visitClass(Class spec) => null; + + @override + T visitConstructor(Constructor spec, String clazz) => null; + + @override + T visitCode(Code spec) => null; + + @override + T visitField(Field spec) => null; + + @override + T visitMethod(Method spec) => null; + + @override + T visitReference(Reference spec) => null; + + @override + T visitSpec(Spec spec) => spec.accept(this); + + @override + T visitType(TypeReference spec) => null; + + @override + T visitTypeParameters(Iterable specs) => null; +} + +class RecursiveSpecVisitor extends SimpleSpecVisitor { + const RecursiveSpecVisitor(); +} + +class GeneralizingSpecVisitor extends RecursiveSpecVisitor { + const GeneralizingSpecVisitor(); +} diff --git a/pkgs/code_builder/lib/testing.dart b/pkgs/code_builder/lib/testing.dart deleted file mode 100644 index ef6ae980c..000000000 --- a/pkgs/code_builder/lib/testing.dart +++ /dev/null @@ -1,100 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/src/pretty_printer.dart'; -import 'package:dart_style/dart_style.dart'; -import 'package:matcher/matcher.dart'; - -/// Returns a [Matcher] that checks an [AstBuilder] versus [source]. -/// -/// On failure, uses the default string matcher to show a detailed diff between -/// the expected and actual source code results. -/// -/// If [pretty] is set, uses another `toSource` method that adds additional -/// line breaks to make the output more readable and idiomatic. -Matcher equalsSource( - String source, { - bool pretty: false, - Scope scope: Scope.identity, -}) { - var canParse = false; - try { - source = dartfmt(source); - canParse = true; - } on FormatterException catch (_) {} - return new _EqualsSource( - scope, - source, - canParse, - pretty, - ); -} - -class _EqualsSource extends Matcher { - final Scope _scope; - final String _source; - final bool _canParse; - final bool _pretty; - - _EqualsSource(this._scope, this._source, this._canParse, this._pretty); - - @override - Description describe(Description description) { - if (_canParse) { - return equals(_source).describe(description); - } else { - return equalsIgnoringWhitespace(_source).describe(description); - } - } - - @override - Description describeMismatch( - item, - Description mismatchDescription, - Map matchState, - bool verbose, - ) { - if (item is AstBuilder) { - var origin = _formatAst(item); - if (_canParse) { - return equals(_source).describeMismatch( - origin, - mismatchDescription.addDescriptionOf(origin), - matchState, - verbose, - ); - } else { - return equalsIgnoringWhitespace(_source).describeMismatch( - origin, - mismatchDescription.addDescriptionOf(origin), - matchState, - verbose, - ); - } - } else { - return mismatchDescription.add('$item is not a CodeBuilder'); - } - } - - @override - bool matches(item, _) { - if (item is AstBuilder) { - if (_canParse) { - return equals(_formatAst(item)).matches(_source, {}); - } else { - return equalsIgnoringWhitespace(_formatAst(item)).matches(_source, {}); - } - } - return false; - } - - String _formatAst(AstBuilder builder) { - var astNode = builder.buildAst(_scope); - if (_canParse) { - return dartfmt(_pretty ? prettyToSource(astNode) : astNode.toSource()); - } - return astNode.toSource(); - } -} diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 4453fd355..afc6135ad 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 1.0.4 +version: 2.0.0-dev description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -8,11 +8,13 @@ environment: sdk: '>=1.22.0 <2.0.0' dependencies: - analyzer: '>=0.29.11 <0.31.0' - dart_style: '>=0.2.10 <2.0.0' - func: '>=0.1.0 <2.0.0' - matcher: ^0.12.0+2 - meta: ^1.0.2 + built_collection: ^1.0.0 + built_value: ^1.0.0 + matcher: ^0.12.0 + meta: ^1.0.5 dev_dependencies: + build_runner: ^0.3.0 + built_value_generator: ^1.0.0 + dart_style: ^1.0.0 test: ^0.12.0 diff --git a/pkgs/code_builder/test/builders/break_test.dart b/pkgs/code_builder/test/builders/break_test.dart deleted file mode 100644 index de03eec99..000000000 --- a/pkgs/code_builder/test/builders/break_test.dart +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -import 'package:code_builder/src/builders/statement/break.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -void main() { - test('should emit a break statement', () { - expect(breakStatement, equalsSource('break;')); - }); -} diff --git a/pkgs/code_builder/test/builders/class_test.dart b/pkgs/code_builder/test/builders/class_test.dart deleted file mode 100644 index ba64f94fb..000000000 --- a/pkgs/code_builder/test/builders/class_test.dart +++ /dev/null @@ -1,199 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/src/builders/method.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -void main() { - test('should emit an empty class', () { - expect( - clazz('Animal'), - equalsSource(r''' - class Animal {} - '''), - ); - }); - - test('should emit an abstract class', () { - expect( - new ClassBuilder('Animal', asAbstract: true) - ..addMethod(new MethodBuilder.returnVoid( - 'eat', - asAbstract: true, - )), - equalsSource(r''' - abstract class Animal { - void eat(); - } - '''), - ); - }); - - test('should emit a class with an annotation', () { - expect( - clazz('Animal', [reference('deprecated')]), - equalsSource(r''' - @deprecated - class Animal {} - '''), - ); - }); - - test('should emit a class that extends another', () { - expect( - clazz('Animal', [extend(reference('Life'))]), - equalsSource(r''' - class Animal extends Life {} - '''), - ); - }); - - test('should emit a class that implements another', () { - expect( - clazz('Animal', [implement(reference('Living'))]), - equalsSource(r''' - class Animal implements Living {} - '''), - ); - }); - - test('should emit a class that mixes in another', () { - expect( - clazz('Animal', [mixin(reference('Living'))]), - equalsSource(r''' - class Animal extends Object with Living {} - '''), - ); - }); - - test('should emit a class with a constructor', () { - expect( - clazz('Animal', [ - constructor(), - ]), - equalsSource(r''' - class Animal { - Animal(); - } - '''), - ); - }); - - test('should emit a class with a named constructor', () { - expect( - clazz('Animal', [ - constructorNamed('internal'), - ]), - equalsSource(r''' - class Animal { - Animal.internal(); - } - '''), - ); - }); - - test('should emit a class with a constructor with parameters', () { - expect( - clazz('Animal', [ - constructor([ - parameter('name', [lib$core.String]), - thisField( - named( - parameter('age').asOptional(literal(0)), - ), - ) - ]) - ]), - equalsSource(r''' - class Animal { - Animal(String name, {this.age: 0}); - } - '''), - ); - }); - - test('should emit a class with a constructor with initializers', () { - expect( - clazz('Animal', [ - new ConstructorBuilder( - invokeSuper: const [], - )..addInitializer('name', toParameter: 'other'), - ]), - equalsSource(r''' - class Animal { - Animal() : name = other, super(); - } - '''), - ); - }); - - test('should emit a class with fields', () { - expect( - clazz('Animal', [ - asStatic( - varField('static1', type: lib$core.String, value: literal('Hello')), - ), - asStatic( - varFinal('static2', type: lib$core.List, value: literal([])), - ), - asStatic( - varConst('static3', type: lib$core.bool, value: literal(true)), - ), - varField('var1', type: lib$core.String, value: literal('Hello')), - varFinal('var2', type: lib$core.List, value: literal([])), - varConst('var3', type: lib$core.bool, value: literal(true)), - ]), - equalsSource(r''' - class Animal { - static String static1 = 'Hello'; - static final List static2 = []; - static const bool static3 = true; - String var1 = 'Hello'; - final List var2 = []; - const bool var3 = true; - } - '''), - ); - }); - - test('should emit a class with methods', () { - expect( - clazz('Animal', [ - asStatic(method('staticMethod', [ - lib$core.$void, - lib$core.print.call([literal('Called staticMethod')]), - ])), - method('instanceMethod', [ - lib$core.$void, - lib$core.print.call([literal('Called instanceMethod')]), - ]), - constructor([ - lib$core.print.call([literal('Called constructor')]), - ]), - new MethodBuilder( - 'toString', - returns: literal(r'$Animal'), - returnType: lib$core.String, - ), - ]), - equalsSource(r''' - class Animal { - Animal() { - print('Called constructor'); - } - static void staticMethod() { - print('Called staticMethod'); - } - void instanceMethod() { - print('Called instanceMethod'); - } - String toString() => '$Animal'; - } - '''), - ); - }); -} diff --git a/pkgs/code_builder/test/builders/expression_test.dart b/pkgs/code_builder/test/builders/expression_test.dart deleted file mode 100644 index 39d83547f..000000000 --- a/pkgs/code_builder/test/builders/expression_test.dart +++ /dev/null @@ -1,449 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -void main() { - group('literal', () { - test('should emit a null', () { - expect(literal(null), equalsSource(r'null')); - }); - - test('should emit true', () { - expect(literal(true), equalsSource(r'true')); - }); - - test('should emit false', () { - expect(literal(false), equalsSource(r'false')); - }); - - test('should emit an int', () { - expect(literal(5), equalsSource(r'5')); - }); - - test('should emit a double', () { - expect(literal(5.5), equalsSource(r'5.5')); - }); - - group('should emit a string', () { - test('simple', () { - expect(literal('Hello'), equalsSource(r"'Hello'")); - }); - - test("with a '", () { - expect(literal("Hello'"), equalsSource(r"'Hello\''")); - }); - - test(r"with a \'", () { - expect(literal(r"Hello\'"), equalsSource(r"'Hello\\\''")); - }); - - test(r"with a \\'", () { - expect(literal(r"Hello\\'"), equalsSource(r"'Hello\\\\\''")); - }); - - test(r"with a newline", () { - expect(literal("Hello\nworld"), equalsSource("'''Hello\nworld'''")); - }); - - test(r"with a newline and ending with a '", () { - expect(literal("Hello\nworld'"), equalsSource("'''Hello\nworld\\''''")); - }); - }); - - test('should emit a list', () { - expect(literal([1, 2, 3]), equalsSource(r'[1, 2, 3]')); - }); - - test('should emit a typed list', () { - expect( - list([1, 2, 3], type: lib$core.int), - equalsSource(r' [1, 2, 3]'), - ); - }); - - test('should emit a map', () { - expect(literal({1: 2, 2: 3}), equalsSource(r'{1 : 2, 2 : 3}')); - }); - - test('should emit a typed map', () { - expect( - map( - { - 1: '2', - 2: '3', - }, - keyType: lib$core.int, - valueType: lib$core.String, - ), - equalsSource(r''' - {1 : '2', 2 : '3'} - '''), - ); - }); - }); - - test('should emit an assert statemnet', () { - expect( - literal(true).asAssert(), - equalsSource(r''' - assert(true); - '''), - ); - }); - - test('should emit an assign expression', () { - expect( - literal(true).asAssign(reference('flag')), - equalsSource(r''' - flag = true - '''), - ); - }); - - test('should emit an assign expression with a null aware', () { - expect( - literal(true).asAssign(reference('flag'), nullAware: true), - equalsSource(r''' - flag ??= true - '''), - ); - }); - - test('should emit a const variable assignment statement', () { - expect( - literal(true).asConst('flag'), - equalsSource(r''' - const flag = true; - '''), - ); - }); - - test('should emit a final variable assignment statement', () { - expect( - literal(true).asFinal('flag'), - equalsSource(r''' - final flag = true; - '''), - ); - }); - - test('should emit a simple var assignment statement', () { - expect( - literal(true).asVar('flag'), - equalsSource(r''' - var flag = true; - '''), - ); - }); - - test('should emit a typed assignemnt statement', () { - expect( - literal(true).asVar('flag', lib$core.bool), - equalsSource(r''' - bool flag = true; - '''), - ); - }); - - test('should emit a return statement', () { - expect( - literal(true).asReturn(), - equalsSource(r''' - return true; - '''), - ); - }); - - test('should emit an expression as a statement', () { - expect( - literal(true).asStatement(), - equalsSource(r''' - true; - '''), - ); - }); - - test('should call an expression as a function', () { - expect( - lib$core.identical.call([literal(true), literal(true)]), - equalsSource(r''' - identical(true, true) - '''), - ); - }); - - test('should call an expression with named arguments', () { - expect( - reference('doThing').call( - [literal(true)], - namedArguments: { - 'otherFlag': literal(false), - }, - ), - equalsSource(r''' - doThing(true, otherFlag: false) - '''), - ); - }); - - test('should call a method on an expression', () { - expect( - explicitThis.invoke('doThing', [literal(true)]), - equalsSource(r''' - this.doThing(true) - '''), - ); - }); - - test('should call a method on an expression with generic parameters', () { - expect( - explicitThis.invoke('doThing', [ - literal(true) - ], genericTypes: [ - lib$core.bool, - ]), - equalsSource(r''' - this.doThing(true) - '''), - ); - }); - - test('should emit an identical() expression', () { - expect( - literal(true).identical(literal(false)), - equalsSource(r''' - identical(true, false) - '''), - ); - }); - - test('should emit an equality (==) expression', () { - expect( - literal(true).equals(literal(false)), - equalsSource(r''' - true == false - '''), - ); - }); - - test('should emit a not equals (!=) expression', () { - expect( - literal(true).notEquals(literal(false)), - equalsSource(r''' - true != false - '''), - ); - }); - - test('should emit a negated expression', () { - expect( - reference('foo').negate(), - equalsSource(r''' - !(foo) - '''), - ); - }); - - test('should add two expressions', () { - expect( - literal(1) + literal(2), - equalsSource(r''' - 1 + 2 - '''), - ); - }); - - test('should subtract two expressions', () { - expect( - literal(2) - literal(1), - equalsSource(r''' - 2 - 1 - '''), - ); - }); - - test('should multiply two expressions', () { - expect( - literal(2) * literal(3), - equalsSource(r''' - 2 * 3 - '''), - ); - }); - - test('should divide two expressions', () { - expect( - literal(3) / literal(2), - equalsSource(r''' - 3 / 2 - '''), - ); - }); - - test('should wrap an expressions in ()', () { - expect( - literal(true).parentheses(), - equalsSource(r''' - (true) - '''), - ); - }); - - test('should return as a negative expression', () { - expect( - literal(1).negative(), - equalsSource(r''' - -(1) - '''), - ); - }); - - test('should return as an index expression', () { - expect( - literal([literal(1), literal(2), literal(3)])[literal(0)], - equalsSource(r''' - [1, 2, 3][0] - '''), - ); - }); - - test('should return as an index expression assignment', () { - expect( - reference('value').asAssign(reference('list')[reference('index')]), - equalsSource(r''' - list[index] = value - '''), - ); - }); - - test('should emit a top-level field declaration', () { - expect( - new LibraryBuilder()..addMember(literal(false).asConst('foo')), - equalsSource(r''' - const foo = false; - '''), - ); - }); - - test('should emit cascaded expressions', () { - expect( - reference('foo') - .cascade((c) => [ - c.invoke('doThis', []), - c.invoke('doThat', []), - reference('Bar').newInstance([]).asAssign(c.property('bar')), - ]) - .asStatement(), - equalsSource(r''' - foo - ..doThis() - ..doThat() - ..bar = new Bar(); - '''), - ); - }); - - test('should emit a newInstance with a named constructor', () { - expect( - reference('Foo').newInstance([], constructor: 'other'), - equalsSource(r''' - new Foo.other() - '''), - ); - }); - - test('should emit a constInstance with a named constructor', () { - expect( - reference('Foo').constInstance([], constructor: 'other'), - equalsSource(r''' - const Foo.other() - '''), - ); - }); - - test('should scope on newInstance', () { - expect( - reference('Foo', 'package:foo/foo.dart').newInstance([]).asReturn(), - equalsSource( - r''' - return new _i1.Foo(); - ''', - scope: new Scope()), - ); - }); - - test('should emit await', () { - expect( - reference('foo').asAwait(), - equalsSource(r''' - await foo - '''), - ); - }); - - test('should emit yield', () { - expect( - reference('foo').asYield(), - equalsSource(r''' - yield foo; - '''), - ); - }); - - test('should emit yield*', () { - expect( - reference('foo').asYieldStar(), - equalsSource(r''' - yield* foo; - '''), - ); - }); - - test('raw expression', () { - expect( - lambda( - 'main', - new ExpressionBuilder.raw( - (scope) => '5 + 3 + ${scope.identifier('q')}', - ), - ), - equalsSource(r''' - main() => 5 + 3 + q; - '''), - ); - }); - - test('should emit casted as another type', () { - expect( - literal(1.0).castAs(lib$core.num), - equalsSource(r''' - 1.0 as num - '''), - ); - }); - - test('should throw an exception', () { - expect( - new TypeBuilder('StateError') - .newInstance([literal('Hey! No!')]) - .asThrow() - .asStatement(), - equalsSource(''' - throw new StateError('Hey! No!'); - ''')); - }); - - test('should create a ternary condition ? ifTrue : ifFalse', () { - expect( - reference('someValue').ternary(literal(true), literal(false)), - equalsSource(r''' - someValue ? true : false - '''), - ); - }); -} diff --git a/pkgs/code_builder/test/builders/field_test.dart b/pkgs/code_builder/test/builders/field_test.dart deleted file mode 100644 index 739e7a726..000000000 --- a/pkgs/code_builder/test/builders/field_test.dart +++ /dev/null @@ -1,37 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -void main() { - test('emit a var', () { - expect( - varField('a', type: lib$core.String, value: literal('Hello')), - equalsSource(r''' - String a = 'Hello'; - '''), - ); - }); - - test('emit a final', () { - expect( - varFinal('a', type: lib$core.String, value: literal('Hello')), - equalsSource(r''' - final String a = 'Hello'; - '''), - ); - }); - - test('emit a const', () { - expect( - varConst('a', type: lib$core.String, value: literal('Hello')), - equalsSource(r''' - const String a = 'Hello'; - '''), - ); - }); -} diff --git a/pkgs/code_builder/test/builders/file_test.dart b/pkgs/code_builder/test/builders/file_test.dart deleted file mode 100644 index 24dfe84b1..000000000 --- a/pkgs/code_builder/test/builders/file_test.dart +++ /dev/null @@ -1,103 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -void main() { - group('$ImportBuilder', () { - test('should support "show"', () { - expect( - new ImportBuilder('package:foo/foo.dart')..show('Foo'), - equalsSource(r''' - import 'package:foo/foo.dart' show Foo; - '''), - ); - }); - - test('should support "show"', () { - expect( - new ImportBuilder('package:foo/foo.dart')..hide('Bar'), - equalsSource(r''' - import 'package:foo/foo.dart' hide Bar; - '''), - ); - }); - - test('should support "deferred as"', () { - expect( - new ImportBuilder( - 'package:foo/foo.dart', - deferred: true, - prefix: 'foo', - ), - equalsSource(r''' - import 'package:foo/foo.dart' deferred as foo; - '''), - ); - }); - }); - - group('$ExportBuilder', () { - test('should support "show"', () { - expect( - new ExportBuilder('package:foo/foo.dart')..show('Foo'), - equalsSource(r''' - export 'package:foo/foo.dart' show Foo; - '''), - ); - }); - - test('should support "show"', () { - expect( - new ExportBuilder('package:foo/foo.dart')..hide('Bar'), - equalsSource(r''' - export 'package:foo/foo.dart' hide Bar; - '''), - ); - }); - - group('$LibraryBuilder', () { - test('should handle empty methods', () { - expect( - new LibraryBuilder()..addMember(new MethodBuilder.returnVoid('main')), - equalsSource('void main() {}'), - ); - }); - - test('should support metadata', () { - expect( - new LibraryBuilder('some_lib')..addAnnotation(reference('ignore')), - equalsSource(r''' - @ignore - library some_lib; - '''), - ); - }); - }); - - group('$PartBuilder', () { - test('should emit a part directive', () { - expect( - new LibraryBuilder()..addDirective(new PartBuilder('part.dart')), - equalsSource(r''' - part 'part.dart'; - '''), - ); - }); - }); - - group('$PartOfBuilder', () { - test('should emit a part-of file', () { - expect( - new PartOfBuilder('main.dart'), - equalsSource(r''' - part of 'main.dart'; - '''), - ); - }); - }); - }); -} diff --git a/pkgs/code_builder/test/builders/is_instance_of_test.dart b/pkgs/code_builder/test/builders/is_instance_of_test.dart deleted file mode 100644 index 20bbf6c85..000000000 --- a/pkgs/code_builder/test/builders/is_instance_of_test.dart +++ /dev/null @@ -1,20 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -final TypeBuilder _barType = new TypeBuilder('Bar'); - -void main() { - test('should emit an `is` expression', () { - expect(reference('foo').isInstanceOf(_barType), equalsSource('foo is Bar')); - }); - - test('should emit an `is!` expression', () { - expect(reference('foo').isInstanceOf(_barType).negate(), - equalsSource('!(foo is Bar)')); - }); -} diff --git a/pkgs/code_builder/test/builders/method_test.dart b/pkgs/code_builder/test/builders/method_test.dart deleted file mode 100644 index 01c495512..000000000 --- a/pkgs/code_builder/test/builders/method_test.dart +++ /dev/null @@ -1,305 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -void main() { - test('should emit a top-level main() function', () { - expect( - method('main'), - equalsSource(r''' - main() {} - '''), - ); - }); - - test('should emit a top-level void main() function', () { - expect( - method('main', [ - lib$core.$void, - ]).buildMethod(false).toSource(), - equalsIgnoringWhitespace(r''' - void main() {} - '''), - ); - }); - - test('should emit a function with a parameter', () { - expect( - method('main', [ - parameter('args', [lib$core.List]), - ]).buildMethod(false).toSource(), - equalsIgnoringWhitespace(r''' - main(List args) {} - '''), - ); - }); - - test('should emit a function with multiple parameters', () { - expect( - method('main', [ - parameter('a'), - parameter('b'), - parameter('c').asOptional(), - ]), - equalsSource(r''' - main(a, b, [c]) {} - '''), - ); - }); - - test('should emit a function with multiple parameters', () { - expect( - method('main', [ - parameter('a'), - parameter('b'), - parameter('c').asOptional(literal(true)), - ]), - equalsSource(r''' - main(a, b, [c = true]) {} - '''), - ); - }); - - test('should emit a function with named parameters', () { - expect( - method('main', [ - named(parameter('a')), - named(parameter('b').asOptional(literal(true))), - ]).buildMethod(false).toSource(), - equalsIgnoringWhitespace(r''' - main({a, b : true}) {} - '''), - ); - }); - - test('should emit a function with a lambda expression', () { - expect( - new MethodBuilder('talk', returns: literal('Hello World')), - equalsSource(r''' - talk() => 'Hello World'; - '''), - ); - }); - - group('constructors', () { - test('should emit a simple constructor', () { - expect( - new ConstructorBuilder() - .buildConstructor( - reference('Animal'), - ) - .toSource(), - equalsIgnoringWhitespace(r''' - Animal(); - '''), - ); - }); - - test('should emit a simple constructor with parameters', () { - expect( - (new ConstructorBuilder()..addPositional(parameter('name'))) - .buildConstructor( - reference('Animal'), - ) - .toSource(), - equalsIgnoringWhitespace(r''' - Animal(name); - '''), - ); - }); - - test('should emit a simple constructor with field-formal parameters', () { - expect( - (new ConstructorBuilder() - ..addPositional( - parameter('name'), - asField: true, - )) - .buildConstructor( - reference('Animal'), - ) - .toSource(), - equalsIgnoringWhitespace(r''' - Animal(this.name); - '''), - ); - }); - - test('should emit a const constructor', () { - expect( - new ConstructorBuilder(asConst: true) - .buildConstructor( - reference('Animal'), - ) - .toSource(), - equalsIgnoringWhitespace(r''' - const Animal(); - '''), - ); - }); - - test('should emit a factory constructor', () { - expect( - (new ConstructorBuilder(asFactory: true) - ..addStatement(literal(null).asReturn())) - .buildConstructor( - reference('Animal'), - ) - .toSource(), - equalsIgnoringWhitespace(r''' - factory Animal() {return null;} - '''), - ); - }); - - test('should emit a redirecting constructor', () { - expect( - new ConstructorBuilder.redirectTo( - 'noopAnimal', - reference('NoopAnimalImpl'), - asConst: true, - ) - .buildConstructor(reference('Animal')) - .toSource(), - equalsIgnoringWhitespace(r''' - const factory Animal.noopAnimal() = NoopAnimalImpl; - '''), - ); - }); - - test('should a method with a lambda value', () { - expect( - lambda('supported', literal(true), returnType: lib$core.bool), - equalsSource(r''' - bool supported() => true; - '''), - ); - }); - }); - - test('should emit a getter with a lambda value', () { - expect( - getter('unsupported', returns: literal(true)), - equalsSource(r''' - get unsupported => true; - '''), - ); - }); - - test('should emit a getter with statements', () { - expect( - getter( - 'values', - returnType: lib$core.Iterable, - statements: [ - literal([]).asReturn(), - ], - ), - equalsSource(r''' - Iterable get values { - return []; - } - '''), - ); - }); - - test('should emit a setter', () { - expect( - setter('name', parameter('name', [lib$core.String]), [ - (reference('name') + literal('!')).asAssign(reference('_name')), - ]), - equalsSource(r''' - set name(String name) { - _name = name + '!'; - } - '''), - ); - }); - - test('should emit an async method', () { - expect( - method('fetch', [MethodModifier.asAsync]), - equalsSource(r''' - fetch() async {} - '''), - ); - }); - - test('should emit an async* method', () { - expect( - method('fetch', [MethodModifier.asAsyncStar]), - equalsSource(r''' - fetch() async* {} - '''), - ); - }); - - test('should emit an sync* method', () { - expect( - method('fetch', [MethodModifier.asSyncStar]), - equalsSource(r''' - fetch() sync* {} - '''), - ); - }); - - group('closure', () { - MethodBuilder closure; - setUp(() { - closure = new MethodBuilder.closure( - returns: literal(false).or(reference('defaultTo')), - )..addPositional(parameter('defaultTo', [lib$core.bool])); - }); - - test('should emit a closure', () { - // Should be usable as an expression/parameter itself. - expect(closure, const isInstanceOf()); - expect( - closure, - equalsSource(r''' - (bool defaultTo) => false || defaultTo - '''), - ); - }); - - test('should treat closure as expression', () { - expect( - list([true, false]).invoke('where', [closure]), - equalsSource( - '[true, false].where((bool defaultTo) => false || defaultTo)', - ), - ); - }); - - test('should emit a closure as a function in a library', () { - final library = new LibraryBuilder(); - library.addMember(closure); - expect( - library, - equalsSource('(bool defaultTo) => false || defaultTo;'), - ); - }); - - test('should emit a closure with a statement body', () { - expect( - (new MethodBuilder.closure() - ..addPositional(new ParameterBuilder('value')) - ..addStatement(reference('value').invoke( - 'join', - [literal(' - ')], - ).asAssign(reference('title')))) - .asStatement(), - equalsSource(r''' - (value) { - title = value.join(' - '); - }; - '''), - ); - }); - }); -} diff --git a/pkgs/code_builder/test/builders/parameter_test.dart b/pkgs/code_builder/test/builders/parameter_test.dart deleted file mode 100644 index b77cb15a9..000000000 --- a/pkgs/code_builder/test/builders/parameter_test.dart +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -void main() { - test('should emit a simple parameter', () { - expect( - parameter('foo'), - equalsSource(r''' - foo - '''), - ); - }); - - test('should emit a typed parameter', () { - expect( - parameter('foo', [reference('String')]), - equalsSource(r''' - String foo - '''), - ); - }); - - test('should emit an optional parameter with a default value', () { - expect( - parameter('foo').asOptional(literal(true)), - equalsSource(r''' - foo = true - '''), - ); - }); - - test('should emit a named parameter with a default value', () { - expect( - parameter('foo').asOptional(literal(true)).buildNamed(false).toSource(), - equalsIgnoringCase(r'foo : true'), - ); - }); - - test('should emit a field formal parameter', () { - expect( - parameter('foo').buildPositional(true).toSource(), - equalsIgnoringCase(r'this.foo'), - ); - }); - - test('should emit a function typed parameter', () { - expect( - (new FunctionParameterBuilder( - 'callback', - returnType: lib$core.$void, - )..addPositional(parameter('value'))) - .buildPositional(false) - .toSource(), - equalsIgnoringWhitespace(r''' - void callback(value) - '''), - ); - }); -} diff --git a/pkgs/code_builder/test/builders/shared_test.dart b/pkgs/code_builder/test/builders/shared_test.dart deleted file mode 100644 index 12a314f65..000000000 --- a/pkgs/code_builder/test/builders/shared_test.dart +++ /dev/null @@ -1,21 +0,0 @@ -// 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. - -// 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. - -import 'package:code_builder/src/builders/shared.dart'; -import 'package:code_builder/src/tokens.dart'; -import 'package:test/test.dart'; - -void main() { - test('stringIdentifier should return a string identifier', () { - expect(stringIdentifier('Coffee').toSource(), 'Coffee'); - }); - - test('stringToken should return a string token', () { - expect(stringToken('Coffee').value().toString(), 'Coffee'); - }); -} diff --git a/pkgs/code_builder/test/builders/statement_test.dart b/pkgs/code_builder/test/builders/statement_test.dart deleted file mode 100644 index ca6f91277..000000000 --- a/pkgs/code_builder/test/builders/statement_test.dart +++ /dev/null @@ -1,155 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -void main() { - group('if statements', () { - test('should emit a simple if statement', () { - expect( - ifThen(literal(true), [ - lib$core.print.call([literal('Hello World')]), - ]), - equalsSource(r''' - if (true) { - print('Hello World'); - } - '''), - ); - }); - - test('should emit an if then else statement', () { - expect( - ifThen(literal(true), [ - lib$core.print.call([literal('TRUE')]), - elseThen([ - lib$core.print.call([literal('FALSE')]), - ]), - ]), - equalsSource(r''' - if (true) { - print('TRUE'); - } else { - print('FALSE'); - } - '''), - ); - }); - - test('should emit an if else then statement', () { - final a = reference('a'); - expect( - ifThen(a.equals(literal(1)), [ - lib$core.print.call([literal('Was 1')]), - elseIf(ifThen(a.equals(literal(2)), [ - lib$core.print.call([literal('Was 2')]), - ])), - ]), - equalsSource(r''' - if (a == 1) { - print('Was 1'); - } else if (a == 2) { - print('Was 2'); - } - '''), - ); - }); - - test('should emit an if else if else statement', () { - final a = reference('a'); - expect( - ifThen( - a.equals(literal(1)), - [ - lib$core.print.call([literal('Was 1')]), - elseIf(ifThen(a.equals(literal(2)), [ - lib$core.print.call([literal('Was 2')]), - elseThen([ - lib$core.print.call([literal('Was ') + a]), - ]), - ])), - ], - ), - equalsSource(r''' - if (a == 1) { - print('Was 1'); - } else if (a == 2) { - print('Was 2'); - } else { - print('Was ' + a); - } - '''), - ); - }); - - test('should emit a return statement', () { - expect( - returnVoid, - equalsSource(r''' - return; - '''), - ); - }); - }); - - group('for statements', () { - test('should emit a simple for-loop', () { - expect( - new ForStatementBuilder( - 'i', - literal(0), - reference('i') < reference('items').property('length'), - [ - reference('i').increment(), - ], - ), - equalsSource(r''' - for (var i = 0; i < items.length; i++) {} - '''), - ); - }); - - test('should emit a simple for-each loop', () { - expect( - new ForStatementBuilder.forEach( - 'item', - reference('items'), - ), - equalsSource(r''' - for (var item in items) {} - '''), - ); - }); - }); - - group('while loop', () { - test('should emit a simple while loop', () { - expect(literal(true).asWhile(), equalsSource(r''' - while(true) {} - ''')); - }); - - test('should emit a simple do-while loop', () { - expect(literal(true).asWhile(asDo: true), equalsSource(r''' - do {} while (true); - ''')); - }); - }); - - test('raw statement', () { - expect( - method('main', [ - new StatementBuilder.raw((scope) => 'print(${scope.identifier('q')});'), - ]), - equalsSource(r''' - main() { - print(q); - } - '''), - ); - }); -} diff --git a/pkgs/code_builder/test/builders/switch_test.dart b/pkgs/code_builder/test/builders/switch_test.dart deleted file mode 100644 index daf50a63c..000000000 --- a/pkgs/code_builder/test/builders/switch_test.dart +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/src/builders/statement/switch.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -void main() { - test('should emit an empty switch statement', () { - expect(switchStatement(reference('foo')), equalsSource(''' - switch (foo) {} - ''')); - }); - - test('should emit cases', () { - expect( - switchStatement(reference('foo'), cases: [ - switchCase(literal('bar'), [literal('baz').asReturn()]), - switchCase(literal(42) * literal(5), [ - reference('math') - .call([literal(24) + reference('three')]).asReturn() - ]) - ]), - equalsSource(''' - switch (foo) { - case 'bar': - return 'baz'; - case 42 * 5: - return math(24 + three); - } - ''')); - }); - - test('should emit default case if given', () { - expect( - switchStatement(reference('foo'), - cases: [ - switchCase(literal('bar'), [ - reference('print').call([literal('baz')]), - breakStatement - ]) - ], - defaultCase: switchDefault([literal(null).asReturn()])), - equalsSource(''' - switch(foo) { - case 'bar': - print('baz'); - break; - default: - return null; - } - ''')); - }); -} diff --git a/pkgs/code_builder/test/builders/type_test.dart b/pkgs/code_builder/test/builders/type_test.dart deleted file mode 100644 index 18d356f03..000000000 --- a/pkgs/code_builder/test/builders/type_test.dart +++ /dev/null @@ -1,161 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -void main() { - test('TypeBuilder emits a generic type reference', () { - expect( - new TypeBuilder('List', genericTypes: [reference('String')]), - equalsSource(r''' - List - '''), - ); - }); - - test('ReferenceBuilder.toTyped emits a generic type reference', () { - expect( - lib$core.Map.toTyped([ - lib$core.String, - lib$core.List.toTyped([ - lib$core.int, - ]), - ]), - equalsSource(r''' - Map> - '''), - ); - }); - - group('new instance', () { - test('emits a new List', () { - expect( - lib$core.List.newInstance([]), - equalsSource(r''' - new List() - '''), - ); - }); - - test('emits a new List.from', () { - expect( - lib$core.List.newInstance([ - literal([1, 2, 3]), - ], constructor: 'from'), - equalsSource(r''' - new List.from([1, 2, 3]) - '''), - ); - }); - - test('emits a new const Point', () { - expect( - reference('Point').constInstance([ - literal(1), - literal(2), - ]), - equalsSource(r''' - const Point(1, 2) - '''), - ); - }); - - test('emits a const constructor as an annotation', () { - expect( - clazz('Animal', [ - lib$core.Deprecated - .constInstance([literal('Animals are out of style')]), - ]), - equalsSource(r''' - @Deprecated('Animals are out of style') - class Animal {} - '''), - ); - }); - - test('emits a named const constructor as an annotation', () { - expect( - clazz('Animal', [ - reference('Component').constInstance( - [], - constructor: 'stateful', - namedArguments: { - 'selector': literal('animal'), - }, - ), - ]), - equalsSource(r''' - @Component.stateful(selector: 'animal') - class Animal {} - '''), - ); - }); - - test('emits an export builder', () { - expect( - reference('Foo', 'package:foo/foo.dart').toExportBuilder(), - equalsSource(r''' - export 'package:foo/foo.dart' show Foo; - '''), - ); - }); - - test('emits an export builder', () { - expect( - reference('Foo', 'package:foo/foo.dart').toImportBuilder(), - equalsSource(r''' - import 'package:foo/foo.dart' show Foo; - '''), - ); - }); - }); - - test('emits as a Type to be used as an expression', () { - expect( - lambda('foo', new TypeBuilder('Foo')), - equalsSource(r''' - foo() => Foo; - '''), - ); - }); - - test('throws when a Type references generics for an expression', () { - expect( - () => new TypeBuilder('Foo', genericTypes: [ - new TypeBuilder('Bar'), - ]).buildExpression(), - throwsStateError, - ); - }); - - test('can create a simple typedef', () { - expect( - new TypeDefBuilder( - 'Callback', - returnType: lib$core.$void, - ), - equalsSource(r''' - typedef void Callback(); - '''), - ); - }); - - test('can create a more complex typedef', () { - expect( - new TypeDefBuilder( - 'Callback', - genericTypes: { - 'T': lib$core.Set, - }, - returnType: reference('T'), - )..addPositional(parameter('items')), - equalsSource(r''' - typedef T Callback(items); - '''), - ); - }); -} diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart new file mode 100644 index 000000000..807d7925e --- /dev/null +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -0,0 +1,48 @@ +// 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:test/test.dart'; + +void main() { + test('should generate a complex generated file', () { + // Imports from an existing Dart library. + final $App = const Reference('App', 'package:app/app.dart'); + final $Module = const Reference('Module', 'package:app/app.dart'); + final $Thing = const Reference('Thing', 'package:app/app.dart'); + + final clazz = new ClassBuilder() + ..name = 'Injector' + ..implements.add($App.toType()) + ..fields.add(new Field((b) => b + ..modifier = FieldModifier.final$ + ..name = '_module' + ..type = $Module.toType())) + ..constructors.add(new Constructor((b) => b + ..requiredParameters.add(new Parameter((b) => b + ..name = '_module' + ..toThis = true)))) + ..methods.add(new Method((b) => b + ..name = 'getThing' + ..body = new Code((b) => b + ..code = 'new {{ThingRef}}(_module.get1(), _module.get2())' + ..specs['ThingRef'] = () => $Thing) + ..lambda = true + ..returns = $Thing.toType() + ..annotations.add(new Annotation( + (b) => b..code = new Code((b) => b.code = 'override'))))); + + expect( + clazz.build(), + equalsDart(r''' + class Injector implements App { + Injector(this._module); + final Module _module; + @override + Thing getThing() => new Thing(_module.get1(), _module.get2()); + } + '''), + ); + }); +} diff --git a/pkgs/code_builder/test/e2e_test.dart b/pkgs/code_builder/test/e2e_test.dart deleted file mode 100644 index 356e25e29..000000000 --- a/pkgs/code_builder/test/e2e_test.dart +++ /dev/null @@ -1,118 +0,0 @@ -// 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. - -import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/dart/core.dart'; -import 'package:code_builder/testing.dart'; -import 'package:test/test.dart'; - -// Closely mirrors the API you'd need to generate dependency injection :) -void main() { - test('Should emit a complex generated file', () { - // Imports from an existing Dart library. - var appRef = reference('App', 'package:app/app.dart'); - var moduleRef = reference('Module', 'package:app/app.dart'); - var thingRef = reference('Thing', 'package:app/app.dart'); - - var clazz = new ClassBuilder('Injector', asImplements: [appRef]); - clazz - ..addField( - new FieldBuilder.asFinal('_module', type: moduleRef), - ) - ..addConstructor(new ConstructorBuilder() - ..addPositional( - new ParameterBuilder('_module'), - asField: true, - )) - ..addMethod(new MethodBuilder( - 'getThing', - returns: thingRef.newInstance([ - reference('_module').invoke('getDep1', []), - reference('_module').invoke('getDep2', []), - ]), - returnType: thingRef, - )..addAnnotation(lib$core.override)); - var lib = new LibraryBuilder() - ..addDirective( - new ImportBuilder('app.dart'), - ) - ..addMember( - clazz, - ); - expect( - lib, - equalsSource( - r''' - import 'app.dart'; - - class Injector implements App { - final Module _module; - - Injector(this._module); - - @override - Thing getThing() => new Thing(_module.getDep1(), _module.getDep2()); - } - ''', - pretty: true, - ), - ); - }); - - test('Should emit a complex generated file with scoping applied', () { - var appRef = reference('App', 'package:app/app.dart'); - var moduleRef = reference('Module', 'package:app/app.dart'); - var thingRef = reference('Thing', 'package:app/thing.dart'); - var lib = new LibraryBuilder.scope() - ..addMember(new ClassBuilder('Injector', asImplements: [appRef]) - ..addField( - new FieldBuilder.asFinal( - '_module', - type: moduleRef, - ), - ) - ..addConstructor(new ConstructorBuilder() - ..addPositional( - new ParameterBuilder('_module'), - asField: true, - )) - ..addMethod(new MethodBuilder( - 'getThing', - returnType: thingRef, - returns: thingRef.newInstance([ - reference('_module').invoke('getDep1', []), - reference('_module').invoke('getDep2', []), - ]), - )..addAnnotation(lib$core.override)) - ..addMethod(new MethodBuilder( - 'instantiateAndReturnNamedThing', - returnType: thingRef, - )..addStatement( - thingRef.newInstance([], constructor: 'named').asReturn()))); - expect( - lib, - equalsSource( - r''' - import 'package:app/app.dart' as _i1; - import 'dart:core' as _i2; - import 'package:app/thing.dart' as _i3; - - class Injector implements _i1.App { - final _i1.Module _module; - - Injector(this._module); - - @_i2.override - _i3.Thing getThing() => new _i3.Thing(_module.getDep1(), _module.getDep2()); - - _i3.Thing instantiateAndReturnNamedThing() { - return new _i3.Thing.named(); - } - } - ''', - pretty: true, - ), - ); - }); -} diff --git a/pkgs/code_builder/test/scope_test.dart b/pkgs/code_builder/test/scope_test.dart deleted file mode 100644 index 084d7affc..000000000 --- a/pkgs/code_builder/test/scope_test.dart +++ /dev/null @@ -1,88 +0,0 @@ -// 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. - -import 'package:analyzer/analyzer.dart'; -import 'package:code_builder/src/scope.dart'; -import 'package:test/test.dart'; - -void main() { - Scope scope; - - tearDown(() => scope = null); - - test('Identity scope should do nothing', () { - scope = Scope.identity; - - var identifiers = [ - scope.identifier('Foo', 'package:foo/foo.dart'), - scope.identifier('Bar', 'package:foo/foo.dart'), - scope.identifier('Baz', 'package:baz/baz.dart'), - ].map((i) => i.toSource()); - - expect( - identifiers, - [ - 'Foo', - 'Bar', - 'Baz', - ], - ); - - expect(scope.toImports(), isEmpty); - }); - - test('Deduplicating scope should deduplicate imports', () { - scope = new Scope.dedupe(); - - var identifiers = [ - scope.identifier('Foo', 'package:foo/foo.dart'), - scope.identifier('Bar', 'package:foo/foo.dart'), - scope.identifier('Baz', 'package:baz/baz.dart'), - ].map((i) => i.toSource()); - - expect( - identifiers, - [ - 'Foo', - 'Bar', - 'Baz', - ], - ); - - expect( - scope.toImports().map((i) => i.buildAst().toSource()), - [ - r"import 'package:foo/foo.dart';", - r"import 'package:baz/baz.dart';", - ], - ); - }); - - test('Default scope should auto-prefix', () { - scope = new Scope(); - - var identifiers = [ - scope.identifier('Foo', 'package:foo/foo.dart'), - scope.identifier('Bar', 'package:foo/foo.dart'), - scope.identifier('Baz', 'package:baz/baz.dart'), - ].map((i) => i.toSource()); - - expect( - identifiers, - [ - '_i1.Foo', - '_i1.Bar', - '_i2.Baz', - ], - ); - - expect( - scope.toImports().map((i) => i.buildAst().toSource()), - [ - r"import 'package:foo/foo.dart' as _i1;", - r"import 'package:baz/baz.dart' as _i2;", - ], - ); - }); -} diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart new file mode 100644 index 000000000..61e69d3b4 --- /dev/null +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -0,0 +1,337 @@ +// 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:test/test.dart'; + +void main() { + test('should create a class', () { + expect( + new Class((b) => b..name = 'Foo'), + equalsDart(r''' + class Foo {} + '''), + ); + }); + + test('should create an abstract class', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..abstract = true), + equalsDart(r''' + abstract class Foo {} + '''), + ); + }); + + test('should create a class with documentations', () { + expect( + new Class( + (b) => b + ..name = 'Foo' + ..docs.addAll( + const [ + '/// My favorite class.', + ], + ), + ), + equalsDart(r''' + /// My favorite class. + class Foo {} + '''), + ); + }); + + test('should create a class with annotations', () { + final $deprecated = const Reference.localScope('deprecated'); + expect( + new Class( + (b) => b + ..name = 'Foo' + ..annotations.add( + new Annotation( + (b) => b + ..code = new Code( + (b) => b + ..code = '{{deprecated}}' + ..specs.addAll({ + 'deprecated': () => $deprecated, + }), + ), + ), + ), + ), + equalsDart(r''' + @deprecated + class Foo {} + '''), + ); + }); + + test('should create a class with a generic type', () { + expect( + new Class((b) => b + ..name = 'List' + ..types.add(const Reference.localScope('T').toType())), + equalsDart(r''' + class List {} + '''), + ); + }); + + test('should create a class with multiple generic types', () { + expect( + new Class( + (b) => b + ..name = 'Map' + ..types.addAll([ + const Reference.localScope('K').toType(), + const Reference.localScope('V').toType(), + ]), + ), + equalsDart(r''' + class Map {} + '''), + ); + }); + + test('should create a class with a bound generic type', () { + expect( + new Class((b) => b + ..name = 'Comparable' + ..types.add(new TypeReference((b) => b + ..symbol = 'T' + ..bound = new TypeReference((b) => b + ..symbol = 'Comparable' + ..types.add(const Reference.localScope('T').toType()))))), + equalsDart(r''' + class Comparable> {} + '''), + ); + }); + + test('should create a class extending another class', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..extend = new TypeReference((b) => b.symbol = 'Bar')), + equalsDart(r''' + class Foo extends Bar {} + '''), + ); + }); + + test('should create a class mixing in another class', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..extend = new TypeReference((b) => b.symbol = 'Bar') + ..mixins.add(new TypeReference((b) => b.symbol = 'Foo'))), + equalsDart(r''' + class Foo extends Bar with Foo {} + '''), + ); + }); + + test('should create a class implementing another class', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..extend = new TypeReference((b) => b.symbol = 'Bar') + ..implements.add(new TypeReference((b) => b.symbol = 'Foo'))), + equalsDart(r''' + class Foo extends Bar implements Foo {} + '''), + ); + }); + + test('should create a class with a constructor', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor())), + equalsDart(r''' + class Foo { + Foo(); + } + '''), + ); + }); + + test('should create a class with a constructor with initializers', () { + expect( + new Class( + (b) => b + ..name = 'Foo' + ..constructors.add( + new Constructor( + (b) => b + ..initializers.addAll([ + new Code((b) => b.code = 'a = 5'), + new Code((b) => b.code = 'super()'), + ]), + ), + ), + ), + equalsDart(r''' + class Foo { + Foo() : a = 5, super(); + } + '''), + ); + }); + + test('should create a class with a constructor with an annotation', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor((b) => b + ..annotations.add(new Annotation( + (b) => b..code = new Code((b) => b..code = 'deprecated')))))), + equalsDart(r''' + class Foo { + @deprecated + Foo(); + } + '''), + ); + }); + + test('should create a class with a named constructor', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor((b) => b..name = 'named'))), + equalsDart(r''' + class Foo { + Foo.named(); + } + '''), + ); + }); + + test('should create a class with a const constructor', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor((b) => b..constant = true))), + equalsDart(r''' + class Foo { + const Foo(); + } + '''), + ); + }); + + test('should create a class with an external constructor', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor((b) => b..external = true))), + equalsDart(r''' + class Foo { + external Foo(); + } + '''), + ); + }); + + test('should create a class with a factory constructor', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor((b) => b + ..factory = true + ..redirect = const Reference.localScope('_Foo')))), + equalsDart(r''' + class Foo { + factory Foo() = _Foo; + } + '''), + ); + }); + + test('should create a class with a factory lambda constructor', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor((b) => b + ..factory = true + ..lambda = true + ..body = new Code((b) => b..code = 'new _Foo()')))), + equalsDart(r''' + class Foo { + factory Foo() => new _Foo(); + } + '''), + ); + }); + + test('should create a class with a constructor with a body', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor((b) => b + ..factory = true + ..body = new Code((b) => b..code = 'return new _Foo();')))), + equalsDart(r''' + class Foo { + factory Foo() { + return new _Foo(); + } + } + '''), + ); + }); + + test('should create a class with method parameters', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor((b) => b + ..requiredParameters.addAll([ + new Parameter((b) => b..name = 'a'), + new Parameter((b) => b..name = 'b'), + ]) + ..optionalParameters.addAll([ + new Parameter((b) => b + ..name = 'c' + ..named = true), + ])))), + equalsDart(r''' + class Foo { + Foo(a, b, {c}); + } + '''), + ); + }); + + test('should create a class with a constructor+field-formal parameters', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor((b) => b + ..requiredParameters.addAll([ + new Parameter((b) => b + ..name = 'a' + ..toThis = true), + new Parameter((b) => b + ..name = 'b' + ..toThis = true), + ]) + ..optionalParameters.addAll([ + new Parameter((b) => b + ..name = 'c' + ..named = true + ..toThis = true), + ])))), + equalsDart(r''' + class Foo { + Foo(this.a, this.b, {this.c}); + } + '''), + ); + }); +} diff --git a/pkgs/code_builder/test/specs/field_test.dart b/pkgs/code_builder/test/specs/field_test.dart new file mode 100644 index 000000000..662738e8f --- /dev/null +++ b/pkgs/code_builder/test/specs/field_test.dart @@ -0,0 +1,61 @@ +// 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:test/test.dart'; + +void main() { + test('should create a field', () { + expect( + new Field((b) => b..name = 'foo'), + equalsDart(r''' + var foo; + '''), + ); + }); + + test('should create a typed field', () { + expect( + new Field((b) => b + ..name = 'foo' + ..type = const Reference.localScope('String').toType()), + equalsDart(r''' + String foo; + '''), + ); + }); + + test('should create a final field', () { + expect( + new Field((b) => b + ..name = 'foo' + ..modifier = FieldModifier.final$), + equalsDart(r''' + final foo; + '''), + ); + }); + + test('should create a constant field', () { + expect( + new Field((b) => b + ..name = 'foo' + ..modifier = FieldModifier.constant), + equalsDart(r''' + const foo; + '''), + ); + }); + + test('should create a field with an assignment', () { + expect( + new Field((b) => b + ..name = 'foo' + ..assignment = new Code((b) => b..code = '1')), + equalsDart(r''' + var foo = 1; + '''), + ); + }); +} diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart new file mode 100644 index 000000000..01d122e81 --- /dev/null +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -0,0 +1,315 @@ +// 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:test/test.dart'; + +void main() { + test('should create a method', () { + expect( + new Method((b) => b..name = 'foo'), + equalsDart(r''' + foo(); + '''), + ); + }); + + test('should create a getter', () { + expect( + new Method((b) => b + ..name = 'foo' + ..external = true + ..type = MethodType.getter), + equalsDart(r''' + external get foo; + '''), + ); + }); + + test('should create a setter', () { + expect( + new Method((b) => b + ..name = 'foo' + ..external = true + ..requiredParameters.add((new Parameter((b) => b..name = 'foo'))) + ..type = MethodType.setter), + equalsDart(r''' + external set foo(foo); + '''), + ); + }); + + test('should create a method with a return type', () { + expect( + new Method((b) => b + ..name = 'foo' + ..returns = const Reference.localScope('String').toType()), + equalsDart(r''' + String foo(); + '''), + ); + }); + + test('should create a method with generic types', () { + expect( + new Method((b) => b + ..name = 'foo' + ..types.add(const Reference.localScope('T').toType())), + equalsDart(r''' + foo(); + '''), + ); + }); + + test('should create an external method', () { + expect( + new Method((b) => b + ..name = 'foo' + ..external = true), + equalsDart(r''' + external foo(); + '''), + ); + }); + + test('should create a method with a body', () { + expect( + new Method((b) => b + ..name = 'foo' + ..body = new Code((b) => b.code = r''' + return 1 + 2; + ''')), + equalsDart(r''' + foo() { + return 1 + 2; + } + '''), + ); + }); + + test('should create a lambda method', () { + expect( + new Method( + (b) => b + ..name = 'foo' + ..lambda = true + ..body = new Code( + (b) => b.code = r''' + 1 + 2 + ''', + ), + ), + equalsDart(r''' + foo() => 1 + 2; + '''), + ); + }); + + test('should create a method with a body with references', () { + final linkedHashMap = const Reference('LinkedHashMap', 'dart:collection'); + expect( + new Method( + (b) => b + ..name = 'foo' + ..body = new Code((b) => b + ..code = r''' + return new {{LINKED_HASH_MAP}}(); + ''' + // Just an example to make it clear this != an actual type. + // + // Can be used to do automatic import prefixing or rewrites. + ..specs.addAll({ + 'LINKED_HASH_MAP': () => linkedHashMap, + })), + ), + equalsDart(r''' + foo() { + return new LinkedHashMap(); + } + '''), + ); + }); + + test('should create a method with a paremter', () { + expect( + new Method( + (b) => b + ..name = 'fib' + ..requiredParameters.add( + new Parameter((b) => b.name = 'i'), + ), + ), + equalsDart(r''' + fib(i); + '''), + ); + }); + + test('should create a method with a paremter with an annotation', () { + expect( + new Method( + (b) => b + ..name = 'fib' + ..requiredParameters.add( + new Parameter((b) => b + ..name = 'i' + ..annotations.add(new Annotation( + (a) => a..code = new Code((b) => b..code = 'deprecated')))), + ), + ), + equalsDart(r''' + fib(@deprecated i); + '''), + ); + }); + + test('should create a method with a parameter with a type', () { + expect( + new Method( + (b) => b + ..name = 'fib' + ..requiredParameters.add( + new Parameter( + (b) => b + ..name = 'i' + ..type = const Reference.localScope('int').toType(), + ), + ), + ), + equalsDart(r''' + fib(int i); + '''), + ); + }); + + test('should create a method with a parameter with a generic type', () { + expect( + new Method( + (b) => b + ..name = 'foo' + ..types.add(new TypeReference((b) => b + ..symbol = 'T' + ..bound = const Reference.localScope('Iterable').toType())) + ..requiredParameters.addAll([ + new Parameter( + (b) => b + ..name = 't' + ..type = const Reference.localScope('T').toType(), + ), + new Parameter((b) => b + ..name = 'x' + ..type = new TypeReference((b) => b + ..symbol = 'X' + ..types.add(const Reference.localScope('T').toType()))), + ]), + ), + equalsDart(r''' + foo(T t, X x); + '''), + ); + }); + + test('should create a method with an optional parameter', () { + expect( + new Method( + (b) => b + ..name = 'fib' + ..optionalParameters.add( + new Parameter((b) => b.name = 'i'), + ), + ), + equalsDart(r''' + fib([i]); + '''), + ); + }); + + test('should create a method with multiple optional parameters', () { + expect( + new Method( + (b) => b + ..name = 'foo' + ..optionalParameters.addAll([ + new Parameter((b) => b.name = 'a'), + new Parameter((b) => b.name = 'b'), + ]), + ), + equalsDart(r''' + foo([a, b]); + '''), + ); + }); + + test('should create a method with an optional parameter with a value', () { + expect( + new Method( + (b) => b + ..name = 'fib' + ..optionalParameters.add( + new Parameter((b) => b + ..name = 'i' + ..defaultTo = new Code((b) => b.code = '0')), + ), + ), + equalsDart(r''' + fib([i = 0]); + '''), + ); + }); + + test('should create a method with a named optional parameter', () { + expect( + new Method( + (b) => b + ..name = 'fib' + ..optionalParameters.add( + new Parameter((b) => b + ..named = true + ..name = 'i'), + ), + ), + equalsDart(r''' + fib({i}); + '''), + ); + }); + + test('should create a method with a named optional parameter with value', () { + expect( + new Method( + (b) => b + ..name = 'fib' + ..optionalParameters.add( + new Parameter((b) => b + ..named = true + ..name = 'i' + ..defaultTo = new Code((b) => b.code = '0')), + ), + ), + equalsDart(r''' + fib({i: 0}); + '''), + ); + }); + + test('should create a method with a mix of parameters', () { + expect( + new Method( + (b) => b + ..name = 'foo' + ..requiredParameters.add( + new Parameter((b) => b..name = 'a'), + ) + ..optionalParameters.add( + new Parameter((b) => b + ..named = true + ..name = 'b'), + ), + ), + equalsDart(r''' + foo(a, {b}); + '''), + ); + }); +} diff --git a/pkgs/code_builder/tool/build.dart b/pkgs/code_builder/tool/build.dart new file mode 100644 index 000000000..350e2f3b6 --- /dev/null +++ b/pkgs/code_builder/tool/build.dart @@ -0,0 +1,20 @@ +// 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 'dart:async'; + +import 'package:build_runner/build_runner.dart'; +import 'package:built_value_generator/built_value_generator.dart'; +import 'package:source_gen/source_gen.dart'; + +Future main() async { + await build( + new PhaseGroup.singleAction( + new GeneratorBuilder([ + new BuiltValueGenerator(), + ]), + new InputSet('code_builder', const ['lib/src/specs/**.dart']), + ), + ); +} diff --git a/pkgs/code_builder/tool/presubmit.sh b/pkgs/code_builder/tool/presubmit.sh deleted file mode 100755 index ba3c275c1..000000000 --- a/pkgs/code_builder/tool/presubmit.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -# Make sure dartfmt is run on everything -# This assumes you have dart_style as a dev_dependency -echo "Checking dartfmt..." -if [ "$TRAVIS_DART_VERSION" = "stable" ]; then - NEEDS_DARTFMT="$(find lib test -name "*.dart" | xargs dartfmt -n)" - if [[ ${NEEDS_DARTFMT} != "" ]] - then - echo "FAILED" - echo "${NEEDS_DARTFMT}" - exit 1 - fi - echo "PASSED" -else - echo "SKIPPED" -fi - -# Make sure we pass the analyzer -echo "Checking dartanalyzer..." -FAILS_ANALYZER="$(find lib test -name "*.dart" | xargs dartanalyzer --options .analysis_options)" -if [[ $FAILS_ANALYZER == *"[error]"* ]] -then - echo "FAILED" - echo "${FAILS_ANALYZER}" - exit 1 -fi -echo "PASSED" - -# Fail on anything that fails going forward. -set -e - -pub run test - -# Install dart_coveralls; gather and send coverage data. -if [ "$COVERALLS_TOKEN" ] && [ "$TRAVIS_DART_VERSION" = "stable" ]; then - pub global activate dart_coveralls - pub global run dart_coveralls report \ - --retry 2 \ - --exclude-test-files \ - tool/test_all_for_coverage.dart -fi diff --git a/pkgs/code_builder/tool/test_all_for_coverage.dart b/pkgs/code_builder/tool/test_all_for_coverage.dart deleted file mode 100644 index 1cd141266..000000000 --- a/pkgs/code_builder/tool/test_all_for_coverage.dart +++ /dev/null @@ -1,33 +0,0 @@ -// 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 '../test/e2e_test.dart' as test_01; -import '../test/scope_test.dart' as test_02; -import '../test/builders/break_test.dart' as test_03; -import '../test/builders/class_test.dart' as test_04; -import '../test/builders/expression_test.dart' as test_05; -import '../test/builders/field_test.dart' as test_06; -import '../test/builders/file_test.dart' as test_07; -import '../test/builders/method_test.dart' as test_08; -import '../test/builders/parameter_test.dart' as test_09; -import '../test/builders/shared_test.dart' as test_10; -import '../test/builders/statement_test.dart' as test_11; -import '../test/builders/switch_test.dart' as test_12; -import '../test/builders/type_test.dart' as test_13; - -void main() { - test_01.main(); - test_02.main(); - test_03.main(); - test_04.main(); - test_05.main(); - test_06.main(); - test_07.main(); - test_08.main(); - test_09.main(); - test_10.main(); - test_11.main(); - test_12.main(); - test_13.main(); -} diff --git a/pkgs/code_builder/tool/watch.dart b/pkgs/code_builder/tool/watch.dart new file mode 100644 index 000000000..c6cee8b57 --- /dev/null +++ b/pkgs/code_builder/tool/watch.dart @@ -0,0 +1,20 @@ +// 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 'dart:async'; + +import 'package:build_runner/build_runner.dart'; +import 'package:built_value_generator/built_value_generator.dart'; +import 'package:source_gen/source_gen.dart'; + +Future main() async { + await watch( + new PhaseGroup.singleAction( + new GeneratorBuilder([ + new BuiltValueGenerator(), + ]), + new InputSet('code_builder', const ['lib/src/specs/**.dart']), + ), + ); +} From ad333a4f99d385bb95a68875acd4a09a88c4ba38 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 12 Jul 2017 10:59:04 -0700 Subject: [PATCH 058/271] More work towards feature parity of 1x (dart-lang/code_builder#116) * WIP. * Finish up feature parity. * Dartfmt. * Address feedback. * Format with dart_style:format for now. * Fix tests. --- pkgs/code_builder/lib/code_builder.dart | 4 + pkgs/code_builder/lib/src/allocator.dart | 95 ++++++++++++++ pkgs/code_builder/lib/src/emitter.dart | 56 +++++++- pkgs/code_builder/lib/src/matchers.dart | 30 +++-- .../code_builder/lib/src/specs/directive.dart | 61 +++++++++ .../lib/src/specs/directive.g.dart | 123 ++++++++++++++++++ pkgs/code_builder/lib/src/specs/file.dart | 37 ++++++ pkgs/code_builder/lib/src/specs/file.g.dart | 108 +++++++++++++++ pkgs/code_builder/lib/src/visitors.dart | 20 +-- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/allocator_test.dart | 49 +++++++ .../code_builder/test/e2e/injection_test.dart | 16 ++- pkgs/code_builder/test/specs/file_test.dart | 64 +++++++++ 13 files changed, 642 insertions(+), 23 deletions(-) create mode 100644 pkgs/code_builder/lib/src/allocator.dart create mode 100644 pkgs/code_builder/lib/src/specs/directive.dart create mode 100644 pkgs/code_builder/lib/src/specs/directive.g.dart create mode 100644 pkgs/code_builder/lib/src/specs/file.dart create mode 100644 pkgs/code_builder/lib/src/specs/file.g.dart create mode 100644 pkgs/code_builder/test/allocator_test.dart create mode 100644 pkgs/code_builder/test/specs/file_test.dart diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 85b644e2c..9cc8374b3 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -2,6 +2,7 @@ // 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. +export 'src/allocator.dart' show Allocator; export 'src/base.dart' show Spec; export 'src/emitter.dart' show DartEmitter; export 'src/matchers.dart' show equalsDart; @@ -9,7 +10,10 @@ export 'src/specs/annotation.dart' show Annotation, AnnotationBuilder; export 'src/specs/class.dart' show Class, ClassBuilder; export 'src/specs/code.dart' show Code, CodeBuilder; export 'src/specs/constructor.dart' show Constructor, ConstructorBuilder; +export 'src/specs/directive.dart' + show Directive, DirectiveType, DirectiveBuilder; export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; +export 'src/specs/file.dart' show File, FileBuilder; export 'src/specs/method.dart' show Method, MethodBuilder, MethodType, Parameter, ParameterBuilder; export 'src/specs/reference.dart' show Reference; diff --git a/pkgs/code_builder/lib/src/allocator.dart b/pkgs/code_builder/lib/src/allocator.dart new file mode 100644 index 000000000..aaf1c6900 --- /dev/null +++ b/pkgs/code_builder/lib/src/allocator.dart @@ -0,0 +1,95 @@ +// 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 'specs/directive.dart'; +import 'specs/reference.dart'; + +/// Collects references and automatically allocates prefixes and imports. +/// +/// `Allocator` takes out the manual work of deciding whether a symbol will +/// clash with other imports in your generated code, or what imports are needed +/// to resolve all symbols in your generated code. +abstract class Allocator { + /// An allocator that does not prefix symbols nor collects imports. + static const Allocator none = const _NullAllocator(); + + /// Creates a new default allocator that applies no prefixing. + factory Allocator() = _Allocator; + + /// Creates a new allocator that applies naive prefixing to avoid conflicts. + /// + /// This implementation is not optimized for any particular code generation + /// style and instead takes a conservative approach of prefixing _every_ + /// import except references to `dart:core` (which are considered always + /// imported). + factory Allocator.simplePrefixing() = _PrefixedAllocator; + + /// Returns a reference string given a [reference] object. + /// + /// For example, a no-op implementation: + /// ```dart + /// allocate(const Reference('List', 'dart:core')); // Returns 'List'. + /// ``` + /// + /// Where-as an implementation that prefixes imports might output: + /// ```dart + /// allocate(const Reference('Foo', 'package:foo')); // Returns '_i1.Foo'. + /// ``` + String allocate(Reference reference); + + /// All imports that have so far been added implicitly via [allocate]. + Iterable get imports; +} + +class _Allocator implements Allocator { + final _imports = new Set(); + + @override + String allocate(Reference reference) { + if (reference.url != null) { + _imports.add(reference.url); + } + return reference.symbol; + } + + @override + Iterable get imports { + return _imports.map((u) => new Directive.import(u)); + } +} + +class _NullAllocator implements Allocator { + const _NullAllocator(); + + @override + String allocate(Reference reference) => reference.symbol; + + @override + Iterable get imports => const []; +} + +class _PrefixedAllocator implements Allocator { + static const _doNotPrefix = const ['dart:core']; + + final _imports = {}; + var _keys = 1; + + @override + String allocate(Reference reference) { + final symbol = reference.symbol; + if (reference.url == null || _doNotPrefix.contains(reference.url)) { + return symbol; + } + return '_${_imports.putIfAbsent(reference.url, _nextKey)}.$symbol'; + } + + int _nextKey() => _keys++; + + @override + Iterable get imports { + return _imports.keys.map( + (u) => new Directive.import(u, as: '_${_imports[u]}'), + ); + } +} diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 9de6f7f0d..f9b2862b8 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -2,18 +2,30 @@ // 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 'allocator.dart'; +import 'base.dart'; import 'specs/annotation.dart'; import 'specs/class.dart'; import 'specs/code.dart'; import 'specs/constructor.dart'; +import 'specs/directive.dart'; import 'specs/field.dart'; +import 'specs/file.dart'; import 'specs/method.dart'; import 'specs/reference.dart'; import 'specs/type_reference.dart'; import 'visitors.dart'; -class DartEmitter extends GeneralizingSpecVisitor { - const DartEmitter(); +class DartEmitter implements SpecVisitor { + final Allocator _allocator; + + /// Creates a new instance of [DartEmitter]. + /// + /// May specify an [Allocator] to use for symbols, otherwise uses a no-op. + const DartEmitter([this._allocator = Allocator.none]); + + /// Creates a new instance of [DartEmitter] with a default [Allocator]. + factory DartEmitter.scoped() => new DartEmitter(new Allocator()); @override visitAnnotation(Annotation spec, [StringSink output]) { @@ -154,6 +166,22 @@ class DartEmitter extends GeneralizingSpecVisitor { return output..write(code); } + @override + visitDirective(Directive spec, [StringSink output]) { + output ??= new StringBuffer(); + if (spec.type == DirectiveType.import) { + output.write('import '); + } else { + output.write('export '); + } + output.write("'${spec.url}'"); + if (spec.as != null) { + output.write(' as ${spec.as}'); + } + output.write(';'); + return output; + } + @override visitField(Field spec, [StringSink output]) { output ??= new StringBuffer(); @@ -188,6 +216,25 @@ class DartEmitter extends GeneralizingSpecVisitor { return output; } + @override + visitFile(File spec, [StringSink output]) { + output ??= new StringBuffer(); + // Process the body first in order to prime the allocators. + final body = new StringBuffer(); + for (final spec in spec.body) { + body.write(visitSpec(spec)); + } + // TODO: Allow some sort of logical ordering. + for (final directive in spec.directives) { + visitDirective(directive, output); + } + for (final directive in _allocator.imports) { + visitDirective(directive, output); + } + output.write(body); + return output; + } + @override visitMethod(Method spec, [StringSink output]) { output ??= new StringBuffer(); @@ -293,9 +340,12 @@ class DartEmitter extends GeneralizingSpecVisitor { @override visitReference(Reference spec, [StringSink output]) { - return (output ??= new StringBuffer())..write(spec.symbol); + return (output ??= new StringBuffer())..write(_allocator.allocate(spec)); } + @override + visitSpec(Spec spec) => spec.accept(this); + @override visitType(TypeReference spec, [StringSink output]) { output ??= new StringBuffer(); diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index d0849094a..9a698643c 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -22,16 +22,21 @@ String _dartfmt(String source) { } /// Encodes [spec] as Dart source code. -String _dart(Spec spec) => - _dartfmt(spec.accept(const DartEmitter()).toString()); +String _dart(Spec spec, DartEmitter emitter) => + _dartfmt(spec.accept(emitter).toString()).trim(); /// Returns a matcher for Dart source code. -Matcher equalsDart(String source) => new _EqualsDart(_dartfmt(source)); +Matcher equalsDart( + String source, [ + DartEmitter emitter = const DartEmitter(), +]) => + new _EqualsDart(_dartfmt(source).trim(), emitter); class _EqualsDart extends Matcher { + final DartEmitter _emitter; final String _source; - const _EqualsDart(this._source); + const _EqualsDart(this._source, this._emitter); @override Description describe(Description description) => description.add(_source); @@ -40,11 +45,18 @@ class _EqualsDart extends Matcher { Description describeMismatch( covariant Spec item, Description mismatchDescription, - _, - __, - ) => - mismatchDescription.add(_dart(item)); + state, + verbose, + ) { + final result = _dart(item, _emitter); + return equals(result).describeMismatch( + _source, + mismatchDescription, + state, + verbose, + ); + } @override - bool matches(covariant Spec item, _) => _dart(item) == _source; + bool matches(covariant Spec item, _) => _dart(item, _emitter) == _source; } diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart new file mode 100644 index 000000000..afda656ca --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -0,0 +1,61 @@ +// 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. + +library code_builder.src.specs.directive; + +import 'package:built_value/built_value.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../visitors.dart'; + +part 'directive.g.dart'; + +@immutable +abstract class Directive implements Built, Spec { + factory Directive([void updates(DirectiveBuilder b)]) = _$Directive; + + factory Directive.import( + String url, { + String as, + }) => + new Directive((builder) => builder + ..as = as + ..type = DirectiveType.import + ..url = url); + + factory Directive.export(String url) => new Directive((builder) => builder + ..type = DirectiveType.export + ..url = url); + + Directive._(); + + @nullable + String get as; + + String get url; + + DirectiveType get type; + + @override + R accept(SpecVisitor visitor) => visitor.visitDirective(this); +} + +abstract class DirectiveBuilder + implements Builder { + factory DirectiveBuilder() = _$DirectiveBuilder; + + DirectiveBuilder._(); + + String as; + + String url; + + DirectiveType type; +} + +enum DirectiveType { + import, + export, +} diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart new file mode 100644 index 000000000..166c59407 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -0,0 +1,123 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.directive; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// Target: abstract class Directive +// ************************************************************************** + +class _$Directive extends Directive { + @override + final String as; + @override + final String url; + @override + final DirectiveType type; + + factory _$Directive([void updates(DirectiveBuilder b)]) => + (new DirectiveBuilder()..update(updates)).build() as _$Directive; + + _$Directive._({this.as, this.url, this.type}) : super._() { + if (url == null) throw new ArgumentError.notNull('url'); + if (type == null) throw new ArgumentError.notNull('type'); + } + + @override + Directive rebuild(void updates(DirectiveBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$DirectiveBuilder toBuilder() => new _$DirectiveBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! Directive) return false; + return as == other.as && url == other.url && type == other.type; + } + + @override + int get hashCode { + return $jf($jc($jc($jc(0, as.hashCode), url.hashCode), type.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Directive') + ..add('as', as) + ..add('url', url) + ..add('type', type)) + .toString(); + } +} + +class _$DirectiveBuilder extends DirectiveBuilder { + _$Directive _$v; + + @override + String get as { + _$this; + return super.as; + } + + @override + set as(String as) { + _$this; + super.as = as; + } + + @override + String get url { + _$this; + return super.url; + } + + @override + set url(String url) { + _$this; + super.url = url; + } + + @override + DirectiveType get type { + _$this; + return super.type; + } + + @override + set type(DirectiveType type) { + _$this; + super.type = type; + } + + _$DirectiveBuilder() : super._(); + + DirectiveBuilder get _$this { + if (_$v != null) { + super.as = _$v.as; + super.url = _$v.url; + super.type = _$v.type; + _$v = null; + } + return this; + } + + @override + void replace(Directive other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$Directive; + } + + @override + void update(void updates(DirectiveBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$Directive build() { + final result = _$v ?? new _$Directive._(as: as, url: url, type: type); + replace(result); + return result; + } +} diff --git a/pkgs/code_builder/lib/src/specs/file.dart b/pkgs/code_builder/lib/src/specs/file.dart new file mode 100644 index 000000000..98f26e54e --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/file.dart @@ -0,0 +1,37 @@ +// 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. + +library code_builder.src.specs.library; + +import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../visitors.dart'; +import 'directive.dart'; + +part 'file.g.dart'; + +@immutable +abstract class File implements Built, Spec { + factory File([void updates(FileBuilder b)]) = _$File; + + File._(); + + BuiltList get directives; + BuiltList get body; + + @override + R accept(SpecVisitor visitor) => visitor.visitFile(this); +} + +abstract class FileBuilder implements Builder { + factory FileBuilder() = _$FileBuilder; + + FileBuilder._(); + + ListBuilder directives = new ListBuilder(); + ListBuilder body = new ListBuilder(); +} diff --git a/pkgs/code_builder/lib/src/specs/file.g.dart b/pkgs/code_builder/lib/src/specs/file.g.dart new file mode 100644 index 000000000..700918956 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/file.g.dart @@ -0,0 +1,108 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.library; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// Target: abstract class File +// ************************************************************************** + +class _$File extends File { + @override + final BuiltList directives; + @override + final BuiltList body; + + factory _$File([void updates(FileBuilder b)]) => + (new FileBuilder()..update(updates)).build() as _$File; + + _$File._({this.directives, this.body}) : super._() { + if (directives == null) throw new ArgumentError.notNull('directives'); + if (body == null) throw new ArgumentError.notNull('body'); + } + + @override + File rebuild(void updates(FileBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$FileBuilder toBuilder() => new _$FileBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! File) return false; + return directives == other.directives && body == other.body; + } + + @override + int get hashCode { + return $jf($jc($jc(0, directives.hashCode), body.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('File') + ..add('directives', directives) + ..add('body', body)) + .toString(); + } +} + +class _$FileBuilder extends FileBuilder { + _$File _$v; + + @override + ListBuilder get directives { + _$this; + return super.directives ??= new ListBuilder(); + } + + @override + set directives(ListBuilder directives) { + _$this; + super.directives = directives; + } + + @override + ListBuilder get body { + _$this; + return super.body ??= new ListBuilder(); + } + + @override + set body(ListBuilder body) { + _$this; + super.body = body; + } + + _$FileBuilder() : super._(); + + FileBuilder get _$this { + if (_$v != null) { + super.directives = _$v.directives?.toBuilder(); + super.body = _$v.body?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(File other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$File; + } + + @override + void update(void updates(FileBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$File build() { + final result = _$v ?? + new _$File._(directives: directives?.build(), body: body?.build()); + replace(result); + return result; + } +} diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 2af0e66be..dcde2babc 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -7,7 +7,9 @@ import 'specs/annotation.dart'; import 'specs/class.dart'; import 'specs/code.dart'; import 'specs/constructor.dart'; +import 'specs/directive.dart'; import 'specs/field.dart'; +import 'specs/file.dart'; import 'specs/method.dart'; import 'specs/reference.dart'; import 'specs/type_reference.dart'; @@ -23,8 +25,12 @@ abstract class SpecVisitor { T visitConstructor(Constructor spec, String clazz); + T visitDirective(Directive spec); + T visitField(Field spec); + T visitFile(File spec); + T visitMethod(Method spec); T visitReference(Reference spec); @@ -51,9 +57,15 @@ class SimpleSpecVisitor implements SpecVisitor { @override T visitCode(Code spec) => null; + @override + T visitDirective(Directive spec) => null; + @override T visitField(Field spec) => null; + @override + T visitFile(File spec) => null; + @override T visitMethod(Method spec) => null; @@ -69,11 +81,3 @@ class SimpleSpecVisitor implements SpecVisitor { @override T visitTypeParameters(Iterable specs) => null; } - -class RecursiveSpecVisitor extends SimpleSpecVisitor { - const RecursiveSpecVisitor(); -} - -class GeneralizingSpecVisitor extends RecursiveSpecVisitor { - const GeneralizingSpecVisitor(); -} diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index afc6135ad..85c82746c 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -15,6 +15,6 @@ dependencies: dev_dependencies: build_runner: ^0.3.0 - built_value_generator: ^1.0.0 + built_value_generator: '>=1.0.0 <=1.1.4' dart_style: ^1.0.0 test: ^0.12.0 diff --git a/pkgs/code_builder/test/allocator_test.dart b/pkgs/code_builder/test/allocator_test.dart new file mode 100644 index 000000000..f800d872b --- /dev/null +++ b/pkgs/code_builder/test/allocator_test.dart @@ -0,0 +1,49 @@ +// 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:test/test.dart'; + +void main() { + group('Allocator', () { + Allocator allocator; + + test('should return the exact (non-prefixed) symbol', () { + allocator = new Allocator(); + expect(allocator.allocate(const Reference('Foo', 'package:foo')), 'Foo'); + }); + + test('should collect import URLs', () { + allocator = new Allocator() + ..allocate(const Reference('List', 'dart:core')) + ..allocate(const Reference('LinkedHashMap', 'dart:collection')) + ..allocate(const Reference.localScope('someSymbol')); + expect(allocator.imports.map((d) => d.url), [ + 'dart:core', + 'dart:collection', + ]); + }); + + test('.none should do nothing', () { + allocator = Allocator.none; + expect(allocator.allocate(const Reference('Foo', 'package:foo')), 'Foo'); + expect(allocator.imports, isEmpty); + }); + + test('.simplePrefixing should add import prefixes', () { + allocator = new Allocator.simplePrefixing(); + expect( + allocator.allocate(const Reference('List', 'dart:core')), + 'List', + ); + expect( + allocator.allocate(const Reference('LinkedHashMap', 'dart:collection')), + '_1.LinkedHashMap', + ); + expect(allocator.imports.map((d) => '${d.url} as ${d.as}'), [ + 'dart:collection as _1', + ]); + }); + }); +} diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index 807d7925e..7cb40b86f 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -9,8 +9,8 @@ void main() { test('should generate a complex generated file', () { // Imports from an existing Dart library. final $App = const Reference('App', 'package:app/app.dart'); - final $Module = const Reference('Module', 'package:app/app.dart'); - final $Thing = const Reference('Thing', 'package:app/app.dart'); + final $Module = const Reference('Module', 'package:app/module.dart'); + final $Thing = const Reference('Thing', 'package:app/thing.dart'); final clazz = new ClassBuilder() ..name = 'Injector' @@ -44,5 +44,17 @@ void main() { } '''), ); + + expect( + clazz.build(), + equalsDart(r''' + class Injector implements _1.App { + Injector(this._module); + final _2.Module _module; + @override + _3.Thing getThing() => new _3.Thing(_module.get1(), _module.get2()); + } + ''', new DartEmitter(new Allocator.simplePrefixing())), + ); }); } diff --git a/pkgs/code_builder/test/specs/file_test.dart b/pkgs/code_builder/test/specs/file_test.dart new file mode 100644 index 000000000..070ee186d --- /dev/null +++ b/pkgs/code_builder/test/specs/file_test.dart @@ -0,0 +1,64 @@ +// 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:test/test.dart'; + +void main() { + group('File', () { + const $linkedHashMap = const Reference('LinkedHashMap', 'dart:collection'); + + test('should emit a source file with manual imports', () { + expect( + new File((b) => b + ..directives.add(new Directive.import('dart:collection')) + ..body.add(new Field((b) => b + ..name = 'test' + ..modifier = FieldModifier.final$ + ..assignment = new Code((b) => b + ..code = 'new {{LinkedHashMap}}()' + ..specs.addAll({'LinkedHashMap': () => $linkedHashMap}))))), + equalsDart(r''' + import 'dart:collection'; + + final test = new LinkedHashMap(); + ''', const DartEmitter()), + ); + }); + + test('should emit a source file with allocation', () { + expect( + new File((b) => b + ..body.add(new Field((b) => b + ..name = 'test' + ..modifier = FieldModifier.final$ + ..assignment = new Code((b) => b + ..code = 'new {{LinkedHashMap}}()' + ..specs.addAll({'LinkedHashMap': () => $linkedHashMap}))))), + equalsDart(r''' + import 'dart:collection'; + + final test = new LinkedHashMap(); + ''', new DartEmitter.scoped()), + ); + }); + + test('should emit a source file with allocation + prefixing', () { + expect( + new File((b) => b + ..body.add(new Field((b) => b + ..name = 'test' + ..modifier = FieldModifier.final$ + ..assignment = new Code((b) => b + ..code = 'new {{LinkedHashMap}}()' + ..specs.addAll({'LinkedHashMap': () => $linkedHashMap}))))), + equalsDart(r''' + import 'dart:collection' as _1; + + final test = new _1.LinkedHashMap(); + ''', new DartEmitter(new Allocator.simplePrefixing())), + ); + }); + }); +} From cbc9e6b895442514d32aac91d009b3909f5a8b52 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 14 Jul 2017 12:28:06 -0700 Subject: [PATCH 059/271] Prepare to publish 2.0.0-alpha (dart-lang/code_builder#118) --- pkgs/code_builder/CHANGELOG.md | 6 ++ pkgs/code_builder/README.md | 78 ++++++++++++++++++- pkgs/code_builder/example/animal.dart | 18 +++++ pkgs/code_builder/example/scope.dart | 21 +++++ pkgs/code_builder/lib/src/specs/method.dart | 11 +++ pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/method_test.dart | 9 +++ 7 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 pkgs/code_builder/example/animal.dart create mode 100644 pkgs/code_builder/example/scope.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 07dbf73c8..de5c639ea 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,9 @@ +## 2.0.0-alpha + +* Complete re-write to not use `package:analyzer`. +* Code generation now properly uses the _builder_ pattern (via `built_value`). +* See examples and tests for details. + ## 1.0.4 * Added `isInstanceOf` to `ExpressionBuilder`, which performs an `is` check: diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 54b9533b6..4152d616c 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -6,7 +6,79 @@ `code_builder` is a fluent Dart API for generating valid Dart source code. -**Experimental Branch for _2.0_**: -- Drops use of the `package:analyzer` API. -- Uses a proper [builder pattern](https://github.com/square/javapoet). +## Contributing +* Read and help us document common patterns over [at the wiki][wiki]. +* Is there a *bug* in the code? [File an issue][issue]. + +If a feature is missing (the Dart language is always evolving) or you'd like an +easier or better way to do something, consider [opening a pull request][pull]. +You can always [file an issue][issue], but generally speaking feature requests +will be on a best-effort basis. + +[wiki]: https://github.com/dart-lang/code_builder/wiki +[issue]: https://github.com/dart-lang/code_builder/issues +[pull]: https://github.com/dart-lang/code_builder/pulls + +## Usage + +`code_builder` has a narrow and user-friendly API. + +For example creating a class with a method: + +```dart +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 = const Reference.localScope('Organism').toType() + ..methods.add(new Method.returnsVoid((b) => b + ..name = 'eat' + ..lambda = true + ..body = new Code((b) => b..code = 'print(\'Yum\')')))); + final emitter = const DartEmitter(); + print(new DartFormatter().format('${animal.accept(emitter)}')); +} +``` + +Outputs: +```dart +class Animal extends Organism { + void eat() => print('Yum!'); +} +``` + +Have a complicated set of dependencies for your generated code? +`code_builder` supports automatic scoping of your ASTs to automatically +use prefixes to avoid symbol conflicts: + +```dart +import 'package:code_builder/code_builder.dart'; +import 'package:dart_style/dart_style.dart'; + +void main() { + final library = new File((b) => b.body.addAll([ + new Method((b) => b + ..body = new Code((b) => b.code = '') + ..name = 'doThing' + ..returns = const Reference('Thing', 'package:a/a.dart').toType()), + new Method((b) => b + ..body = new Code((b) => b..code = '') + ..name = 'doOther' + ..returns = const Reference('Other', 'package:b/b.dart').toType()), + ])); + final emitter = new DartEmitter(new Allocator.simplePrefixing()); + print(new DartFormatter().format('${library.accept(emitter)}')); +} +``` + +Outputs: +```dart +import 'package:a/a.dart' as _1; +import 'package:b/b.dart' as _2; + +_1.Thing doThing() {} +_2.Other doOther() {} +``` \ No newline at end of file diff --git a/pkgs/code_builder/example/animal.dart b/pkgs/code_builder/example/animal.dart new file mode 100644 index 000000000..057ba4d46 --- /dev/null +++ b/pkgs/code_builder/example/animal.dart @@ -0,0 +1,18 @@ +// 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 = const Reference.localScope('Organism').toType() + ..methods.add(new Method.returnsVoid((b) => b + ..name = 'eat' + ..lambda = true + ..body = new Code((b) => b..code = 'print(\'Yum\')')))); + final emitter = const DartEmitter(); + print(new DartFormatter().format('${animal.accept(emitter)}')); +} diff --git a/pkgs/code_builder/example/scope.dart b/pkgs/code_builder/example/scope.dart new file mode 100644 index 000000000..2b9c2709b --- /dev/null +++ b/pkgs/code_builder/example/scope.dart @@ -0,0 +1,21 @@ +// 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 library = new File((b) => b.body.addAll([ + new Method((b) => b + ..body = new Code((b) => b.code = '') + ..name = 'doThing' + ..returns = const Reference('Thing', 'package:a/a.dart').toType()), + new Method((b) => b + ..body = new Code((b) => b..code = '') + ..name = 'doOther' + ..returns = const Reference('Other', 'package:b/b.dart').toType()), + ])); + final emitter = new DartEmitter(new Allocator.simplePrefixing()); + print(new DartFormatter().format('${library.accept(emitter)}')); +} diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 40455ac04..248f4f979 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -20,12 +20,23 @@ import 'type_reference.dart'; part 'method.g.dart'; +final TypeReference _$void = const Reference.localScope('void').toType(); + @immutable abstract class Method extends Object with HasAnnotations, HasGenerics, HasDartDocs implements Built, Reference, Spec { factory Method([void updates(MethodBuilder b)]) = _$Method; + factory Method.returnsVoid([void updates(MethodBuilder b)]) { + return new Method((b) { + if (updates != null) { + updates(b); + } + b.returns = _$void; + }); + } + Method._(); @override diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 85c82746c..8b7fa5c3d 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.0.0-dev +version: 2.0.0-alpha description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 01d122e81..9679d5b05 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -51,6 +51,15 @@ void main() { ); }); + test('should create a method with a void return type', () { + expect( + new Method.returnsVoid((b) => b..name = 'foo'), + equalsDart(r''' + void foo(); + '''), + ); + }); + test('should create a method with generic types', () { expect( new Method((b) => b From 1cf0bdac2a562357a0264fff63cf4cd46e53a08d Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 14 Jul 2017 14:22:16 -0700 Subject: [PATCH 060/271] Use Reference instead of TypeReference. (dart-lang/code_builder#121) * Use Reference instead of TypeReference. * Test in dart2js. * Update README. * Fix travis. * Remove chrome. --- pkgs/code_builder/.travis.yml | 5 ++ pkgs/code_builder/CHANGELOG.md | 21 ++++++++ pkgs/code_builder/README.md | 6 +-- pkgs/code_builder/example/animal.dart | 2 +- pkgs/code_builder/example/scope.dart | 4 +- pkgs/code_builder/lib/src/emitter.dart | 22 ++++---- .../code_builder/lib/src/mixins/generics.dart | 6 +-- pkgs/code_builder/lib/src/specs/class.dart | 52 ++++--------------- pkgs/code_builder/lib/src/specs/class.g.dart | 30 +++++------ pkgs/code_builder/lib/src/specs/field.dart | 4 +- pkgs/code_builder/lib/src/specs/field.g.dart | 6 +-- pkgs/code_builder/lib/src/specs/method.dart | 18 +++---- pkgs/code_builder/lib/src/specs/method.g.dart | 28 +++++----- .../code_builder/lib/src/specs/reference.dart | 5 +- .../lib/src/specs/type_reference.dart | 8 +-- .../lib/src/specs/type_reference.g.dart | 14 ++--- pkgs/code_builder/pubspec.yaml | 11 ++-- pkgs/code_builder/test/allocator_test.dart | 2 +- .../code_builder/test/e2e/injection_test.dart | 4 +- pkgs/code_builder/test/specs/class_test.dart | 12 ++--- pkgs/code_builder/test/specs/field_test.dart | 2 +- pkgs/code_builder/test/specs/method_test.dart | 12 ++--- pkgs/code_builder/tool/build.dart | 1 + pkgs/code_builder/tool/watch.dart | 1 + 24 files changed, 139 insertions(+), 137 deletions(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index 363e12b64..a391ab1ba 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -6,6 +6,11 @@ cache: directories: - $HOME/.pub-cache +# TODO: Use chrome in --headless mode once supported by pub run test. +dist: trusty +addons: + chrome: stable + branches: only: [master, v2] diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index de5c639ea..d4a417d5a 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,24 @@ +## 2.0.0-alpha+1 + +* Removed `Reference.localScope`. Just use `Reference(symbol)` now. +* Allow `Reference` instead of an explicit `TypeReference` in most APIs. + * `toType()` is performed for you as part the emitter process + +```dart +final 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\')')))); +``` + +* We now support the Dart 2.0 pre-release SDKs (`<2.0.0-dev.infinity`) +* Removed the ability to treat `Class` as a `TypeReference`. + * Was required for compilation to `dart2js`, which is now tested on travis. + ## 2.0.0-alpha * Complete re-write to not use `package:analyzer`. diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 4152d616c..e8581f865 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -33,7 +33,7 @@ import 'package:dart_style/dart_style.dart'; void main() { final animal = new Class((b) => b ..name = 'Animal' - ..extend = const Reference.localScope('Organism').toType() + ..extend = const Reference('Organism').toType() ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' ..lambda = true @@ -63,11 +63,11 @@ void main() { new Method((b) => b ..body = new Code((b) => b.code = '') ..name = 'doThing' - ..returns = const Reference('Thing', 'package:a/a.dart').toType()), + ..returns = const Reference('Thing', 'package:a/a.dart')), new Method((b) => b ..body = new Code((b) => b..code = '') ..name = 'doOther' - ..returns = const Reference('Other', 'package:b/b.dart').toType()), + ..returns = const Reference('Other', 'package:b/b.dart')), ])); final emitter = new DartEmitter(new Allocator.simplePrefixing()); print(new DartFormatter().format('${library.accept(emitter)}')); diff --git a/pkgs/code_builder/example/animal.dart b/pkgs/code_builder/example/animal.dart index 057ba4d46..9030e4e84 100644 --- a/pkgs/code_builder/example/animal.dart +++ b/pkgs/code_builder/example/animal.dart @@ -8,7 +8,7 @@ import 'package:dart_style/dart_style.dart'; void main() { final animal = new Class((b) => b ..name = 'Animal' - ..extend = const Reference.localScope('Organism').toType() + ..extend = const Reference('Organism') ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' ..lambda = true diff --git a/pkgs/code_builder/example/scope.dart b/pkgs/code_builder/example/scope.dart index 2b9c2709b..ee0e9f557 100644 --- a/pkgs/code_builder/example/scope.dart +++ b/pkgs/code_builder/example/scope.dart @@ -10,11 +10,11 @@ void main() { new Method((b) => b ..body = new Code((b) => b.code = '') ..name = 'doThing' - ..returns = const Reference('Thing', 'package:a/a.dart').toType()), + ..returns = const Reference('Thing', 'package:a/a.dart')), new Method((b) => b ..body = new Code((b) => b..code = '') ..name = 'doOther' - ..returns = const Reference('Other', 'package:b/b.dart').toType()), + ..returns = const Reference('Other', 'package:b/b.dart')), ])); final emitter = new DartEmitter(new Allocator.simplePrefixing()); print(new DartFormatter().format('${library.accept(emitter)}')); diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index f9b2862b8..8d76e8e8d 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -44,20 +44,22 @@ class DartEmitter implements SpecVisitor { output.write('abstract '); } output.write('class ${spec.name}'); - visitTypeParameters(spec.types, output); + visitTypeParameters(spec.types.map((r) => r.toType()), output); if (spec.extend != null) { output.write(' extends '); - visitType(spec.extend, output); + visitType(spec.extend.toType(), output); } if (spec.mixins.isNotEmpty) { output ..write(' with ') - ..writeAll(spec.mixins.map(visitType), ','); + ..writeAll( + spec.mixins.map((m) => visitType(m.toType())), ','); } if (spec.implements.isNotEmpty) { output ..write(' implements ') - ..writeAll(spec.implements.map(visitType), ','); + ..writeAll( + spec.implements.map((m) => visitType(m.toType())), ','); } output.write(' {'); spec.constructors.forEach((c) => visitConstructor(c, spec.name, output)); @@ -204,7 +206,7 @@ class DartEmitter implements SpecVisitor { break; } if (spec.type != null) { - visitType(spec.type, output); + visitType(spec.type.toType(), output); output.write(' '); } output.write(spec.name); @@ -247,7 +249,7 @@ class DartEmitter implements SpecVisitor { output.write('static '); } if (spec.returns != null) { - visitType(spec.returns, output); + visitType(spec.returns.toType(), output); output.write(' '); } if (spec.type == MethodType.getter) { @@ -257,7 +259,7 @@ class DartEmitter implements SpecVisitor { output.write('set '); } output.write(spec.name); - visitTypeParameters(spec.types, output); + visitTypeParameters(spec.types.map((r) => r.toType()), output); output.write('('); if (spec.requiredParameters.isNotEmpty) { var count = 0; @@ -321,7 +323,7 @@ class DartEmitter implements SpecVisitor { spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); if (spec.type != null) { - visitType(spec.type, output); + visitType(spec.type.toType(), output); output.write(' '); } if (spec.toThis) { @@ -352,9 +354,9 @@ class DartEmitter implements SpecVisitor { visitReference(spec, output); if (spec.bound != null) { output.write(' extends '); - visitType(spec.bound, output); + visitType(spec.bound.toType(), output); } - visitTypeParameters(spec.types, output); + visitTypeParameters(spec.types.map((r) => r.toType()), output); return output; } diff --git a/pkgs/code_builder/lib/src/mixins/generics.dart b/pkgs/code_builder/lib/src/mixins/generics.dart index aff26e1c9..04a049e3f 100644 --- a/pkgs/code_builder/lib/src/mixins/generics.dart +++ b/pkgs/code_builder/lib/src/mixins/generics.dart @@ -4,14 +4,14 @@ import 'package:built_collection/built_collection.dart'; -import '../specs/type_reference.dart'; +import '../specs/reference.dart'; abstract class HasGenerics { /// Generic type parameters. - BuiltList get types; + BuiltList get types; } abstract class HasGenericsBuilder { /// Generic type parameters. - ListBuilder types; + ListBuilder types; } diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart index 567d235c5..dcc350b28 100644 --- a/pkgs/code_builder/lib/src/specs/class.dart +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -17,14 +17,14 @@ import 'annotation.dart'; import 'constructor.dart'; import 'field.dart'; import 'method.dart'; -import 'type_reference.dart'; +import 'reference.dart'; part 'class.g.dart'; @immutable abstract class Class extends Object with HasAnnotations, HasDartDocs, HasGenerics - implements Built, TypeReference, Spec { + implements Built, Spec { factory Class([void updates(ClassBuilder b)]) = _$Class; Class._(); @@ -39,14 +39,14 @@ abstract class Class extends Object BuiltList get docs; @nullable - TypeReference get extend; + Reference get extend; - BuiltList get implements; + BuiltList get implements; - BuiltList get mixins; + BuiltList get mixins; @override - BuiltList get types; + BuiltList get types; BuiltList get constructors; BuiltList get methods; @@ -55,25 +55,13 @@ abstract class Class extends Object /// Name of the class. String get name; - @override - TypeReference get bound => null; - - @override - String get url => null; - - @override - String get symbol => name; - @override R accept(SpecVisitor visitor) => visitor.visitClass(this); - - @override - TypeReference toType() => this; } abstract class ClassBuilder extends Object with HasAnnotationsBuilder, HasDartDocsBuilder, HasGenericsBuilder - implements Builder, TypeReferenceBuilder { + implements Builder { factory ClassBuilder() = _$ClassBuilder; ClassBuilder._(); @@ -87,13 +75,13 @@ abstract class ClassBuilder extends Object @override ListBuilder docs = new ListBuilder(); - TypeReference extend; + Reference extend; - ListBuilder implements = new ListBuilder(); - ListBuilder mixins = new ListBuilder(); + ListBuilder implements = new ListBuilder(); + ListBuilder mixins = new ListBuilder(); @override - ListBuilder types = new ListBuilder(); + ListBuilder types = new ListBuilder(); ListBuilder constructors = new ListBuilder(); ListBuilder methods = new ListBuilder(); @@ -101,22 +89,4 @@ abstract class ClassBuilder extends Object /// Name of the class. String name; - - @override - TypeReference get bound => null; - - @override - set bound(TypeReference bound) => throw new UnsupportedError(''); - - @override - String get url => null; - - @override - set url(String url) => throw new UnsupportedError(''); - - @override - set symbol(String symbol) => name = symbol; - - @override - String get symbol => name; } diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index 8a6099663..8edbcc630 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -15,13 +15,13 @@ class _$Class extends Class { @override final BuiltList docs; @override - final TypeReference extend; + final Reference extend; @override - final BuiltList implements; + final BuiltList implements; @override - final BuiltList mixins; + final BuiltList mixins; @override - final BuiltList types; + final BuiltList types; @override final BuiltList constructors; @override @@ -165,49 +165,49 @@ class _$ClassBuilder extends ClassBuilder { } @override - TypeReference get extend { + Reference get extend { _$this; return super.extend; } @override - set extend(TypeReference extend) { + set extend(Reference extend) { _$this; super.extend = extend; } @override - ListBuilder get implements { + ListBuilder get implements { _$this; - return super.implements ??= new ListBuilder(); + return super.implements ??= new ListBuilder(); } @override - set implements(ListBuilder implements) { + set implements(ListBuilder implements) { _$this; super.implements = implements; } @override - ListBuilder get mixins { + ListBuilder get mixins { _$this; - return super.mixins ??= new ListBuilder(); + return super.mixins ??= new ListBuilder(); } @override - set mixins(ListBuilder mixins) { + set mixins(ListBuilder mixins) { _$this; super.mixins = mixins; } @override - ListBuilder get types { + ListBuilder get types { _$this; - return super.types ??= new ListBuilder(); + return super.types ??= new ListBuilder(); } @override - set types(ListBuilder types) { + set types(ListBuilder types) { _$this; super.types = types; } diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index 30ce0f4d9..f03c3d7d7 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -46,7 +46,7 @@ abstract class Field extends Object String get name; @nullable - TypeReference get type; + Reference get type; FieldModifier get modifier; @@ -93,7 +93,7 @@ abstract class FieldBuilder extends Object /// Name of the field. String name; - TypeReference type; + Reference type; FieldModifier modifier = FieldModifier.var$; } diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 355746bd2..d3dde8485 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -19,7 +19,7 @@ class _$Field extends Field { @override final String name; @override - final TypeReference type; + final Reference type; @override final FieldModifier modifier; @@ -154,13 +154,13 @@ class _$FieldBuilder extends FieldBuilder { } @override - TypeReference get type { + Reference get type { _$this; return super.type; } @override - set type(TypeReference type) { + set type(Reference type) { _$this; super.type = type; } diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 248f4f979..f51966d73 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -20,7 +20,7 @@ import 'type_reference.dart'; part 'method.g.dart'; -final TypeReference _$void = const Reference.localScope('void').toType(); +final Reference _$void = const Reference('void'); @immutable abstract class Method extends Object @@ -46,7 +46,7 @@ abstract class Method extends Object BuiltList get docs; @override - BuiltList get types; + BuiltList get types; /// Optional parameters. BuiltList get optionalParameters; @@ -77,7 +77,7 @@ abstract class Method extends Object MethodType get type; @nullable - TypeReference get returns; + Reference get returns; @override String get symbol => name; @@ -106,7 +106,7 @@ abstract class MethodBuilder extends Object ListBuilder docs = new ListBuilder(); @override - ListBuilder types = new ListBuilder(); + ListBuilder types = new ListBuilder(); /// Optional parameters. ListBuilder optionalParameters = new ListBuilder(); @@ -134,7 +134,7 @@ abstract class MethodBuilder extends Object /// Whether this is a getter or setter. MethodType type; - TypeReference returns; + Reference returns; } enum MethodType { @@ -171,11 +171,11 @@ abstract class Parameter extends Object BuiltList get docs; @override - BuiltList get types; + BuiltList get types; /// Type of the parameter; @nullable - TypeReference get type; + Reference get type; } abstract class ParameterBuilder extends Object @@ -206,8 +206,8 @@ abstract class ParameterBuilder extends Object ListBuilder docs = new ListBuilder(); @override - ListBuilder types = new ListBuilder(); + ListBuilder types = new ListBuilder(); /// Type of the parameter; - TypeReference type; + Reference type; } diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index a4262740d..b7a0f59a3 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -13,7 +13,7 @@ class _$Method extends Method { @override final BuiltList docs; @override - final BuiltList types; + final BuiltList types; @override final BuiltList optionalParameters; @override @@ -31,7 +31,7 @@ class _$Method extends Method { @override final MethodType type; @override - final TypeReference returns; + final Reference returns; factory _$Method([void updates(MethodBuilder b)]) => (new MethodBuilder()..update(updates)).build() as _$Method; @@ -161,13 +161,13 @@ class _$MethodBuilder extends MethodBuilder { } @override - ListBuilder get types { + ListBuilder get types { _$this; - return super.types ??= new ListBuilder(); + return super.types ??= new ListBuilder(); } @override - set types(ListBuilder types) { + set types(ListBuilder types) { _$this; super.types = types; } @@ -269,13 +269,13 @@ class _$MethodBuilder extends MethodBuilder { } @override - TypeReference get returns { + Reference get returns { _$this; return super.returns; } @override - set returns(TypeReference returns) { + set returns(Reference returns) { _$this; super.returns = returns; } @@ -352,9 +352,9 @@ class _$Parameter extends Parameter { @override final BuiltList docs; @override - final BuiltList types; + final BuiltList types; @override - final TypeReference type; + final Reference type; factory _$Parameter([void updates(ParameterBuilder b)]) => (new ParameterBuilder()..update(updates)).build() as _$Parameter; @@ -505,25 +505,25 @@ class _$ParameterBuilder extends ParameterBuilder { } @override - ListBuilder get types { + ListBuilder get types { _$this; - return super.types ??= new ListBuilder(); + return super.types ??= new ListBuilder(); } @override - set types(ListBuilder types) { + set types(ListBuilder types) { _$this; super.types = types; } @override - TypeReference get type { + Reference get type { _$this; return super.type; } @override - set type(TypeReference type) { + set type(Reference type) { _$this; super.type = type; } diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index ced2f1428..0ecba93a0 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -26,10 +26,7 @@ class Reference implements Spec { final String symbol; /// Create a reference to [symbol] in [url]. - const Reference(this.symbol, this.url); - - /// Create a reference to [symbol] in the same library (no import statement). - const Reference.localScope(this.symbol) : url = null; + const Reference(this.symbol, [this.url]); @override R accept(SpecVisitor visitor) => visitor.visitReference(this); diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index 855011b82..0bdf984f8 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -34,10 +34,10 @@ abstract class TypeReference extends Object /// Optional bound generic. @nullable - TypeReference get bound; + Reference get bound; @override - BuiltList get types; + BuiltList get types; @override R accept(SpecVisitor visitor) => visitor.visitType(this); @@ -58,8 +58,8 @@ abstract class TypeReferenceBuilder extends Object String url; /// Optional bound generic. - TypeReference bound; + Reference bound; @override - ListBuilder types = new ListBuilder(); + ListBuilder types = new ListBuilder(); } diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index c6bee1677..eccc07c2e 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -13,9 +13,9 @@ class _$TypeReference extends TypeReference { @override final String url; @override - final TypeReference bound; + final Reference bound; @override - final BuiltList types; + final BuiltList types; factory _$TypeReference([void updates(TypeReferenceBuilder b)]) => (new TypeReferenceBuilder()..update(updates)).build() as _$TypeReference; @@ -90,25 +90,25 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { } @override - TypeReference get bound { + Reference get bound { _$this; return super.bound; } @override - set bound(TypeReference bound) { + set bound(Reference bound) { _$this; super.bound = bound; } @override - ListBuilder get types { + ListBuilder get types { _$this; - return super.types ??= new ListBuilder(); + return super.types ??= new ListBuilder(); } @override - set types(ListBuilder types) { + set types(ListBuilder types) { _$this; super.types = types; } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 8b7fa5c3d..45fdfe7af 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,20 +1,25 @@ name: code_builder -version: 2.0.0-alpha +version: 2.0.0-alpha+1 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=1.22.0 <2.0.0' + sdk: '>=1.22.0 <2.0.0-dev.infinity' dependencies: built_collection: ^1.0.0 built_value: ^1.0.0 + dart_style: ^1.0.0 matcher: ^0.12.0 meta: ^1.0.5 dev_dependencies: build_runner: ^0.3.0 built_value_generator: '>=1.0.0 <=1.1.4' - dart_style: ^1.0.0 + source_gen: '>=0.5.0 <0.7.0' test: ^0.12.0 + +transformers: + - test/pub_serve: + $include: test/**_test.dart diff --git a/pkgs/code_builder/test/allocator_test.dart b/pkgs/code_builder/test/allocator_test.dart index f800d872b..dbd366df8 100644 --- a/pkgs/code_builder/test/allocator_test.dart +++ b/pkgs/code_builder/test/allocator_test.dart @@ -18,7 +18,7 @@ void main() { allocator = new Allocator() ..allocate(const Reference('List', 'dart:core')) ..allocate(const Reference('LinkedHashMap', 'dart:collection')) - ..allocate(const Reference.localScope('someSymbol')); + ..allocate(const Reference('someSymbol')); expect(allocator.imports.map((d) => d.url), [ 'dart:core', 'dart:collection', diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index 7cb40b86f..fa75637bd 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -14,7 +14,7 @@ void main() { final clazz = new ClassBuilder() ..name = 'Injector' - ..implements.add($App.toType()) + ..implements.add($App) ..fields.add(new Field((b) => b ..modifier = FieldModifier.final$ ..name = '_module' @@ -29,7 +29,7 @@ void main() { ..code = 'new {{ThingRef}}(_module.get1(), _module.get2())' ..specs['ThingRef'] = () => $Thing) ..lambda = true - ..returns = $Thing.toType() + ..returns = $Thing ..annotations.add(new Annotation( (b) => b..code = new Code((b) => b.code = 'override'))))); diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 61e69d3b4..45d4098ce 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -45,7 +45,7 @@ void main() { }); test('should create a class with annotations', () { - final $deprecated = const Reference.localScope('deprecated'); + final $deprecated = const Reference('deprecated'); expect( new Class( (b) => b @@ -74,7 +74,7 @@ void main() { expect( new Class((b) => b ..name = 'List' - ..types.add(const Reference.localScope('T').toType())), + ..types.add(const Reference('T'))), equalsDart(r''' class List {} '''), @@ -87,8 +87,8 @@ void main() { (b) => b ..name = 'Map' ..types.addAll([ - const Reference.localScope('K').toType(), - const Reference.localScope('V').toType(), + const Reference('K'), + const Reference('V'), ]), ), equalsDart(r''' @@ -105,7 +105,7 @@ void main() { ..symbol = 'T' ..bound = new TypeReference((b) => b ..symbol = 'Comparable' - ..types.add(const Reference.localScope('T').toType()))))), + ..types.add(const Reference('T').toType()))))), equalsDart(r''' class Comparable> {} '''), @@ -244,7 +244,7 @@ void main() { ..name = 'Foo' ..constructors.add(new Constructor((b) => b ..factory = true - ..redirect = const Reference.localScope('_Foo')))), + ..redirect = const Reference('_Foo')))), equalsDart(r''' class Foo { factory Foo() = _Foo; diff --git a/pkgs/code_builder/test/specs/field_test.dart b/pkgs/code_builder/test/specs/field_test.dart index 662738e8f..f8ca58486 100644 --- a/pkgs/code_builder/test/specs/field_test.dart +++ b/pkgs/code_builder/test/specs/field_test.dart @@ -19,7 +19,7 @@ void main() { expect( new Field((b) => b ..name = 'foo' - ..type = const Reference.localScope('String').toType()), + ..type = const Reference('String')), equalsDart(r''' String foo; '''), diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 9679d5b05..39d76b8d4 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -44,7 +44,7 @@ void main() { expect( new Method((b) => b ..name = 'foo' - ..returns = const Reference.localScope('String').toType()), + ..returns = const Reference('String')), equalsDart(r''' String foo(); '''), @@ -64,7 +64,7 @@ void main() { expect( new Method((b) => b ..name = 'foo' - ..types.add(const Reference.localScope('T').toType())), + ..types.add(const Reference('T'))), equalsDart(r''' foo(); '''), @@ -182,7 +182,7 @@ void main() { new Parameter( (b) => b ..name = 'i' - ..type = const Reference.localScope('int').toType(), + ..type = const Reference('int').toType(), ), ), ), @@ -199,18 +199,18 @@ void main() { ..name = 'foo' ..types.add(new TypeReference((b) => b ..symbol = 'T' - ..bound = const Reference.localScope('Iterable').toType())) + ..bound = const Reference('Iterable'))) ..requiredParameters.addAll([ new Parameter( (b) => b ..name = 't' - ..type = const Reference.localScope('T').toType(), + ..type = const Reference('T'), ), new Parameter((b) => b ..name = 'x' ..type = new TypeReference((b) => b ..symbol = 'X' - ..types.add(const Reference.localScope('T').toType()))), + ..types.add(const Reference('T')))), ]), ), equalsDart(r''' diff --git a/pkgs/code_builder/tool/build.dart b/pkgs/code_builder/tool/build.dart index 350e2f3b6..c2b1c0d2b 100644 --- a/pkgs/code_builder/tool/build.dart +++ b/pkgs/code_builder/tool/build.dart @@ -16,5 +16,6 @@ Future main() async { ]), new InputSet('code_builder', const ['lib/src/specs/**.dart']), ), + deleteFilesByDefault: true, ); } diff --git a/pkgs/code_builder/tool/watch.dart b/pkgs/code_builder/tool/watch.dart index c6cee8b57..a930b2580 100644 --- a/pkgs/code_builder/tool/watch.dart +++ b/pkgs/code_builder/tool/watch.dart @@ -16,5 +16,6 @@ Future main() async { ]), new InputSet('code_builder', const ['lib/src/specs/**.dart']), ), + deleteFilesByDefault: true, ); } From b9da65162294960a2db07312dcd42a8db44dcce7 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 12 Sep 2017 20:47:13 -0700 Subject: [PATCH 061/271] Standardize license file format --- pkgs/code_builder/LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/LICENSE b/pkgs/code_builder/LICENSE index 4ded3fa11..82e9b524a 100644 --- a/pkgs/code_builder/LICENSE +++ b/pkgs/code_builder/LICENSE @@ -23,4 +23,4 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 1d25da8335d7966633d7b240a31d7abdaf144a0c Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 20 Sep 2017 18:42:44 -0700 Subject: [PATCH 062/271] Add small set of 2.x milestone fixes. (dart-lang/code_builder#128) * Add small set of 2.x milestone fixes. * Dartfmt. * Add instructions for dartfmt. --- pkgs/code_builder/.travis.yml | 2 + pkgs/code_builder/CHANGELOG.md | 11 +++ pkgs/code_builder/README.md | 7 ++ pkgs/code_builder/lib/code_builder.dart | 8 +- pkgs/code_builder/lib/src/emitter.dart | 31 ++++++- .../lib/src/specs/annotation.g.dart | 11 ++- pkgs/code_builder/lib/src/specs/class.g.dart | 11 ++- pkgs/code_builder/lib/src/specs/code.g.dart | 11 ++- .../lib/src/specs/constructor.g.dart | 11 ++- .../code_builder/lib/src/specs/directive.dart | 45 +++++++++- .../lib/src/specs/directive.g.dart | 89 +++++++++++++++++-- pkgs/code_builder/lib/src/specs/field.g.dart | 11 ++- pkgs/code_builder/lib/src/specs/file.g.dart | 11 ++- pkgs/code_builder/lib/src/specs/method.dart | 13 +++ pkgs/code_builder/lib/src/specs/method.g.dart | 67 +++++++++----- .../lib/src/specs/type_reference.g.dart | 11 ++- pkgs/code_builder/pubspec.yaml | 9 +- pkgs/code_builder/test/specs/file_test.dart | 51 +++++++++++ pkgs/code_builder/test/specs/method_test.dart | 39 ++++++++ pkgs/code_builder/tool/build.dart | 14 +-- pkgs/code_builder/tool/src/codegen.dart | 18 ++++ pkgs/code_builder/tool/watch.dart | 14 +-- 22 files changed, 403 insertions(+), 92 deletions(-) create mode 100644 pkgs/code_builder/tool/src/codegen.dart diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index a391ab1ba..d489071b4 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -20,6 +20,8 @@ dart_task: - dartanalyzer - dartfmt +# TODO: Test with dartdevc once https://github.com/dart-lang/sdk/issues/30810. + # The Dart language is constantly being worked on, and sometimes the dev and # stable builds don't agree on what is considered formatted or what is analysis # warning free (though this does not effect _using_ the library, likely). diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index d4a417d5a..b31c02192 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,14 @@ +## 2.0.0-alpha+2 + +* 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). + ## 2.0.0-alpha+1 * Removed `Reference.localScope`. Just use `Reference(symbol)` now. diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index e8581f865..0ecfd00aa 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -16,6 +16,13 @@ easier or better way to do something, consider [opening a pull request][pull]. You can always [file an issue][issue], but generally speaking feature requests will be on a best-effort basis. +> **NOTE**: Due to the evolving Dart SDK the local `dartfmt` must be used to +> format this repository. You can run it simply from the command-line: + +```sh +$ pub run dart_style:format -w . +``` + [wiki]: https://github.com/dart-lang/code_builder/wiki [issue]: https://github.com/dart-lang/code_builder/issues [pull]: https://github.com/dart-lang/code_builder/pulls diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 9cc8374b3..d3c4d8184 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -15,6 +15,12 @@ export 'src/specs/directive.dart' export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; export 'src/specs/file.dart' show File, FileBuilder; export 'src/specs/method.dart' - show Method, MethodBuilder, MethodType, Parameter, ParameterBuilder; + show + Method, + MethodBuilder, + MethodModifier, + MethodType, + Parameter, + ParameterBuilder; export 'src/specs/reference.dart' show Reference; export 'src/specs/type_reference.dart' show TypeReference, TypeReferenceBuilder; diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 8d76e8e8d..90d3b6539 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -65,7 +65,7 @@ class DartEmitter implements SpecVisitor { spec.constructors.forEach((c) => visitConstructor(c, spec.name, output)); spec.fields.forEach((f) => visitField(f, output)); spec.methods.forEach((m) => visitMethod(m, output)); - output.write(' }'); + output.writeln(' }'); return output; } @@ -149,6 +149,7 @@ class DartEmitter implements SpecVisitor { } else { output.write(';'); } + output.writeln(); return output; } @@ -178,8 +179,20 @@ class DartEmitter implements SpecVisitor { } output.write("'${spec.url}'"); if (spec.as != null) { + if (spec.deferred) { + output.write(' deferred '); + } output.write(' as ${spec.as}'); } + if (spec.show.isNotEmpty) { + output + ..write(' show ') + ..writeAll(spec.show, ', '); + } else if (spec.hide.isNotEmpty) { + output + ..write(' hide ') + ..writeAll(spec.hide, ', '); + } output.write(';'); return output; } @@ -214,7 +227,7 @@ class DartEmitter implements SpecVisitor { output.write(' = '); visitCode(spec.assignment, output); } - output.write(';'); + output.writeln(';'); return output; } @@ -296,6 +309,19 @@ class DartEmitter implements SpecVisitor { output.write(')'); } if (spec.body != null) { + if (spec.modifier != null) { + switch (spec.modifier) { + case MethodModifier.async: + output.write(' async '); + break; + case MethodModifier.asyncStar: + output.write(' async* '); + break; + case MethodModifier.syncStar: + output.write(' sync* '); + break; + } + } if (spec.lambda) { output.write(' => '); } else { @@ -310,6 +336,7 @@ class DartEmitter implements SpecVisitor { } else { output.write(';'); } + output.writeln(); return output; } diff --git a/pkgs/code_builder/lib/src/specs/annotation.g.dart b/pkgs/code_builder/lib/src/specs/annotation.g.dart index 13d3b4106..f5ff5c755 100644 --- a/pkgs/code_builder/lib/src/specs/annotation.g.dart +++ b/pkgs/code_builder/lib/src/specs/annotation.g.dart @@ -4,9 +4,12 @@ part of code_builder.src.specs.annotation; // ************************************************************************** // Generator: BuiltValueGenerator -// Target: abstract class Annotation // ************************************************************************** +// ignore_for_file: annotate_overrides +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + class _$Annotation extends Annotation { @override final Code code; @@ -82,8 +85,8 @@ class _$AnnotationBuilder extends AnnotationBuilder { @override _$Annotation build() { - final result = _$v ?? new _$Annotation._(code: code); - replace(result); - return result; + final _$result = _$v ?? new _$Annotation._(code: code); + replace(_$result); + return _$result; } } diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index 8edbcc630..f0ea47cd4 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -4,9 +4,12 @@ part of code_builder.src.specs.class_; // ************************************************************************** // Generator: BuiltValueGenerator -// Target: abstract class Class // ************************************************************************** +// ignore_for_file: annotate_overrides +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + class _$Class extends Class { @override final bool abstract; @@ -293,7 +296,7 @@ class _$ClassBuilder extends ClassBuilder { @override _$Class build() { - final result = _$v ?? + final _$result = _$v ?? new _$Class._( abstract: abstract, annotations: annotations?.build(), @@ -306,7 +309,7 @@ class _$ClassBuilder extends ClassBuilder { methods: methods?.build(), fields: fields?.build(), name: name); - replace(result); - return result; + replace(_$result); + return _$result; } } diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart index cacd4053b..fb0af4d64 100644 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -4,9 +4,12 @@ part of code_builder.src.specs.code; // ************************************************************************** // Generator: BuiltValueGenerator -// Target: abstract class Code // ************************************************************************** +// ignore_for_file: annotate_overrides +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + class _$Code extends Code { @override final String code; @@ -100,8 +103,8 @@ class _$CodeBuilder extends CodeBuilder { @override _$Code build() { - final result = _$v ?? new _$Code._(code: code, specs: specs?.build()); - replace(result); - return result; + final _$result = _$v ?? new _$Code._(code: code, specs: specs?.build()); + replace(_$result); + return _$result; } } diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index cd72dfe51..b33795d28 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -4,9 +4,12 @@ part of code_builder.src.specs.constructor; // ************************************************************************** // Generator: BuiltValueGenerator -// Target: abstract class Constructor // ************************************************************************** +// ignore_for_file: annotate_overrides +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + class _$Constructor extends Constructor { @override final BuiltList annotations; @@ -314,7 +317,7 @@ class _$ConstructorBuilder extends ConstructorBuilder { @override _$Constructor build() { - final result = _$v ?? + final _$result = _$v ?? new _$Constructor._( annotations: annotations?.build(), docs: docs?.build(), @@ -328,7 +331,7 @@ class _$ConstructorBuilder extends ConstructorBuilder { lambda: lambda, name: name, redirect: redirect); - replace(result); - return result; + replace(_$result); + return _$result; } } diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart index afda656ca..d1213fcd2 100644 --- a/pkgs/code_builder/lib/src/specs/directive.dart +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -19,15 +19,40 @@ abstract class Directive implements Built, Spec { factory Directive.import( String url, { String as, + List show: const [], + List hide: const [], }) => new Directive((builder) => builder ..as = as ..type = DirectiveType.import - ..url = url); + ..url = url + ..show.addAll(show) + ..hide.addAll(hide)); + + factory Directive.importDeferredAs( + String url, + String as, { + List show: const [], + List hide: const [], + }) => + new Directive((builder) => builder + ..as = as + ..type = DirectiveType.import + ..url = url + ..deferred = true + ..show.addAll(show) + ..hide.addAll(hide)); - factory Directive.export(String url) => new Directive((builder) => builder - ..type = DirectiveType.export - ..url = url); + factory Directive.export( + String url, { + List show: const [], + List hide: const [], + }) => + new Directive((builder) => builder + ..type = DirectiveType.export + ..url = url + ..show.addAll(show) + ..hide.addAll(hide)); Directive._(); @@ -38,6 +63,12 @@ abstract class Directive implements Built, Spec { DirectiveType get type; + List get show; + + List get hide; + + bool get deferred; + @override R accept(SpecVisitor visitor) => visitor.visitDirective(this); } @@ -48,10 +79,16 @@ abstract class DirectiveBuilder DirectiveBuilder._(); + bool deferred = false; + String as; String url; + List show = []; + + List hide = []; + DirectiveType type; } diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart index 166c59407..035c7acdd 100644 --- a/pkgs/code_builder/lib/src/specs/directive.g.dart +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -4,9 +4,12 @@ part of code_builder.src.specs.directive; // ************************************************************************** // Generator: BuiltValueGenerator -// Target: abstract class Directive // ************************************************************************** +// ignore_for_file: annotate_overrides +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + class _$Directive extends Directive { @override final String as; @@ -14,13 +17,24 @@ class _$Directive extends Directive { final String url; @override final DirectiveType type; + @override + final List show; + @override + final List hide; + @override + final bool deferred; factory _$Directive([void updates(DirectiveBuilder b)]) => (new DirectiveBuilder()..update(updates)).build() as _$Directive; - _$Directive._({this.as, this.url, this.type}) : super._() { + _$Directive._( + {this.as, this.url, this.type, this.show, this.hide, this.deferred}) + : super._() { if (url == null) throw new ArgumentError.notNull('url'); if (type == null) throw new ArgumentError.notNull('type'); + if (show == null) throw new ArgumentError.notNull('show'); + if (hide == null) throw new ArgumentError.notNull('hide'); + if (deferred == null) throw new ArgumentError.notNull('deferred'); } @override @@ -34,12 +48,22 @@ class _$Directive extends Directive { bool operator ==(dynamic other) { if (identical(other, this)) return true; if (other is! Directive) return false; - return as == other.as && url == other.url && type == other.type; + return as == other.as && + url == other.url && + type == other.type && + show == other.show && + hide == other.hide && + deferred == other.deferred; } @override int get hashCode { - return $jf($jc($jc($jc(0, as.hashCode), url.hashCode), type.hashCode)); + return $jf($jc( + $jc( + $jc($jc($jc($jc(0, as.hashCode), url.hashCode), type.hashCode), + show.hashCode), + hide.hashCode), + deferred.hashCode)); } @override @@ -47,7 +71,10 @@ class _$Directive extends Directive { return (newBuiltValueToStringHelper('Directive') ..add('as', as) ..add('url', url) - ..add('type', type)) + ..add('type', type) + ..add('show', show) + ..add('hide', hide) + ..add('deferred', deferred)) .toString(); } } @@ -91,6 +118,42 @@ class _$DirectiveBuilder extends DirectiveBuilder { super.type = type; } + @override + List get show { + _$this; + return super.show; + } + + @override + set show(List show) { + _$this; + super.show = show; + } + + @override + List get hide { + _$this; + return super.hide; + } + + @override + set hide(List hide) { + _$this; + super.hide = hide; + } + + @override + bool get deferred { + _$this; + return super.deferred; + } + + @override + set deferred(bool deferred) { + _$this; + super.deferred = deferred; + } + _$DirectiveBuilder() : super._(); DirectiveBuilder get _$this { @@ -98,6 +161,9 @@ class _$DirectiveBuilder extends DirectiveBuilder { super.as = _$v.as; super.url = _$v.url; super.type = _$v.type; + super.show = _$v.show; + super.hide = _$v.hide; + super.deferred = _$v.deferred; _$v = null; } return this; @@ -116,8 +182,15 @@ class _$DirectiveBuilder extends DirectiveBuilder { @override _$Directive build() { - final result = _$v ?? new _$Directive._(as: as, url: url, type: type); - replace(result); - return result; + final _$result = _$v ?? + new _$Directive._( + as: as, + url: url, + type: type, + show: show, + hide: hide, + deferred: deferred); + replace(_$result); + return _$result; } } diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index d3dde8485..1d662b237 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -4,9 +4,12 @@ part of code_builder.src.specs.field; // ************************************************************************** // Generator: BuiltValueGenerator -// Target: abstract class Field // ************************************************************************** +// ignore_for_file: annotate_overrides +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + class _$Field extends Field { @override final BuiltList annotations; @@ -206,7 +209,7 @@ class _$FieldBuilder extends FieldBuilder { @override _$Field build() { - final result = _$v ?? + final _$result = _$v ?? new _$Field._( annotations: annotations?.build(), docs: docs?.build(), @@ -215,7 +218,7 @@ class _$FieldBuilder extends FieldBuilder { name: name, type: type, modifier: modifier); - replace(result); - return result; + replace(_$result); + return _$result; } } diff --git a/pkgs/code_builder/lib/src/specs/file.g.dart b/pkgs/code_builder/lib/src/specs/file.g.dart index 700918956..d2540ef0b 100644 --- a/pkgs/code_builder/lib/src/specs/file.g.dart +++ b/pkgs/code_builder/lib/src/specs/file.g.dart @@ -4,9 +4,12 @@ part of code_builder.src.specs.library; // ************************************************************************** // Generator: BuiltValueGenerator -// Target: abstract class File // ************************************************************************** +// ignore_for_file: annotate_overrides +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + class _$File extends File { @override final BuiltList directives; @@ -100,9 +103,9 @@ class _$FileBuilder extends FileBuilder { @override _$File build() { - final result = _$v ?? + final _$result = _$v ?? new _$File._(directives: directives?.build(), body: body?.build()); - replace(result); - return result; + replace(_$result); + return _$result; } } diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index f51966d73..44ad1db65 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -76,6 +76,10 @@ abstract class Method extends Object @nullable MethodType get type; + /// Whether this method is `async`, `async*`, or `sync*`. + @nullable + MethodModifier get modifier; + @nullable Reference get returns; @@ -134,6 +138,9 @@ abstract class MethodBuilder extends Object /// Whether this is a getter or setter. MethodType type; + /// Whether this method is `async`, `async*`, or `sync*`. + MethodModifier modifier; + Reference returns; } @@ -142,6 +149,12 @@ enum MethodType { setter, } +enum MethodModifier { + async, + asyncStar, + syncStar, +} + abstract class Parameter extends Object with HasAnnotations, HasGenerics, HasDartDocs implements Built { diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index b7a0f59a3..1417d4206 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -4,9 +4,12 @@ part of code_builder.src.specs.method; // ************************************************************************** // Generator: BuiltValueGenerator -// Target: abstract class Method // ************************************************************************** +// ignore_for_file: annotate_overrides +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + class _$Method extends Method { @override final BuiltList annotations; @@ -31,6 +34,8 @@ class _$Method extends Method { @override final MethodType type; @override + final MethodModifier modifier; + @override final Reference returns; factory _$Method([void updates(MethodBuilder b)]) => @@ -48,6 +53,7 @@ class _$Method extends Method { this.static, this.name, this.type, + this.modifier, this.returns}) : super._() { if (annotations == null) throw new ArgumentError.notNull('annotations'); @@ -85,6 +91,7 @@ class _$Method extends Method { static == other.static && name == other.name && type == other.type && + modifier == other.modifier && returns == other.returns; } @@ -100,17 +107,21 @@ class _$Method extends Method { $jc( $jc( $jc( - $jc($jc(0, annotations.hashCode), - docs.hashCode), - types.hashCode), - optionalParameters.hashCode), - requiredParameters.hashCode), - body.hashCode), - external.hashCode), - lambda.hashCode), - static.hashCode), - name.hashCode), - type.hashCode), + $jc( + $jc( + $jc(0, + annotations.hashCode), + docs.hashCode), + types.hashCode), + optionalParameters.hashCode), + requiredParameters.hashCode), + body.hashCode), + external.hashCode), + lambda.hashCode), + static.hashCode), + name.hashCode), + type.hashCode), + modifier.hashCode), returns.hashCode)); } @@ -128,6 +139,7 @@ class _$Method extends Method { ..add('static', static) ..add('name', name) ..add('type', type) + ..add('modifier', modifier) ..add('returns', returns)) .toString(); } @@ -268,6 +280,18 @@ class _$MethodBuilder extends MethodBuilder { super.type = type; } + @override + MethodModifier get modifier { + _$this; + return super.modifier; + } + + @override + set modifier(MethodModifier modifier) { + _$this; + super.modifier = modifier; + } + @override Reference get returns { _$this; @@ -295,6 +319,7 @@ class _$MethodBuilder extends MethodBuilder { super.static = _$v.static; super.name = _$v.name; super.type = _$v.type; + super.modifier = _$v.modifier; super.returns = _$v.returns; _$v = null; } @@ -314,7 +339,7 @@ class _$MethodBuilder extends MethodBuilder { @override _$Method build() { - final result = _$v ?? + final _$result = _$v ?? new _$Method._( annotations: annotations?.build(), docs: docs?.build(), @@ -327,17 +352,13 @@ class _$MethodBuilder extends MethodBuilder { static: static, name: name, type: type, + modifier: modifier, returns: returns); - replace(result); - return result; + replace(_$result); + return _$result; } } -// ************************************************************************** -// Generator: BuiltValueGenerator -// Target: abstract class Parameter -// ************************************************************************** - class _$Parameter extends Parameter { @override final Code defaultTo; @@ -558,7 +579,7 @@ class _$ParameterBuilder extends ParameterBuilder { @override _$Parameter build() { - final result = _$v ?? + final _$result = _$v ?? new _$Parameter._( defaultTo: defaultTo, name: name, @@ -568,7 +589,7 @@ class _$ParameterBuilder extends ParameterBuilder { docs: docs?.build(), types: types?.build(), type: type); - replace(result); - return result; + replace(_$result); + return _$result; } } diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index eccc07c2e..3b658ecf2 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -4,9 +4,12 @@ part of code_builder.src.specs.type_reference; // ************************************************************************** // Generator: BuiltValueGenerator -// Target: abstract class TypeReference // ************************************************************************** +// ignore_for_file: annotate_overrides +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + class _$TypeReference extends TypeReference { @override final String symbol; @@ -139,10 +142,10 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { @override _$TypeReference build() { - final result = _$v ?? + final _$result = _$v ?? new _$TypeReference._( symbol: symbol, url: url, bound: bound, types: types?.build()); - replace(result); - return result; + replace(_$result); + return _$result; } } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 45fdfe7af..38cff1420 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -9,15 +9,16 @@ environment: dependencies: built_collection: ^1.0.0 - built_value: ^1.0.0 + built_value: '>=2.0.0 <5.0.0' dart_style: ^1.0.0 matcher: ^0.12.0 meta: ^1.0.5 dev_dependencies: - build_runner: ^0.3.0 - built_value_generator: '>=1.0.0 <=1.1.4' - source_gen: '>=0.5.0 <0.7.0' + build_runner: '>=0.4.0 <0.6.0' + built_value_generator: '>=2.0.0 <5.0.0' + io: '>=0.1.0 <0.3.0' + source_gen: '^0.7.0' test: ^0.12.0 transformers: diff --git a/pkgs/code_builder/test/specs/file_test.dart b/pkgs/code_builder/test/specs/file_test.dart index 070ee186d..0c5850192 100644 --- a/pkgs/code_builder/test/specs/file_test.dart +++ b/pkgs/code_builder/test/specs/file_test.dart @@ -27,6 +27,57 @@ void main() { ); }); + test('should emit a source file with a deferred import', () { + expect( + new File( + (b) => b + ..directives.add( + new Directive.importDeferredAs( + 'package:foo/foo.dart', + 'foo', + ), + ), + ), + equalsDart(r''' + import 'package:foo/foo.dart' deferred as foo; + '''), + ); + }); + + test('should emit a source file with a "show" combinator', () { + expect( + new File( + (b) => b + ..directives.add( + new Directive.import( + 'package:foo/foo.dart', + show: ['Foo', 'Bar'], + ), + ), + ), + equalsDart(r''' + import 'package:foo/foo.dart' show Foo, Bar; + '''), + ); + }); + + test('should emit a source file with a "hide" combinator', () { + expect( + new File( + (b) => b + ..directives.add( + new Directive.import( + 'package:foo/foo.dart', + hide: ['Foo', 'Bar'], + ), + ), + ), + equalsDart(r''' + import 'package:foo/foo.dart' hide Foo, Bar; + '''), + ); + }); + test('should emit a source file with allocation', () { expect( new File((b) => b diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 39d76b8d4..d6f583977 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -15,6 +15,45 @@ void main() { ); }); + test('should create an async method', () { + expect( + new Method((b) => b + ..name = 'foo' + ..modifier = MethodModifier.async + ..lambda = true + ..body = new Code((b) => b..code = 'null')), + equalsDart(r''' + foo() async => null; + '''), + ); + }); + + test('should create an async* method', () { + expect( + new Method((b) => b + ..name = 'foo' + ..modifier = MethodModifier.asyncStar + ..lambda = true + ..body = new Code((b) => b..code = 'null')), + equalsDart(r''' + foo() async* => null; + '''), + ); + }); + + test('should create an sync* method', () { + expect( + new Method((b) => b + ..name = 'foo' + ..modifier = MethodModifier.syncStar + ..lambda = true + ..body = new Code((b) => b..code = 'null')), + equalsDart(r''' + foo() sync* => null; + '''), + ); + }); + test('should create a getter', () { expect( new Method((b) => b diff --git a/pkgs/code_builder/tool/build.dart b/pkgs/code_builder/tool/build.dart index c2b1c0d2b..55be42c1b 100644 --- a/pkgs/code_builder/tool/build.dart +++ b/pkgs/code_builder/tool/build.dart @@ -5,17 +5,9 @@ import 'dart:async'; import 'package:build_runner/build_runner.dart'; -import 'package:built_value_generator/built_value_generator.dart'; -import 'package:source_gen/source_gen.dart'; + +import 'src/codegen.dart'; Future main() async { - await build( - new PhaseGroup.singleAction( - new GeneratorBuilder([ - new BuiltValueGenerator(), - ]), - new InputSet('code_builder', const ['lib/src/specs/**.dart']), - ), - deleteFilesByDefault: true, - ); + await build([buildAction()], deleteFilesByDefault: true); } diff --git a/pkgs/code_builder/tool/src/codegen.dart b/pkgs/code_builder/tool/src/codegen.dart new file mode 100644 index 000000000..80edcf824 --- /dev/null +++ b/pkgs/code_builder/tool/src/codegen.dart @@ -0,0 +1,18 @@ +// 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:build_runner/build_runner.dart'; +import 'package:built_value_generator/built_value_generator.dart'; +import 'package:source_gen/source_gen.dart'; + +/// Returns the [BuildAction] for both `build.dart` and `watch.dart`. +BuildAction buildAction() { + return new BuildAction( + new PartBuilder([ + new BuiltValueGenerator(), + ]), + 'code_builder', + inputs: const ['lib/src/specs/**.dart'], + ); +} diff --git a/pkgs/code_builder/tool/watch.dart b/pkgs/code_builder/tool/watch.dart index a930b2580..eb3e9fcad 100644 --- a/pkgs/code_builder/tool/watch.dart +++ b/pkgs/code_builder/tool/watch.dart @@ -5,17 +5,9 @@ import 'dart:async'; import 'package:build_runner/build_runner.dart'; -import 'package:built_value_generator/built_value_generator.dart'; -import 'package:source_gen/source_gen.dart'; + +import 'src/codegen.dart'; Future main() async { - await watch( - new PhaseGroup.singleAction( - new GeneratorBuilder([ - new BuiltValueGenerator(), - ]), - new InputSet('code_builder', const ['lib/src/specs/**.dart']), - ), - deleteFilesByDefault: true, - ); + await watch([buildAction()], deleteFilesByDefault: true); } From 406554d0219e92a376b75d11a076c29c23d73316 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 Sep 2017 09:46:15 -0700 Subject: [PATCH 063/271] Clean up SDK constraint (dart-lang/code_builder#129) Don't need -dev.infinity --- pkgs/code_builder/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 38cff1420..893890ff4 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -5,7 +5,7 @@ author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=1.22.0 <2.0.0-dev.infinity' + sdk: '>=1.22.0 <2.0.0' dependencies: built_collection: ^1.0.0 From f4d45676d7912ff6731d3fb492479bc62b23fc74 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 10 Oct 2017 16:33:37 -0700 Subject: [PATCH 064/271] Initial support for Expression(s). (dart-lang/code_builder#130) * Initial support for Expression(s). * More in changelog. --- pkgs/code_builder/CHANGELOG.md | 11 ++ pkgs/code_builder/lib/code_builder.dart | 8 ++ pkgs/code_builder/lib/src/emitter.dart | 37 +++--- .../lib/src/specs/code/expression.dart | 111 ++++++++++++++++++ pkgs/code_builder/lib/src/visitors.dart | 40 ------- pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 16 +++ 7 files changed, 167 insertions(+), 58 deletions(-) create mode 100644 pkgs/code_builder/lib/src/specs/code/expression.dart create mode 100644 pkgs/code_builder/test/specs/code/expression_test.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index b31c02192..cbacf9892 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -9,6 +9,17 @@ * Added `Directive.importDeferredAs`. * Added a new line character after emitting some types (class, method, etc). +* Removed `SimpleSpecVisitor` (it was unused). + +* In process of adding classes/methods for writing bodies of `Code` fluently: + * `Expression` + * `LiteralExpression` + * `literal` + * `literalNull` + * `literalBool` + * `literalTrue` + * `literalFalse` + ## 2.0.0-alpha+1 * Removed `Reference.localScope`. Just use `Reference(symbol)` now. diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index d3c4d8184..22a5294a9 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -9,6 +9,14 @@ 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 Code, CodeBuilder; +export 'src/specs/code/expression.dart' + show + Expression, + literal, + literalNull, + literalBool, + literalTrue, + literalFalse; export 'src/specs/constructor.dart' show Constructor, ConstructorBuilder; export 'src/specs/directive.dart' show Directive, DirectiveType, DirectiveBuilder; diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 90d3b6539..f0c6ea6b9 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -7,6 +7,7 @@ import 'base.dart'; import 'specs/annotation.dart'; import 'specs/class.dart'; import 'specs/code.dart'; +import 'specs/code/expression.dart'; import 'specs/constructor.dart'; import 'specs/directive.dart'; import 'specs/field.dart'; @@ -16,7 +17,7 @@ import 'specs/reference.dart'; import 'specs/type_reference.dart'; import 'visitors.dart'; -class DartEmitter implements SpecVisitor { +class DartEmitter extends ExpressionEmitter implements SpecVisitor { final Allocator _allocator; /// Creates a new instance of [DartEmitter]. @@ -153,22 +154,6 @@ class DartEmitter implements SpecVisitor { return output; } - static final Pattern _refReplace = new RegExp(r'{{([^{}]*)}}'); - - @override - visitCode(Code spec, [StringSink output]) { - output ??= new StringBuffer(); - var code = spec.code; - if (spec.specs.isNotEmpty) { - code = code.replaceAllMapped(_refReplace, (match) { - // ignore: strong_mode_implicit_dynamic_variable - final lazy = spec.specs[match.group(1)]; - return lazy().accept(this).toString(); - }); - } - return output..write(code); - } - @override visitDirective(Directive spec, [StringSink output]) { output ??= new StringBuffer(); @@ -398,4 +383,22 @@ class DartEmitter implements SpecVisitor { } return output; } + + // Expression/Bodies + + static final Pattern _refReplace = new RegExp(r'{{([^{}]*)}}'); + + @override + visitCode(Code spec, [StringSink output]) { + output ??= new StringBuffer(); + var code = spec.code; + if (spec.specs.isNotEmpty) { + code = code.replaceAllMapped(_refReplace, (match) { + // ignore: strong_mode_implicit_dynamic_variable + final lazy = spec.specs[match.group(1)]; + return lazy().accept(this).toString(); + }); + } + return output..write(code); + } } diff --git a/pkgs/code_builder/lib/src/specs/code/expression.dart b/pkgs/code_builder/lib/src/specs/code/expression.dart new file mode 100644 index 000000000..f658dfbc3 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/code/expression.dart @@ -0,0 +1,111 @@ +// 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 '../../base.dart'; +import '../../visitors.dart'; + +/// Represents a Dart expression. +/// +/// See various concrete implementations for details. +abstract class Expression implements Spec { + const Expression(); + + @override + R accept(covariant ExpressionVisitor visitor); + + Expression and(Expression other) => new BinaryExpression._(this, other, '&&'); +} + +/// Knowledge of different types of expressions in Dart. +/// +/// **INTERNAL ONLY**. +abstract class ExpressionVisitor implements SpecVisitor { + T visitBinaryExpression(BinaryExpression expression, [T context]); + T visitLiteralExpression(LiteralExpression expression, [T context]); +} + +/// Knowledge of how to write valid Dart code from [ExpressionVisitor]. +/// +/// **INTERNAL ONLY**. +abstract class ExpressionEmitter implements ExpressionVisitor { + const ExpressionEmitter(); + + @override + visitBinaryExpression(BinaryExpression expression, [StringSink output]) { + output ??= new StringBuffer(); + return output + ..write(expression.left.accept(this)) + ..write(' ') + ..write(expression.operator) + ..write(' ') + ..write(expression.right.accept(this)); + } + + @override + visitLiteralExpression(LiteralExpression expression, [StringSink output]) { + output ??= new StringBuffer(); + return output..write(expression.literal); + } +} + +/// Converts a runtime Dart [literal] value into an [Expression]. +/// +/// Unsupported inputs invoke the [onError] callback. +Expression literal(Object literal, {Expression onError(Object value)}) { + if (literal is bool) { + return literalBool(literal); + } + if (literal == null) { + return literalNull; + } + if (onError != null) { + return onError(literal); + } + throw new UnsupportedError('Not a supported literal type: $literal.'); +} + +/// Represents the literal value `true`. +const Expression literalTrue = const LiteralExpression._('true'); + +/// Represents the literal value `false`. +const Expression literalFalse = const LiteralExpression._('false'); + +/// Create a literal expression from a boolean [value]. +Expression literalBool(bool value) => value ? literalTrue : literalFalse; + +/// Represents the literal value `null`. +const Expression literalNull = const LiteralExpression._('null'); + +/// Represents a literal value in Dart source code. +/// +/// For example, `new LiteralExpression('null')` should emit `null`. +/// +/// Some common literals and helpers are available as methods/fields: +/// * [literal] +/// * [literalBool] and [literalTrue], [literalFalse] +/// * [literalNull] +class LiteralExpression extends Expression { + final String literal; + + const LiteralExpression._(this.literal); + + @override + R accept(ExpressionVisitor visitor) { + return visitor.visitLiteralExpression(this); + } +} + +/// Represents two expressions ([left] and [right]) and an [operator]. +class BinaryExpression extends Expression { + final Expression left; + final Expression right; + final String operator; + + const BinaryExpression._(this.left, this.right, this.operator); + + @override + R accept(ExpressionVisitor visitor) { + return visitor.visitBinaryExpression(this); + } +} diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index dcde2babc..975bc69a0 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -41,43 +41,3 @@ abstract class SpecVisitor { T visitTypeParameters(Iterable specs); } - -class SimpleSpecVisitor implements SpecVisitor { - const SimpleSpecVisitor(); - - @override - T visitAnnotation(Annotation spec) => null; - - @override - T visitClass(Class spec) => null; - - @override - T visitConstructor(Constructor spec, String clazz) => null; - - @override - T visitCode(Code spec) => null; - - @override - T visitDirective(Directive spec) => null; - - @override - T visitField(Field spec) => null; - - @override - T visitFile(File spec) => null; - - @override - T visitMethod(Method spec) => null; - - @override - T visitReference(Reference spec) => null; - - @override - T visitSpec(Spec spec) => spec.accept(this); - - @override - T visitType(TypeReference spec) => null; - - @override - T visitTypeParameters(Iterable specs) => null; -} diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 893890ff4..0c95c170e 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.0.0-alpha+1 +version: 2.0.0-alpha+2 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart new file mode 100644 index 000000000..c9d44d75b --- /dev/null +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -0,0 +1,16 @@ +// 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:test/test.dart'; + +void main() { + test('should emit a simple expression', () { + expect(literalNull, equalsDart('null')); + }); + + test('should emit a && expression', () { + expect(literalTrue.and(literalFalse), equalsDart('true && false')); + }); +} From 6cd96ef9ad941979afa80f98255063788f0d0f81 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 11 Oct 2017 13:28:35 -0700 Subject: [PATCH 065/271] More code support across codebase (dart-lang/code_builder#131) * Initial support for Expression(s). * More in changelog. * Add context everywhere. * All tests passing. * More cleanup. --- pkgs/code_builder/CHANGELOG.md | 6 +- pkgs/code_builder/example/animal.dart | 4 +- pkgs/code_builder/example/scope.dart | 4 +- pkgs/code_builder/lib/code_builder.dart | 2 +- pkgs/code_builder/lib/src/base.dart | 2 +- pkgs/code_builder/lib/src/emitter.dart | 47 +++----- pkgs/code_builder/lib/src/matchers.dart | 13 ++- .../lib/src/specs/annotation.dart | 6 +- pkgs/code_builder/lib/src/specs/class.dart | 6 +- pkgs/code_builder/lib/src/specs/code.dart | 84 ++++++++++--- pkgs/code_builder/lib/src/specs/code.g.dart | 110 ------------------ .../lib/src/specs/code/expression.dart | 12 +- .../code_builder/lib/src/specs/directive.dart | 6 +- pkgs/code_builder/lib/src/specs/field.dart | 6 +- pkgs/code_builder/lib/src/specs/file.dart | 6 +- pkgs/code_builder/lib/src/specs/method.dart | 6 +- .../code_builder/lib/src/specs/reference.dart | 6 +- .../lib/src/specs/type_reference.dart | 6 +- pkgs/code_builder/lib/src/visitors.dart | 28 ++--- .../code_builder/test/e2e/injection_test.dart | 13 ++- pkgs/code_builder/test/specs/class_test.dart | 21 ++-- pkgs/code_builder/test/specs/field_test.dart | 2 +- pkgs/code_builder/test/specs/file_test.dart | 17 ++- pkgs/code_builder/test/specs/method_test.dart | 51 +++----- 24 files changed, 201 insertions(+), 263 deletions(-) delete mode 100644 pkgs/code_builder/lib/src/specs/code.g.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index cbacf9892..322ecf20a 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -9,8 +9,10 @@ * Added `Directive.importDeferredAs`. * Added a new line character after emitting some types (class, method, etc). +* `SpecVisitor`'s methods all have an optional `[T context]` parameter now. + * This makes it much easier to avoid allocating extra `StringBuffer`s. * Removed `SimpleSpecVisitor` (it was unused). - +* `equalsDart` removes insignificant white space before comparing results. * In process of adding classes/methods for writing bodies of `Code` fluently: * `Expression` * `LiteralExpression` @@ -19,6 +21,8 @@ * `literalBool` * `literalTrue` * `literalFalse` + * `const Code(staticString)` + * `const Code.scope((allocate) => '')` ## 2.0.0-alpha+1 diff --git a/pkgs/code_builder/example/animal.dart b/pkgs/code_builder/example/animal.dart index 9030e4e84..9bee3b025 100644 --- a/pkgs/code_builder/example/animal.dart +++ b/pkgs/code_builder/example/animal.dart @@ -12,7 +12,7 @@ void main() { ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' ..lambda = true - ..body = new Code((b) => b..code = 'print(\'Yum\')')))); - final emitter = const DartEmitter(); + ..body = const Code('print(\'Yum\')')))); + final emitter = new DartEmitter(); print(new DartFormatter().format('${animal.accept(emitter)}')); } diff --git a/pkgs/code_builder/example/scope.dart b/pkgs/code_builder/example/scope.dart index ee0e9f557..9ba85d602 100644 --- a/pkgs/code_builder/example/scope.dart +++ b/pkgs/code_builder/example/scope.dart @@ -8,11 +8,11 @@ import 'package:dart_style/dart_style.dart'; void main() { final library = new File((b) => b.body.addAll([ new Method((b) => b - ..body = new Code((b) => b.code = '') + ..body = const Code('') ..name = 'doThing' ..returns = const Reference('Thing', 'package:a/a.dart')), new Method((b) => b - ..body = new Code((b) => b..code = '') + ..body = const Code('') ..name = 'doOther' ..returns = const Reference('Other', 'package:b/b.dart')), ])); diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 22a5294a9..bc4dfdb7c 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -8,7 +8,7 @@ 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 Code, CodeBuilder; +export 'src/specs/code.dart' show Code, StaticCode, ScopedCode; export 'src/specs/code/expression.dart' show Expression, diff --git a/pkgs/code_builder/lib/src/base.dart b/pkgs/code_builder/lib/src/base.dart index 9bd91bc3f..c164ae0da 100644 --- a/pkgs/code_builder/lib/src/base.dart +++ b/pkgs/code_builder/lib/src/base.dart @@ -5,5 +5,5 @@ import 'visitors.dart'; abstract class Spec { - R accept(SpecVisitor visitor); + R accept(SpecVisitor visitor, [R context]); } diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index f0c6ea6b9..dba36a0bc 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -17,13 +17,16 @@ import 'specs/reference.dart'; import 'specs/type_reference.dart'; import 'visitors.dart'; -class DartEmitter extends ExpressionEmitter implements SpecVisitor { - final Allocator _allocator; +class DartEmitter extends Object + with CodeEmitter, ExpressionEmitter + implements SpecVisitor { + @override + final Allocator allocator; /// Creates a new instance of [DartEmitter]. /// /// May specify an [Allocator] to use for symbols, otherwise uses a no-op. - const DartEmitter([this._allocator = Allocator.none]); + DartEmitter([this.allocator = Allocator.none]); /// Creates a new instance of [DartEmitter] with a default [Allocator]. factory DartEmitter.scoped() => new DartEmitter(new Allocator()); @@ -31,7 +34,7 @@ class DartEmitter extends ExpressionEmitter implements SpecVisitor { @override visitAnnotation(Annotation spec, [StringSink output]) { (output ??= new StringBuffer()).write('@'); - visitCode(spec.code, output); + spec.code.accept(this, output); output.write(' '); return output; } @@ -127,7 +130,7 @@ class DartEmitter extends ExpressionEmitter implements SpecVisitor { var count = 0; for (final initializer in spec.initializers) { count++; - visitCode(initializer, output); + initializer.accept(this, output); if (count != spec.initializers.length) { output.write(', '); } @@ -140,11 +143,11 @@ class DartEmitter extends ExpressionEmitter implements SpecVisitor { } else if (spec.body != null) { if (spec.lambda) { output.write(' => '); - visitCode(spec.body, output); + spec.body.accept(this, output); output.write(';'); } else { output.write(' { '); - visitCode(spec.body, output); + spec.body.accept(this, output); output.write(' }'); } } else { @@ -210,7 +213,7 @@ class DartEmitter extends ExpressionEmitter implements SpecVisitor { output.write(spec.name); if (spec.assignment != null) { output.write(' = '); - visitCode(spec.assignment, output); + spec.assignment.accept(this, output); } output.writeln(';'); return output; @@ -228,7 +231,7 @@ class DartEmitter extends ExpressionEmitter implements SpecVisitor { for (final directive in spec.directives) { visitDirective(directive, output); } - for (final directive in _allocator.imports) { + for (final directive in allocator.imports) { visitDirective(directive, output); } output.write(body); @@ -312,7 +315,7 @@ class DartEmitter extends ExpressionEmitter implements SpecVisitor { } else { output.write(' { '); } - visitCode(spec.body, output); + spec.body.accept(this, output); if (spec.lambda) { output.write(';'); } else { @@ -348,17 +351,17 @@ class DartEmitter extends ExpressionEmitter implements SpecVisitor { } else { output.write(' = '); } - visitCode(spec.defaultTo, output); + spec.defaultTo.accept(this, output); } } @override visitReference(Reference spec, [StringSink output]) { - return (output ??= new StringBuffer())..write(_allocator.allocate(spec)); + return (output ??= new StringBuffer())..write(allocator.allocate(spec)); } @override - visitSpec(Spec spec) => spec.accept(this); + visitSpec(Spec spec, [StringSink output]) => spec.accept(this, output); @override visitType(TypeReference spec, [StringSink output]) { @@ -383,22 +386,4 @@ class DartEmitter extends ExpressionEmitter implements SpecVisitor { } return output; } - - // Expression/Bodies - - static final Pattern _refReplace = new RegExp(r'{{([^{}]*)}}'); - - @override - visitCode(Code spec, [StringSink output]) { - output ??= new StringBuffer(); - var code = spec.code; - if (spec.specs.isNotEmpty) { - code = code.replaceAllMapped(_refReplace, (match) { - // ignore: strong_mode_implicit_dynamic_variable - final lazy = spec.specs[match.group(1)]; - return lazy().accept(this).toString(); - }); - } - return output..write(code); - } } diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index 9a698643c..3183f4ffe 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -13,12 +13,15 @@ final _formatter = new DartFormatter(); /// Runs dartfmt. String _dartfmt(String source) { try { - return _formatter.format(source); + source = _formatter.format(source); } on FormatException catch (_) { - return _formatter.formatStatement(source); + source = _formatter.formatStatement(source); } catch (_) { - return source.replaceAll(' ', ' ').replaceAll('\n', '').trim(); + // Ignored on purpose, probably not exactly valid Dart code. + } finally { + source = source.replaceAll(' ', ' ').replaceAll('\n', '').trim(); } + return source; } /// Encodes [spec] as Dart source code. @@ -28,9 +31,9 @@ String _dart(Spec spec, DartEmitter emitter) => /// Returns a matcher for Dart source code. Matcher equalsDart( String source, [ - DartEmitter emitter = const DartEmitter(), + DartEmitter emitter, ]) => - new _EqualsDart(_dartfmt(source).trim(), emitter); + new _EqualsDart(_dartfmt(source).trim(), emitter ?? new DartEmitter()); class _EqualsDart extends Matcher { final DartEmitter _emitter; diff --git a/pkgs/code_builder/lib/src/specs/annotation.dart b/pkgs/code_builder/lib/src/specs/annotation.dart index f6add9f41..9b74d4537 100644 --- a/pkgs/code_builder/lib/src/specs/annotation.dart +++ b/pkgs/code_builder/lib/src/specs/annotation.dart @@ -24,7 +24,11 @@ abstract class Annotation Code get code; @override - R accept(SpecVisitor visitor) => visitor.visitAnnotation(this); + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitAnnotation(this, context); } abstract class AnnotationBuilder diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart index dcc350b28..41d4ae6ea 100644 --- a/pkgs/code_builder/lib/src/specs/class.dart +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -56,7 +56,11 @@ abstract class Class extends Object String get name; @override - R accept(SpecVisitor visitor) => visitor.visitClass(this); + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitClass(this, context); } abstract class ClassBuilder extends Object diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index 00d095d1f..b4a7afb7d 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -4,38 +4,88 @@ library code_builder.src.specs.code; -import 'package:built_value/built_value.dart'; -import 'package:built_collection/built_collection.dart'; import 'package:meta/meta.dart'; +import '../allocator.dart'; import '../base.dart'; +import '../specs/reference.dart'; import '../visitors.dart'; -part 'code.g.dart'; +/// Returns a scoped symbol to [Reference], with an import prefix if needed. +/// +/// This is short-hand for [Allocator.allocate] in most implementations. +typedef Allocate = String Function(Reference reference); -/// Returns a [Spec] to be created lazily on demand. -typedef Spec LazySpec(); +/// Represents arbitrary Dart code (either expressions or statements). +/// +/// See the various constructors for details. +abstract class Code implements Spec { + /// Create a simple code body based on a static string. + const factory Code(String code) = StaticCode._; -@immutable -abstract class Code implements Built, Spec { - factory Code([void updates(CodeBuilder b)]) = _$Code; + /// Create a code based that may use a provided [Allocator] for scoping: + /// + /// ```dart + /// // Emits `new _i123.FooType()`, where `_i123` is the import prefix. + /// + /// new Code.scope((a) { + /// return 'new ${a.allocate(fooType)}()' + /// }); + /// ``` + const factory Code.scope( + String Function(Allocate allocate) scope, + ) = ScopedCode._; - Code._(); + @override + R accept(covariant CodeVisitor visitor, [R context]); +} - String get code; +/// Knowledge of different types of blocks of code in Dart. +/// +/// **INTERNAL ONLY**. +abstract class CodeVisitor implements SpecVisitor { + T visitStaticCode(StaticCode code, [T context]); + T visitScopedCode(ScopedCode code, [T context]); +} - BuiltMap get specs; +/// Knowledge of how to write valid Dart code from [CodeVisitor]. +abstract class CodeEmitter implements CodeVisitor { + @protected + Allocator get allocator; + + @override + visitStaticCode(StaticCode code, [StringSink output]) { + output ??= new StringBuffer(); + return output..write(code.code); + } @override - R accept(SpecVisitor visitor) => visitor.visitCode(this); + visitScopedCode(ScopedCode code, [StringSink output]) { + output ??= new StringBuffer(); + return output..write(code.code(allocator.allocate)); + } } -abstract class CodeBuilder implements Builder { - factory CodeBuilder() = _$CodeBuilder; +/// Represents a simple, literal [code] block to be inserted as-is. +class StaticCode implements Code { + final String code; - CodeBuilder._(); + const StaticCode._(this.code); - String code; + @override + R accept(CodeVisitor visitor, [R context]) { + return visitor.visitStaticCode(this, context); + } +} + +/// Represents a [code] block that may require scoping. +class ScopedCode implements Code { + final String Function(Allocate allocate) code; - MapBuilder specs = new MapBuilder(); + const ScopedCode._(this.code); + + @override + R accept(CodeVisitor visitor, [R context]) { + return visitor.visitScopedCode(this, context); + } } diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart deleted file mode 100644 index fb0af4d64..000000000 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ /dev/null @@ -1,110 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of code_builder.src.specs.code; - -// ************************************************************************** -// Generator: BuiltValueGenerator -// ************************************************************************** - -// ignore_for_file: annotate_overrides -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - -class _$Code extends Code { - @override - final String code; - @override - final BuiltMap specs; - - factory _$Code([void updates(CodeBuilder b)]) => - (new CodeBuilder()..update(updates)).build() as _$Code; - - _$Code._({this.code, this.specs}) : super._() { - if (code == null) throw new ArgumentError.notNull('code'); - if (specs == null) throw new ArgumentError.notNull('specs'); - } - - @override - Code rebuild(void updates(CodeBuilder b)) => - (toBuilder()..update(updates)).build(); - - @override - _$CodeBuilder toBuilder() => new _$CodeBuilder()..replace(this); - - @override - bool operator ==(dynamic other) { - if (identical(other, this)) return true; - if (other is! Code) return false; - return code == other.code && specs == other.specs; - } - - @override - int get hashCode { - return $jf($jc($jc(0, code.hashCode), specs.hashCode)); - } - - @override - String toString() { - return (newBuiltValueToStringHelper('Code') - ..add('code', code) - ..add('specs', specs)) - .toString(); - } -} - -class _$CodeBuilder extends CodeBuilder { - _$Code _$v; - - @override - String get code { - _$this; - return super.code; - } - - @override - set code(String code) { - _$this; - super.code = code; - } - - @override - MapBuilder get specs { - _$this; - return super.specs ??= new MapBuilder(); - } - - @override - set specs(MapBuilder specs) { - _$this; - super.specs = specs; - } - - _$CodeBuilder() : super._(); - - CodeBuilder get _$this { - if (_$v != null) { - super.code = _$v.code; - super.specs = _$v.specs?.toBuilder(); - _$v = null; - } - return this; - } - - @override - void replace(Code other) { - if (other == null) throw new ArgumentError.notNull('other'); - _$v = other as _$Code; - } - - @override - void update(void updates(CodeBuilder b)) { - if (updates != null) updates(this); - } - - @override - _$Code build() { - final _$result = _$v ?? new _$Code._(code: code, specs: specs?.build()); - replace(_$result); - return _$result; - } -} diff --git a/pkgs/code_builder/lib/src/specs/code/expression.dart b/pkgs/code_builder/lib/src/specs/code/expression.dart index f658dfbc3..9b17205d3 100644 --- a/pkgs/code_builder/lib/src/specs/code/expression.dart +++ b/pkgs/code_builder/lib/src/specs/code/expression.dart @@ -12,7 +12,7 @@ abstract class Expression implements Spec { const Expression(); @override - R accept(covariant ExpressionVisitor visitor); + R accept(covariant ExpressionVisitor visitor, [R context]); Expression and(Expression other) => new BinaryExpression._(this, other, '&&'); } @@ -29,8 +29,6 @@ abstract class ExpressionVisitor implements SpecVisitor { /// /// **INTERNAL ONLY**. abstract class ExpressionEmitter implements ExpressionVisitor { - const ExpressionEmitter(); - @override visitBinaryExpression(BinaryExpression expression, [StringSink output]) { output ??= new StringBuffer(); @@ -91,8 +89,8 @@ class LiteralExpression extends Expression { const LiteralExpression._(this.literal); @override - R accept(ExpressionVisitor visitor) { - return visitor.visitLiteralExpression(this); + R accept(ExpressionVisitor visitor, [R context]) { + return visitor.visitLiteralExpression(this, context); } } @@ -105,7 +103,7 @@ class BinaryExpression extends Expression { const BinaryExpression._(this.left, this.right, this.operator); @override - R accept(ExpressionVisitor visitor) { - return visitor.visitBinaryExpression(this); + R accept(ExpressionVisitor visitor, [R context]) { + return visitor.visitBinaryExpression(this, context); } } diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart index d1213fcd2..bc3a9db79 100644 --- a/pkgs/code_builder/lib/src/specs/directive.dart +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -70,7 +70,11 @@ abstract class Directive implements Built, Spec { bool get deferred; @override - R accept(SpecVisitor visitor) => visitor.visitDirective(this); + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitDirective(this, context); } abstract class DirectiveBuilder diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index f03c3d7d7..96672ecfa 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -57,7 +57,11 @@ abstract class Field extends Object String get url => null; @override - R accept(SpecVisitor visitor) => visitor.visitField(this); + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitField(this, context); @override TypeReference toType() => throw new UnsupportedError(''); diff --git a/pkgs/code_builder/lib/src/specs/file.dart b/pkgs/code_builder/lib/src/specs/file.dart index 98f26e54e..39b5356f1 100644 --- a/pkgs/code_builder/lib/src/specs/file.dart +++ b/pkgs/code_builder/lib/src/specs/file.dart @@ -24,7 +24,11 @@ abstract class File implements Built, Spec { BuiltList get body; @override - R accept(SpecVisitor visitor) => visitor.visitFile(this); + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitFile(this, context); } abstract class FileBuilder implements Builder { diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 44ad1db65..3422192db 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -90,7 +90,11 @@ abstract class Method extends Object String get url => null; @override - R accept(SpecVisitor visitor) => visitor.visitMethod(this); + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitMethod(this, context); @override TypeReference toType() => throw new UnsupportedError(''); diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 0ecba93a0..1e2514c2d 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -29,7 +29,11 @@ class Reference implements Spec { const Reference(this.symbol, [this.url]); @override - R accept(SpecVisitor visitor) => visitor.visitReference(this); + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitReference(this, context); @override int get hashCode => '$url#$symbol'.hashCode; diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index 0bdf984f8..5dfb9fda3 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -40,7 +40,11 @@ abstract class TypeReference extends Object BuiltList get types; @override - R accept(SpecVisitor visitor) => visitor.visitType(this); + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitType(this, context); @override TypeReference toType() => this; diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 975bc69a0..03aea23a5 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -2,10 +2,11 @@ // 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:meta/meta.dart'; + import 'base.dart'; import 'specs/annotation.dart'; import 'specs/class.dart'; -import 'specs/code.dart'; import 'specs/constructor.dart'; import 'specs/directive.dart'; import 'specs/field.dart'; @@ -14,30 +15,29 @@ import 'specs/method.dart'; import 'specs/reference.dart'; import 'specs/type_reference.dart'; +@optionalTypeArgs abstract class SpecVisitor { const SpecVisitor._(); - T visitAnnotation(Annotation spec); - - T visitClass(Class spec); + T visitAnnotation(Annotation spec, [T context]); - T visitCode(Code spec); + T visitClass(Class spec, [T context]); - T visitConstructor(Constructor spec, String clazz); + T visitConstructor(Constructor spec, String clazz, [T context]); - T visitDirective(Directive spec); + T visitDirective(Directive spec, [T context]); - T visitField(Field spec); + T visitField(Field spec, [T context]); - T visitFile(File spec); + T visitFile(File spec, [T context]); - T visitMethod(Method spec); + T visitMethod(Method spec, [T context]); - T visitReference(Reference spec); + T visitReference(Reference spec, [T context]); - T visitSpec(Spec spec); + T visitSpec(Spec spec, [T context]); - T visitType(TypeReference spec); + T visitType(TypeReference spec, [T context]); - T visitTypeParameters(Iterable specs); + T visitTypeParameters(Iterable specs, [T context]); } diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index fa75637bd..36ee5317e 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -25,20 +25,21 @@ void main() { ..toThis = true)))) ..methods.add(new Method((b) => b ..name = 'getThing' - ..body = new Code((b) => b - ..code = 'new {{ThingRef}}(_module.get1(), _module.get2())' - ..specs['ThingRef'] = () => $Thing) + ..body = new Code.scope( + (a) => 'new ${a($Thing)}(_module.get1(), _module.get2())') ..lambda = true ..returns = $Thing - ..annotations.add(new Annotation( - (b) => b..code = new Code((b) => b.code = 'override'))))); + ..annotations + .add(new Annotation((b) => b..code = const Code('override'))))); expect( clazz.build(), equalsDart(r''' class Injector implements App { Injector(this._module); + final Module _module; + @override Thing getThing() => new Thing(_module.get1(), _module.get2()); } @@ -50,7 +51,9 @@ void main() { equalsDart(r''' class Injector implements _1.App { Injector(this._module); + final _2.Module _module; + @override _3.Thing getThing() => new _3.Thing(_module.get1(), _module.get2()); } diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 45d4098ce..11a607f6d 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -52,14 +52,7 @@ void main() { ..name = 'Foo' ..annotations.add( new Annotation( - (b) => b - ..code = new Code( - (b) => b - ..code = '{{deprecated}}' - ..specs.addAll({ - 'deprecated': () => $deprecated, - }), - ), + (b) => b..code = new Code.scope((a) => a($deprecated)), ), ), ), @@ -169,8 +162,8 @@ void main() { new Constructor( (b) => b ..initializers.addAll([ - new Code((b) => b.code = 'a = 5'), - new Code((b) => b.code = 'super()'), + const Code('a = 5'), + const Code('super()'), ]), ), ), @@ -188,8 +181,8 @@ void main() { new Class((b) => b ..name = 'Foo' ..constructors.add(new Constructor((b) => b - ..annotations.add(new Annotation( - (b) => b..code = new Code((b) => b..code = 'deprecated')))))), + ..annotations.add( + new Annotation((b) => b..code = const Code('deprecated')))))), equalsDart(r''' class Foo { @deprecated @@ -260,7 +253,7 @@ void main() { ..constructors.add(new Constructor((b) => b ..factory = true ..lambda = true - ..body = new Code((b) => b..code = 'new _Foo()')))), + ..body = const Code('new _Foo()')))), equalsDart(r''' class Foo { factory Foo() => new _Foo(); @@ -275,7 +268,7 @@ void main() { ..name = 'Foo' ..constructors.add(new Constructor((b) => b ..factory = true - ..body = new Code((b) => b..code = 'return new _Foo();')))), + ..body = const Code('return new _Foo();')))), equalsDart(r''' class Foo { factory Foo() { diff --git a/pkgs/code_builder/test/specs/field_test.dart b/pkgs/code_builder/test/specs/field_test.dart index f8ca58486..3cd4fb768 100644 --- a/pkgs/code_builder/test/specs/field_test.dart +++ b/pkgs/code_builder/test/specs/field_test.dart @@ -52,7 +52,7 @@ void main() { expect( new Field((b) => b ..name = 'foo' - ..assignment = new Code((b) => b..code = '1')), + ..assignment = const Code('1')), equalsDart(r''' var foo = 1; '''), diff --git a/pkgs/code_builder/test/specs/file_test.dart b/pkgs/code_builder/test/specs/file_test.dart index 0c5850192..fb32f60ad 100644 --- a/pkgs/code_builder/test/specs/file_test.dart +++ b/pkgs/code_builder/test/specs/file_test.dart @@ -16,14 +16,13 @@ void main() { ..body.add(new Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ - ..assignment = new Code((b) => b - ..code = 'new {{LinkedHashMap}}()' - ..specs.addAll({'LinkedHashMap': () => $linkedHashMap}))))), + ..assignment = + new Code.scope((a) => 'new ${a($linkedHashMap)}()')))), equalsDart(r''' import 'dart:collection'; final test = new LinkedHashMap(); - ''', const DartEmitter()), + ''', new DartEmitter()), ); }); @@ -84,9 +83,8 @@ void main() { ..body.add(new Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ - ..assignment = new Code((b) => b - ..code = 'new {{LinkedHashMap}}()' - ..specs.addAll({'LinkedHashMap': () => $linkedHashMap}))))), + ..assignment = + new Code.scope((a) => 'new ${a($linkedHashMap)}()')))), equalsDart(r''' import 'dart:collection'; @@ -101,9 +99,8 @@ void main() { ..body.add(new Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ - ..assignment = new Code((b) => b - ..code = 'new {{LinkedHashMap}}()' - ..specs.addAll({'LinkedHashMap': () => $linkedHashMap}))))), + ..assignment = + new Code.scope((a) => 'new ${a($linkedHashMap)}()')))), equalsDart(r''' import 'dart:collection' as _1; diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index d6f583977..91dd5f71e 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -21,7 +21,7 @@ void main() { ..name = 'foo' ..modifier = MethodModifier.async ..lambda = true - ..body = new Code((b) => b..code = 'null')), + ..body = const Code('null')), equalsDart(r''' foo() async => null; '''), @@ -34,7 +34,7 @@ void main() { ..name = 'foo' ..modifier = MethodModifier.asyncStar ..lambda = true - ..body = new Code((b) => b..code = 'null')), + ..body = const Code('null')), equalsDart(r''' foo() async* => null; '''), @@ -47,7 +47,7 @@ void main() { ..name = 'foo' ..modifier = MethodModifier.syncStar ..lambda = true - ..body = new Code((b) => b..code = 'null')), + ..body = const Code('null')), equalsDart(r''' foo() sync* => null; '''), @@ -125,9 +125,7 @@ void main() { expect( new Method((b) => b ..name = 'foo' - ..body = new Code((b) => b.code = r''' - return 1 + 2; - ''')), + ..body = const Code('return 1+ 2;')), equalsDart(r''' foo() { return 1 + 2; @@ -138,16 +136,10 @@ void main() { test('should create a lambda method', () { expect( - new Method( - (b) => b - ..name = 'foo' - ..lambda = true - ..body = new Code( - (b) => b.code = r''' - 1 + 2 - ''', - ), - ), + new Method((b) => b + ..name = 'foo' + ..lambda = true + ..body = const Code('1 + 2')), equalsDart(r''' foo() => 1 + 2; '''), @@ -157,20 +149,11 @@ void main() { test('should create a method with a body with references', () { final linkedHashMap = const Reference('LinkedHashMap', 'dart:collection'); expect( - new Method( - (b) => b - ..name = 'foo' - ..body = new Code((b) => b - ..code = r''' - return new {{LINKED_HASH_MAP}}(); - ''' - // Just an example to make it clear this != an actual type. - // - // Can be used to do automatic import prefixing or rewrites. - ..specs.addAll({ - 'LINKED_HASH_MAP': () => linkedHashMap, - })), - ), + new Method((b) => b + ..name = 'foo' + ..body = new Code.scope( + (a) => 'return new ${a(linkedHashMap)}();', + )), equalsDart(r''' foo() { return new LinkedHashMap(); @@ -202,8 +185,8 @@ void main() { ..requiredParameters.add( new Parameter((b) => b ..name = 'i' - ..annotations.add(new Annotation( - (a) => a..code = new Code((b) => b..code = 'deprecated')))), + ..annotations.add( + new Annotation((a) => a..code = const Code('deprecated')))), ), ), equalsDart(r''' @@ -297,7 +280,7 @@ void main() { ..optionalParameters.add( new Parameter((b) => b ..name = 'i' - ..defaultTo = new Code((b) => b.code = '0')), + ..defaultTo = const Code('0')), ), ), equalsDart(r''' @@ -332,7 +315,7 @@ void main() { new Parameter((b) => b ..named = true ..name = 'i' - ..defaultTo = new Code((b) => b.code = '0')), + ..defaultTo = const Code('0')), ), ), equalsDart(r''' From 933d3f5f820158c6d8e84fbd4f39633e07bce861 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 12 Oct 2017 16:04:09 -0700 Subject: [PATCH 066/271] Even more expression/code support (dart-lang/code_builder#132) * Initial support for Expression(s). * More in changelog. * Add context everywhere. * All tests passing. * More cleanup. * More expression work. --- pkgs/code_builder/CHANGELOG.md | 3 + pkgs/code_builder/lib/code_builder.dart | 18 ++- pkgs/code_builder/lib/src/emitter.dart | 2 +- .../lib/src/specs/annotation.dart | 5 +- pkgs/code_builder/lib/src/specs/code.dart | 2 +- .../lib/src/specs/expression.dart | 136 ++++++++++++++++++ .../lib/src/specs/expression/binary.dart | 19 +++ .../lib/src/specs/expression/code.dart | 19 +++ .../lib/src/specs/expression/invoke.dart | 32 +++++ .../literal.dart} | 69 +++------ pkgs/code_builder/lib/src/specs/field.dart | 12 +- pkgs/code_builder/lib/src/specs/method.dart | 12 +- .../code_builder/lib/src/specs/reference.dart | 9 +- .../lib/src/specs/type_reference.dart | 9 +- pkgs/code_builder/pubspec.yaml | 6 +- .../test/specs/code/expression_test.dart | 42 ++++++ 16 files changed, 305 insertions(+), 90 deletions(-) create mode 100644 pkgs/code_builder/lib/src/specs/expression.dart create mode 100644 pkgs/code_builder/lib/src/specs/expression/binary.dart create mode 100644 pkgs/code_builder/lib/src/specs/expression/code.dart create mode 100644 pkgs/code_builder/lib/src/specs/expression/invoke.dart rename pkgs/code_builder/lib/src/specs/{code/expression.dart => expression/literal.dart} (51%) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 322ecf20a..b01d3d780 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -12,7 +12,9 @@ * `SpecVisitor`'s methods all have an optional `[T context]` parameter now. * This makes it much easier to avoid allocating extra `StringBuffer`s. * Removed `SimpleSpecVisitor` (it was unused). +* Removed `implements Reference` from `Method` and `Field`; not a lot of value. * `equalsDart` removes insignificant white space before comparing results. + * In process of adding classes/methods for writing bodies of `Code` fluently: * `Expression` * `LiteralExpression` @@ -21,6 +23,7 @@ * `literalBool` * `literalTrue` * `literalFalse` + * `literalList` * `const Code(staticString)` * `const Code.scope((allocate) => '')` diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index bc4dfdb7c..cf41252d9 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -9,17 +9,27 @@ 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 Code, StaticCode, ScopedCode; -export 'src/specs/code/expression.dart' +export 'src/specs/constructor.dart' show Constructor, ConstructorBuilder; +export 'src/specs/directive.dart' + show Directive, DirectiveType, DirectiveBuilder; +export 'src/specs/expression.dart' show + BinaryExpression, + CodeExpression, Expression, + ExpressionEmitter, + ExpressionVisitor, + InvokeExpression, + InvokeExpressionType, + LiteralExpression, + LiteralListExpression, literal, literalNull, literalBool, + literalList, + literalConstList, literalTrue, literalFalse; -export 'src/specs/constructor.dart' show Constructor, ConstructorBuilder; -export 'src/specs/directive.dart' - show Directive, DirectiveType, DirectiveBuilder; export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; export 'src/specs/file.dart' show File, FileBuilder; export 'src/specs/method.dart' diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index dba36a0bc..6a4141a8d 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -7,9 +7,9 @@ import 'base.dart'; import 'specs/annotation.dart'; import 'specs/class.dart'; import 'specs/code.dart'; -import 'specs/code/expression.dart'; import 'specs/constructor.dart'; import 'specs/directive.dart'; +import 'specs/expression.dart'; import 'specs/field.dart'; import 'specs/file.dart'; import 'specs/method.dart'; diff --git a/pkgs/code_builder/lib/src/specs/annotation.dart b/pkgs/code_builder/lib/src/specs/annotation.dart index 9b74d4537..83c5f85ec 100644 --- a/pkgs/code_builder/lib/src/specs/annotation.dart +++ b/pkgs/code_builder/lib/src/specs/annotation.dart @@ -24,10 +24,7 @@ abstract class Annotation Code get code; @override - R accept( - SpecVisitor visitor, [ - R context, - ]) => + R accept(SpecVisitor visitor, [R context]) => visitor.visitAnnotation(this, context); } diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index b4a7afb7d..c29051676 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -14,7 +14,7 @@ import '../visitors.dart'; /// Returns a scoped symbol to [Reference], with an import prefix if needed. /// /// This is short-hand for [Allocator.allocate] in most implementations. -typedef Allocate = String Function(Reference reference); +typedef String Allocate(Reference reference); /// Represents arbitrary Dart code (either expressions or statements). /// diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart new file mode 100644 index 000000000..7827db5fe --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -0,0 +1,136 @@ +// 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. + +library code_builder.src.specs.expression; + +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../visitors.dart'; +import 'code.dart'; +import 'reference.dart'; + +part 'expression/binary.dart'; +part 'expression/code.dart'; +part 'expression/invoke.dart'; +part 'expression/literal.dart'; + +/// Represents a Dart expression. +/// +/// See various concrete implementations for details. +abstract class Expression implements Spec { + const Expression(); + + @override + R accept(covariant ExpressionVisitor visitor, [R context]); + + /// Returns the result of [this] `&&` [other]. + Expression and(Expression other) { + return new BinaryExpression._(toExpression(), other, '&&'); + } + + /// Call this expression as a method. + Expression call() { + return new InvokeExpression._(this); + } + + /// Returns a new instance of this expression. + Expression newInstance() { + return new InvokeExpression._new(this); + } + + /// Returns a const instance of this expression. + Expression constInstance() { + return new InvokeExpression._const(this); + } + + /// May be overriden to support other types implementing [Expression]. + @visibleForOverriding + Expression toExpression() => this; +} + +/// Knowledge of different types of expressions in Dart. +/// +/// **INTERNAL ONLY**. +abstract class ExpressionVisitor implements SpecVisitor { + T visitBinaryExpression(BinaryExpression expression, [T context]); + T visitCodeExpression(CodeExpression expression, [T context]); + T visitInvokeExpression(InvokeExpression expression, [T context]); + T visitLiteralExpression(LiteralExpression expression, [T context]); + T visitLiteralListExpression(LiteralListExpression expression, [T context]); +} + +/// Knowledge of how to write valid Dart code from [ExpressionVisitor]. +/// +/// **INTERNAL ONLY**. +abstract class ExpressionEmitter implements ExpressionVisitor { + @override + visitBinaryExpression(BinaryExpression expression, [StringSink output]) { + output ??= new StringBuffer(); + return output + ..write(expression.left.accept(this)) + ..write(' ') + ..write(expression.operator) + ..write(' ') + ..write(expression.right.accept(this)); + } + + @override + visitCodeExpression(CodeExpression expression, [StringSink output]) { + output ??= new StringBuffer(); + final visitor = this as CodeVisitor; + return expression.code.accept(visitor, output); + } + + @override + visitInvokeExpression(InvokeExpression expression, [StringSink output]) { + output ??= new StringBuffer(); + switch (expression.type) { + case InvokeExpressionType.newInstance: + output.write('new '); + break; + case InvokeExpressionType.constInstance: + output.write('const '); + break; + } + expression.target.accept(this, output); + return output..write('()'); + } + + @override + visitLiteralExpression(LiteralExpression expression, [StringSink output]) { + output ??= new StringBuffer(); + return output..write(expression.literal); + } + + @override + visitLiteralListExpression( + LiteralListExpression expression, [ + StringSink output, + ]) { + output ??= new StringBuffer(); + if (expression.isConst) { + output.write('const '); + } + if (expression.type != null) { + output.write('<'); + expression.type.accept(this, output); + output.write('>'); + } + output.write('['); + // ignore: prefer_final_locals + for (var i = 0, l = expression.values.length; i < l; i++) { + final value = expression.values[i]; + if (value is Spec) { + value.accept(this, output); + } else { + literal(value).accept(this, output); + } + if (i < l - 1) { + output.write(', '); + } + } + return output..write(']'); + } +} diff --git a/pkgs/code_builder/lib/src/specs/expression/binary.dart b/pkgs/code_builder/lib/src/specs/expression/binary.dart new file mode 100644 index 000000000..8464bd004 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/expression/binary.dart @@ -0,0 +1,19 @@ +// 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. + +part of code_builder.src.specs.expression; + +/// Represents two expressions ([left] and [right]) and an [operator]. +class BinaryExpression extends Expression { + final Expression left; + final Expression right; + final String operator; + + const BinaryExpression._(this.left, this.right, this.operator); + + @override + R accept(ExpressionVisitor visitor, [R context]) { + return visitor.visitBinaryExpression(this, context); + } +} diff --git a/pkgs/code_builder/lib/src/specs/expression/code.dart b/pkgs/code_builder/lib/src/specs/expression/code.dart new file mode 100644 index 000000000..aa79b838f --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/expression/code.dart @@ -0,0 +1,19 @@ +// 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. + +part of code_builder.src.specs.expression; + +/// Represents a [Code] block as an [Expression]. +class CodeExpression extends Expression { + final Code code; + + /// **INTERNAL ONLY**: Used to wrap [Code] as an [Expression]. + @visibleForTesting + const CodeExpression(this.code); + + @override + R accept(ExpressionVisitor visitor, [R context]) { + return visitor.visitCodeExpression(this, context); + } +} diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart new file mode 100644 index 000000000..207d657db --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -0,0 +1,32 @@ +// 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. + +part of code_builder.src.specs.expression; + +/// Represents invoking [target] as a method with arguments. +class InvokeExpression extends Expression { + /// Target of the method invocation. + final Expression target; + + /// Optional; type of invocation. + final InvokeExpressionType type; + + const InvokeExpression._(this.target) : type = null; + + const InvokeExpression._new(this.target) + : type = InvokeExpressionType.newInstance; + + const InvokeExpression._const(this.target) + : type = InvokeExpressionType.constInstance; + + @override + R accept(ExpressionVisitor visitor, [R context]) { + return visitor.visitInvokeExpression(this, context); + } +} + +enum InvokeExpressionType { + newInstance, + constInstance, +} diff --git a/pkgs/code_builder/lib/src/specs/code/expression.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart similarity index 51% rename from pkgs/code_builder/lib/src/specs/code/expression.dart rename to pkgs/code_builder/lib/src/specs/expression/literal.dart index 9b17205d3..60b6bd8e0 100644 --- a/pkgs/code_builder/lib/src/specs/code/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -2,50 +2,7 @@ // 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 '../../base.dart'; -import '../../visitors.dart'; - -/// Represents a Dart expression. -/// -/// See various concrete implementations for details. -abstract class Expression implements Spec { - const Expression(); - - @override - R accept(covariant ExpressionVisitor visitor, [R context]); - - Expression and(Expression other) => new BinaryExpression._(this, other, '&&'); -} - -/// Knowledge of different types of expressions in Dart. -/// -/// **INTERNAL ONLY**. -abstract class ExpressionVisitor implements SpecVisitor { - T visitBinaryExpression(BinaryExpression expression, [T context]); - T visitLiteralExpression(LiteralExpression expression, [T context]); -} - -/// Knowledge of how to write valid Dart code from [ExpressionVisitor]. -/// -/// **INTERNAL ONLY**. -abstract class ExpressionEmitter implements ExpressionVisitor { - @override - visitBinaryExpression(BinaryExpression expression, [StringSink output]) { - output ??= new StringBuffer(); - return output - ..write(expression.left.accept(this)) - ..write(' ') - ..write(expression.operator) - ..write(' ') - ..write(expression.right.accept(this)); - } - - @override - visitLiteralExpression(LiteralExpression expression, [StringSink output]) { - output ??= new StringBuffer(); - return output..write(expression.literal); - } -} +part of code_builder.src.specs.expression; /// Converts a runtime Dart [literal] value into an [Expression]. /// @@ -75,6 +32,16 @@ Expression literalBool(bool value) => value ? literalTrue : literalFalse; /// Represents the literal value `null`. const Expression literalNull = const LiteralExpression._('null'); +/// Creates a literal list expression from [values]. +LiteralListExpression literalList(List values, [Reference type]) { + return new LiteralListExpression._(false, values, type); +} + +/// Creates a literal `const` list expression from [values]. +LiteralListExpression literalConstList(List values, [Reference type]) { + return new LiteralListExpression._(true, values, type); +} + /// Represents a literal value in Dart source code. /// /// For example, `new LiteralExpression('null')` should emit `null`. @@ -83,6 +50,7 @@ const Expression literalNull = const LiteralExpression._('null'); /// * [literal] /// * [literalBool] and [literalTrue], [literalFalse] /// * [literalNull] +/// * [literalList] and [literalConstList] class LiteralExpression extends Expression { final String literal; @@ -94,16 +62,15 @@ class LiteralExpression extends Expression { } } -/// Represents two expressions ([left] and [right]) and an [operator]. -class BinaryExpression extends Expression { - final Expression left; - final Expression right; - final String operator; +class LiteralListExpression extends Expression { + final bool isConst; + final List values; + final Reference type; - const BinaryExpression._(this.left, this.right, this.operator); + const LiteralListExpression._(this.isConst, this.values, this.type); @override R accept(ExpressionVisitor visitor, [R context]) { - return visitor.visitBinaryExpression(this, context); + return visitor.visitLiteralListExpression(this, context); } } diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index 96672ecfa..661537a36 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -15,14 +15,13 @@ import '../visitors.dart'; import 'annotation.dart'; import 'code.dart'; import 'reference.dart'; -import 'type_reference.dart'; part 'field.g.dart'; @immutable abstract class Field extends Object with HasAnnotations, HasDartDocs - implements Built, Reference, Spec { + implements Built, Spec { factory Field([void updates(FieldBuilder b)]) = _$Field; Field._(); @@ -50,21 +49,12 @@ abstract class Field extends Object FieldModifier get modifier; - @override - String get symbol => name; - - @override - String get url => null; - @override R accept( SpecVisitor visitor, [ R context, ]) => visitor.visitField(this, context); - - @override - TypeReference toType() => throw new UnsupportedError(''); } enum FieldModifier { diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 3422192db..3734758ff 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -16,7 +16,6 @@ import '../visitors.dart'; import 'annotation.dart'; import 'code.dart'; import 'reference.dart'; -import 'type_reference.dart'; part 'method.g.dart'; @@ -25,7 +24,7 @@ final Reference _$void = const Reference('void'); @immutable abstract class Method extends Object with HasAnnotations, HasGenerics, HasDartDocs - implements Built, Reference, Spec { + implements Built, Spec { factory Method([void updates(MethodBuilder b)]) = _$Method; factory Method.returnsVoid([void updates(MethodBuilder b)]) { @@ -83,21 +82,12 @@ abstract class Method extends Object @nullable Reference get returns; - @override - String get symbol => name; - - @override - String get url => null; - @override R accept( SpecVisitor visitor, [ R context, ]) => visitor.visitMethod(this, context); - - @override - TypeReference toType() => throw new UnsupportedError(''); } abstract class MethodBuilder extends Object diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 1e2514c2d..1be28f059 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -9,6 +9,8 @@ import 'package:meta/meta.dart'; import '../base.dart'; import '../visitors.dart'; +import 'code.dart'; +import 'expression.dart'; import 'type_reference.dart'; /// A reference to [symbol], such as a class, or top-level method or field. @@ -16,7 +18,7 @@ import 'type_reference.dart'; /// References can be collected and collated in order to automatically generate /// `import` statements for all used symbols. @immutable -class Reference implements Spec { +class Reference extends Expression implements Spec { /// Relative, `package:` or `dart:` URL of the library. /// /// May be omitted (`null`) in order to express "same library". @@ -42,6 +44,11 @@ class Reference implements Spec { bool operator ==(Object o) => o is Reference && o.url == url && o.symbol == symbol; + @override + Expression toExpression() { + return new CodeExpression(new Code.scope((a) => a(this))); + } + @override String toString() => (newBuiltValueToStringHelper('Reference') ..add('url', url) diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index 5dfb9fda3..68eedb110 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -11,12 +11,14 @@ import 'package:meta/meta.dart'; import '../base.dart'; import '../mixins/generics.dart'; import '../visitors.dart'; +import 'code.dart'; +import 'expression.dart'; import 'reference.dart'; part 'type_reference.g.dart'; @immutable -abstract class TypeReference extends Object +abstract class TypeReference extends Expression with HasGenerics implements Built, Reference, Spec { factory TypeReference([ @@ -46,6 +48,11 @@ abstract class TypeReference extends Object ]) => visitor.visitType(this, context); + @override + Expression toExpression() { + return new CodeExpression(new Code.scope((a) => a(this))); + } + @override TypeReference toType() => this; } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 0c95c170e..38ac24b6a 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -5,7 +5,7 @@ author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=1.22.0 <2.0.0' + sdk: '>=1.24.0 <2.0.0' dependencies: built_collection: ^1.0.0 @@ -20,7 +20,3 @@ dev_dependencies: io: '>=0.1.0 <0.3.0' source_gen: '^0.7.0' test: ^0.12.0 - -transformers: - - test/pub_serve: - $include: test/**_test.dart diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index c9d44d75b..a14961868 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -13,4 +13,46 @@ void main() { test('should emit a && expression', () { expect(literalTrue.and(literalFalse), equalsDart('true && false')); }); + + test('should emit a list', () { + expect(literalList([]), equalsDart('[]')); + }); + + test('should emit a const list', () { + expect(literalConstList([]), equalsDart('const []')); + }); + + test('should emit a typed list', () { + expect(literalList([], const Reference('int')), equalsDart('[]')); + }); + + test('should emit a list of other literals and expressions', () { + expect( + literalList([ + literalList([]), + literalTrue, + literalNull, + const Reference('Map').toExpression().newInstance() + ]), + equalsDart('[[], true, null, new Map()]'), + ); + }); + + test('should emit a type as an expression', () { + expect(const Reference('Map').toExpression(), equalsDart('Map')); + }); + + test('should emit a scoped type as an expression', () { + expect( + const Reference('Foo', 'package:foo/foo.dart').toExpression(), + equalsDart('_1.Foo', new DartEmitter(new Allocator.simplePrefixing())), + ); + }); + + test('should emit invoking new Type()', () { + expect( + const Reference('Map').toExpression().newInstance(), + equalsDart('new Map()'), + ); + }); } From 3fbfc01d2982d0376a2918416efde4ee0086093a Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 13 Oct 2017 08:37:22 -0700 Subject: [PATCH 067/271] Boom expression args (dart-lang/code_builder#133) * Initial support for Expression(s). * More in changelog. * Add context everywhere. * All tests passing. * More cleanup. * More expression work. * Improve calls, add property access. * Update README. * Actually update it. * Be nice to users. * Add literalString, literalMap. --- pkgs/code_builder/CHANGELOG.md | 22 ++- pkgs/code_builder/README.md | 8 +- pkgs/code_builder/example/animal.dart | 2 +- pkgs/code_builder/example/scope.dart | 4 +- pkgs/code_builder/lib/code_builder.dart | 5 +- pkgs/code_builder/lib/src/emitter.dart | 29 ++++ pkgs/code_builder/lib/src/specs/code.dart | 3 +- .../lib/src/specs/expression.dart | 139 +++++++++++++++--- .../lib/src/specs/expression/binary.dart | 8 +- .../lib/src/specs/expression/invoke.dart | 25 +++- .../lib/src/specs/expression/literal.dart | 54 +++++++ .../code_builder/lib/src/specs/reference.dart | 5 + pkgs/code_builder/test/allocator_test.dart | 14 +- .../code_builder/test/e2e/injection_test.dart | 12 +- pkgs/code_builder/test/specs/class_test.dart | 12 +- .../test/specs/code/expression_test.dart | 99 +++++++++++-- pkgs/code_builder/test/specs/field_test.dart | 2 +- pkgs/code_builder/test/specs/file_test.dart | 9 +- pkgs/code_builder/test/specs/method_test.dart | 16 +- 19 files changed, 380 insertions(+), 88 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index b01d3d780..51465cfbe 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -8,14 +8,10 @@ * 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`. -* `SpecVisitor`'s methods all have an optional `[T context]` parameter now. - * This makes it much easier to avoid allocating extra `StringBuffer`s. -* Removed `SimpleSpecVisitor` (it was unused). -* Removed `implements Reference` from `Method` and `Field`; not a lot of value. -* `equalsDart` removes insignificant white space before comparing results. - -* In process of adding classes/methods for writing bodies of `Code` fluently: +* Added many classes/methods for writing bodies of `Code` fluently: * `Expression` * `LiteralExpression` * `literal` @@ -23,10 +19,20 @@ * `literalBool` * `literalTrue` * `literalFalse` - * `literalList` + * `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`'s methods all have an optional `[T context]` parameter now. + * This makes it much easier to avoid allocating extra `StringBuffer`s. +* `equalsDart` removes insignificant white space before comparing results. + ## 2.0.0-alpha+1 * Removed `Reference.localScope`. Just use `Reference(symbol)` now. diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 0ecfd00aa..b06de52d2 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -40,11 +40,11 @@ import 'package:dart_style/dart_style.dart'; void main() { final animal = new Class((b) => b ..name = 'Animal' - ..extend = const Reference('Organism').toType() + ..extend = refer('Organism').toType() ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' ..lambda = true - ..body = new Code((b) => b..code = 'print(\'Yum\')')))); + ..body = const Code('print(\'Yum\')')))); final emitter = const DartEmitter(); print(new DartFormatter().format('${animal.accept(emitter)}')); } @@ -70,11 +70,11 @@ void main() { new Method((b) => b ..body = new Code((b) => b.code = '') ..name = 'doThing' - ..returns = const Reference('Thing', 'package:a/a.dart')), + ..returns = refer('Thing', 'package:a/a.dart')), new Method((b) => b ..body = new Code((b) => b..code = '') ..name = 'doOther' - ..returns = const Reference('Other', 'package:b/b.dart')), + ..returns = refer('Other', 'package:b/b.dart')), ])); final emitter = new DartEmitter(new Allocator.simplePrefixing()); print(new DartFormatter().format('${library.accept(emitter)}')); diff --git a/pkgs/code_builder/example/animal.dart b/pkgs/code_builder/example/animal.dart index 9bee3b025..15fd3a6c9 100644 --- a/pkgs/code_builder/example/animal.dart +++ b/pkgs/code_builder/example/animal.dart @@ -8,7 +8,7 @@ import 'package:dart_style/dart_style.dart'; void main() { final animal = new Class((b) => b ..name = 'Animal' - ..extend = const Reference('Organism') + ..extend = refer('Organism') ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' ..lambda = true diff --git a/pkgs/code_builder/example/scope.dart b/pkgs/code_builder/example/scope.dart index 9ba85d602..90207a8a7 100644 --- a/pkgs/code_builder/example/scope.dart +++ b/pkgs/code_builder/example/scope.dart @@ -10,11 +10,11 @@ void main() { new Method((b) => b ..body = const Code('') ..name = 'doThing' - ..returns = const Reference('Thing', 'package:a/a.dart')), + ..returns = refer('Thing', 'package:a/a.dart')), new Method((b) => b ..body = const Code('') ..name = 'doOther' - ..returns = const Reference('Other', 'package:b/b.dart')), + ..returns = refer('Other', 'package:b/b.dart')), ])); final emitter = new DartEmitter(new Allocator.simplePrefixing()); print(new DartFormatter().format('${library.accept(emitter)}')); diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index cf41252d9..c52a07855 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -28,6 +28,9 @@ export 'src/specs/expression.dart' literalBool, literalList, literalConstList, + literalMap, + literalConstMap, + literalString, literalTrue, literalFalse; export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; @@ -40,5 +43,5 @@ export 'src/specs/method.dart' MethodType, Parameter, ParameterBuilder; -export 'src/specs/reference.dart' show Reference; +export 'src/specs/reference.dart' show refer, Reference; export 'src/specs/type_reference.dart' show TypeReference, TypeReferenceBuilder; diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 6a4141a8d..d408571a4 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -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:meta/meta.dart'; + import 'allocator.dart'; import 'base.dart'; import 'specs/annotation.dart'; @@ -17,6 +19,33 @@ import 'specs/reference.dart'; import 'specs/type_reference.dart'; import 'visitors.dart'; +/// Helper method improving on [StringSink.writeAll]. +/// +/// For every `Spec` in [elements], executing [visit]. +/// +/// If [elements] is at least 2 elements, inserts [separator] delimiting them. +@visibleForTesting +void visitAll( + Iterable elements, + StringSink output, + void visit(T element), [ + String separator = ', ', +]) { + // Basically, this whole method is an improvement on + // output.writeAll(specs.map((s) => s.accept(visitor)); + // + // ... which would allocate more StringBuffer(s) for a one-time use. + if (elements.isEmpty) { + return; + } + final iterator = elements.iterator..moveNext(); + visit(iterator.current); + while (iterator.moveNext()) { + output.write(separator); + visit(iterator.current); + } +} + class DartEmitter extends Object with CodeEmitter, ExpressionEmitter implements SpecVisitor { diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index c29051676..afbd5daee 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -8,9 +8,10 @@ import 'package:meta/meta.dart'; import '../allocator.dart'; import '../base.dart'; -import '../specs/reference.dart'; import '../visitors.dart'; +import 'reference.dart'; + /// Returns a scoped symbol to [Reference], with an import prefix if needed. /// /// This is short-hand for [Allocator.allocate] in most implementations. diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 7827db5fe..5daf622bb 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -7,6 +7,7 @@ library code_builder.src.specs.expression; import 'package:meta/meta.dart'; import '../base.dart'; +import '../emitter.dart'; import '../visitors.dart'; import 'code.dart'; import 'reference.dart'; @@ -25,24 +26,58 @@ abstract class Expression implements Spec { @override R accept(covariant ExpressionVisitor visitor, [R context]); + /// Returns the expression as a valid [Code] block. + Code asCode() => new _AsExpressionCode(this); + /// Returns the result of [this] `&&` [other]. Expression and(Expression other) { return new BinaryExpression._(toExpression(), other, '&&'); } /// Call this expression as a method. - Expression call() { - return new InvokeExpression._(this); + Expression call( + List positionalArguments, [ + Map namedArguments = const {}, + ]) { + return new InvokeExpression._( + this, + positionalArguments, + namedArguments, + ); + } + + /// Returns an expression accessing `.` on this expression. + Expression property(String name) { + return new BinaryExpression._( + this, + new LiteralExpression._(name), + '.', + false, + ); } /// Returns a new instance of this expression. - Expression newInstance() { - return new InvokeExpression._new(this); + Expression newInstance( + List positionalArguments, [ + Map namedArguments = const {}, + ]) { + return new InvokeExpression._new( + this, + positionalArguments, + namedArguments, + ); } /// Returns a const instance of this expression. - Expression constInstance() { - return new InvokeExpression._const(this); + Expression constInstance( + List positionalArguments, [ + Map namedArguments = const {}, + ]) { + return new InvokeExpression._const( + this, + positionalArguments, + namedArguments, + ); } /// May be overriden to support other types implementing [Expression]. @@ -50,6 +85,18 @@ abstract class Expression implements Spec { Expression toExpression() => this; } +/// Represents a [code] block that wraps an [Expression]. +class _AsExpressionCode implements Code { + final Expression code; + + const _AsExpressionCode(this.code); + + @override + R accept(CodeVisitor visitor, [R context]) { + return code.accept(visitor as ExpressionVisitor, context); + } +} + /// Knowledge of different types of expressions in Dart. /// /// **INTERNAL ONLY**. @@ -59,6 +106,7 @@ abstract class ExpressionVisitor implements SpecVisitor { T visitInvokeExpression(InvokeExpression expression, [T context]); T visitLiteralExpression(LiteralExpression expression, [T context]); T visitLiteralListExpression(LiteralListExpression expression, [T context]); + T visitLiteralMapExpression(LiteralMapExpression expression, [T context]); } /// Knowledge of how to write valid Dart code from [ExpressionVisitor]. @@ -68,12 +116,16 @@ abstract class ExpressionEmitter implements ExpressionVisitor { @override visitBinaryExpression(BinaryExpression expression, [StringSink output]) { output ??= new StringBuffer(); - return output - ..write(expression.left.accept(this)) - ..write(' ') - ..write(expression.operator) - ..write(' ') - ..write(expression.right.accept(this)); + expression.left.accept(this, output); + if (expression.addSpace) { + output.write(' '); + } + output.write(expression.operator); + if (expression.addSpace) { + output.write(' '); + } + expression.right.accept(this, output); + return output; } @override @@ -95,7 +147,19 @@ abstract class ExpressionEmitter implements ExpressionVisitor { break; } expression.target.accept(this, output); - return output..write('()'); + output.write('('); + visitAll(expression.positionalArguments, output, (spec) { + spec.accept(this, output); + }); + if (expression.positionalArguments.isNotEmpty && + expression.namedArguments.isNotEmpty) { + output.write(', '); + } + visitAll(expression.namedArguments.keys, output, (name) { + output..write(name)..write(': '); + expression.namedArguments[name].accept(this, output); + }); + return output..write(')'); } @override @@ -104,6 +168,14 @@ abstract class ExpressionEmitter implements ExpressionVisitor { return output..write(expression.literal); } + void _acceptLiteral(Object literalOrSpec, StringSink output) { + if (literalOrSpec is Spec) { + literalOrSpec.accept(this, output); + return; + } + literal(literalOrSpec).accept(this, output); + } + @override visitLiteralListExpression( LiteralListExpression expression, [ @@ -119,18 +191,39 @@ abstract class ExpressionEmitter implements ExpressionVisitor { output.write('>'); } output.write('['); - // ignore: prefer_final_locals - for (var i = 0, l = expression.values.length; i < l; i++) { - final value = expression.values[i]; - if (value is Spec) { - value.accept(this, output); + visitAll(expression.values, output, (value) { + _acceptLiteral(value, output); + }); + return output..write(']'); + } + + @override + visitLiteralMapExpression( + LiteralMapExpression expression, [ + StringSink output, + ]) { + output ??= new StringBuffer(); + if (expression.isConst) { + output.write('const '); + } + if (expression.keyType != null) { + output.write('<'); + expression.keyType.accept(this, output); + output.write(', '); + if (expression.valueType == null) { + const Reference('dynamic', 'dart:core').accept(this, output); } else { - literal(value).accept(this, output); - } - if (i < l - 1) { - output.write(', '); + expression.valueType.accept(this, output); } + output.write('>'); } - return output..write(']'); + output.write('{'); + visitAll(expression.values.keys, output, (key) { + final value = expression.values[key]; + _acceptLiteral(key, output); + output.write(': '); + _acceptLiteral(value, output); + }); + return output..write('}'); } } diff --git a/pkgs/code_builder/lib/src/specs/expression/binary.dart b/pkgs/code_builder/lib/src/specs/expression/binary.dart index 8464bd004..aefd86dde 100644 --- a/pkgs/code_builder/lib/src/specs/expression/binary.dart +++ b/pkgs/code_builder/lib/src/specs/expression/binary.dart @@ -9,8 +9,14 @@ class BinaryExpression extends Expression { final Expression left; final Expression right; final String operator; + final bool addSpace; - const BinaryExpression._(this.left, this.right, this.operator); + const BinaryExpression._( + this.left, + this.right, + this.operator, [ + this.addSpace = true, + ]); @override R accept(ExpressionVisitor visitor, [R context]) { diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index 207d657db..b9e0edb0b 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -12,12 +12,29 @@ class InvokeExpression extends Expression { /// Optional; type of invocation. final InvokeExpressionType type; - const InvokeExpression._(this.target) : type = null; - - const InvokeExpression._new(this.target) + final List positionalArguments; + + final Map namedArguments; + + const InvokeExpression._( + this.target, + this.positionalArguments, [ + this.namedArguments = const {}, + ]) + : type = null; + + const InvokeExpression._new( + this.target, + this.positionalArguments, [ + this.namedArguments = const {}, + ]) : type = InvokeExpressionType.newInstance; - const InvokeExpression._const(this.target) + const InvokeExpression._const( + this.target, + this.positionalArguments, [ + this.namedArguments = const {}, + ]) : type = InvokeExpressionType.constInstance; @override diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 60b6bd8e0..fc02d80df 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -11,6 +11,15 @@ Expression literal(Object literal, {Expression onError(Object value)}) { if (literal is bool) { return literalBool(literal); } + if (literal is num) { + return literalNum(literal); + } + if (literal is String) { + return literalString(literal); + } + if (literal is List) { + return literalList(literal); + } if (literal == null) { return literalNull; } @@ -32,6 +41,14 @@ Expression literalBool(bool value) => value ? literalTrue : literalFalse; /// Represents the literal value `null`. const Expression literalNull = const LiteralExpression._('null'); +/// Create a literal expression from a number [value]. +Expression literalNum(num value) => new LiteralExpression._('$value'); + +/// Create a literal expression from a string [value]. +/// +/// **NOTE**: The string is always formatted `''`. +Expression literalString(String value) => new LiteralExpression._("'$value'"); + /// Creates a literal list expression from [values]. LiteralListExpression literalList(List values, [Reference type]) { return new LiteralListExpression._(false, values, type); @@ -42,6 +59,24 @@ LiteralListExpression literalConstList(List values, [Reference type]) { return new LiteralListExpression._(true, values, type); } +/// Create a literal map expression from [values]. +LiteralMapExpression literalMap( + Map values, [ + Reference keyType, + Reference valueType, +]) { + return new LiteralMapExpression._(false, values, keyType, valueType); +} + +/// Create a literal `const` map expression from [values]. +LiteralMapExpression literalConstMap( + Map values, [ + Reference keyType, + Reference valueType, +]) { + return new LiteralMapExpression._(true, values, keyType, valueType); +} + /// Represents a literal value in Dart source code. /// /// For example, `new LiteralExpression('null')` should emit `null`. @@ -74,3 +109,22 @@ class LiteralListExpression extends Expression { return visitor.visitLiteralListExpression(this, context); } } + +class LiteralMapExpression extends Expression { + final bool isConst; + final Map values; + final Reference keyType; + final Reference valueType; + + const LiteralMapExpression._( + this.isConst, + this.values, + this.keyType, + this.valueType, + ); + + @override + R accept(ExpressionVisitor visitor, [R context]) { + return visitor.visitLiteralMapExpression(this, context); + } +} diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 1be28f059..78aa22092 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -13,6 +13,11 @@ import 'code.dart'; import 'expression.dart'; import 'type_reference.dart'; +/// Short-hand for `new Reference(symbol, url)`. +Reference refer(String symbol, [String url]) { + return new Reference(symbol, url); +} + /// A reference to [symbol], such as a class, or top-level method or field. /// /// References can be collected and collated in order to automatically generate diff --git a/pkgs/code_builder/test/allocator_test.dart b/pkgs/code_builder/test/allocator_test.dart index dbd366df8..0b7dab582 100644 --- a/pkgs/code_builder/test/allocator_test.dart +++ b/pkgs/code_builder/test/allocator_test.dart @@ -11,14 +11,14 @@ void main() { test('should return the exact (non-prefixed) symbol', () { allocator = new Allocator(); - expect(allocator.allocate(const Reference('Foo', 'package:foo')), 'Foo'); + expect(allocator.allocate(refer('Foo', 'package:foo')), 'Foo'); }); test('should collect import URLs', () { allocator = new Allocator() - ..allocate(const Reference('List', 'dart:core')) - ..allocate(const Reference('LinkedHashMap', 'dart:collection')) - ..allocate(const Reference('someSymbol')); + ..allocate(refer('List', 'dart:core')) + ..allocate(refer('LinkedHashMap', 'dart:collection')) + ..allocate(refer('someSymbol')); expect(allocator.imports.map((d) => d.url), [ 'dart:core', 'dart:collection', @@ -27,18 +27,18 @@ void main() { test('.none should do nothing', () { allocator = Allocator.none; - expect(allocator.allocate(const Reference('Foo', 'package:foo')), 'Foo'); + expect(allocator.allocate(refer('Foo', 'package:foo')), 'Foo'); expect(allocator.imports, isEmpty); }); test('.simplePrefixing should add import prefixes', () { allocator = new Allocator.simplePrefixing(); expect( - allocator.allocate(const Reference('List', 'dart:core')), + allocator.allocate(refer('List', 'dart:core')), 'List', ); expect( - allocator.allocate(const Reference('LinkedHashMap', 'dart:collection')), + allocator.allocate(refer('LinkedHashMap', 'dart:collection')), '_1.LinkedHashMap', ); expect(allocator.imports.map((d) => '${d.url} as ${d.as}'), [ diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index 36ee5317e..dc45ef40c 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -8,9 +8,9 @@ import 'package:test/test.dart'; void main() { test('should generate a complex generated file', () { // Imports from an existing Dart library. - final $App = const Reference('App', 'package:app/app.dart'); - final $Module = const Reference('Module', 'package:app/module.dart'); - final $Thing = const Reference('Thing', 'package:app/thing.dart'); + final $App = refer('App', 'package:app/app.dart'); + final $Module = refer('Module', 'package:app/module.dart'); + final $Thing = refer('Thing', 'package:app/thing.dart'); final clazz = new ClassBuilder() ..name = 'Injector' @@ -25,8 +25,10 @@ void main() { ..toThis = true)))) ..methods.add(new Method((b) => b ..name = 'getThing' - ..body = new Code.scope( - (a) => 'new ${a($Thing)}(_module.get1(), _module.get2())') + ..body = $Thing.newInstance([ + refer('_module').property('get1').call([]), + refer('_module').property('get2').call([]), + ]).asCode() ..lambda = true ..returns = $Thing ..annotations diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 11a607f6d..54ba0a3e9 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -45,7 +45,7 @@ void main() { }); test('should create a class with annotations', () { - final $deprecated = const Reference('deprecated'); + final $deprecated = refer('deprecated'); expect( new Class( (b) => b @@ -67,7 +67,7 @@ void main() { expect( new Class((b) => b ..name = 'List' - ..types.add(const Reference('T'))), + ..types.add(refer('T'))), equalsDart(r''' class List {} '''), @@ -80,8 +80,8 @@ void main() { (b) => b ..name = 'Map' ..types.addAll([ - const Reference('K'), - const Reference('V'), + refer('K'), + refer('V'), ]), ), equalsDart(r''' @@ -98,7 +98,7 @@ void main() { ..symbol = 'T' ..bound = new TypeReference((b) => b ..symbol = 'Comparable' - ..types.add(const Reference('T').toType()))))), + ..types.add(refer('T').toType()))))), equalsDart(r''' class Comparable> {} '''), @@ -237,7 +237,7 @@ void main() { ..name = 'Foo' ..constructors.add(new Constructor((b) => b ..factory = true - ..redirect = const Reference('_Foo')))), + ..redirect = refer('_Foo')))), equalsDart(r''' class Foo { factory Foo() = _Foo; diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index a14961868..a12323bb4 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -22,37 +22,114 @@ void main() { expect(literalConstList([]), equalsDart('const []')); }); - test('should emit a typed list', () { - expect(literalList([], const Reference('int')), equalsDart('[]')); + test('should emit an explicitly typed list', () { + expect(literalList([], refer('int')), equalsDart('[]')); + }); + + test('should emit a map', () { + expect(literalMap({}), equalsDart('{}')); + }); + + test('should emit a const map', () { + expect(literalConstMap({}), equalsDart('const {}')); + }); + + test('should emit an explicitly typed map', () { + expect( + literalMap({}, refer('int'), refer('bool')), + equalsDart('{}'), + ); + }); + + test('should emit a map of other literals and expressions', () { + expect( + literalMap({ + 1: 'one', + 2: refer('two'), + refer('three'): 3, + refer('Map').newInstance([]): null, + }), + equalsDart(r"{1: 'one', 2: two, three: 3, new Map(): null}"), + ); }); test('should emit a list of other literals and expressions', () { expect( - literalList([ - literalList([]), - literalTrue, - literalNull, - const Reference('Map').toExpression().newInstance() - ]), + literalList([[], true, null, refer('Map').newInstance([])]), equalsDart('[[], true, null, new Map()]'), ); }); test('should emit a type as an expression', () { - expect(const Reference('Map').toExpression(), equalsDart('Map')); + expect(refer('Map'), equalsDart('Map')); }); test('should emit a scoped type as an expression', () { expect( - const Reference('Foo', 'package:foo/foo.dart').toExpression(), + refer('Foo', 'package:foo/foo.dart'), equalsDart('_1.Foo', new DartEmitter(new Allocator.simplePrefixing())), ); }); test('should emit invoking new Type()', () { expect( - const Reference('Map').toExpression().newInstance(), + refer('Map').newInstance([]), equalsDart('new Map()'), ); }); + + test('should emit invoking a property accessor', () { + expect(refer('foo').property('bar'), equalsDart('foo.bar')); + }); + + test('should emit invoking a method with a single positional argument', () { + expect( + refer('foo').call([ + literal(1), + ]), + equalsDart('foo(1)'), + ); + }); + + test('should emit invoking a method with positional arguments', () { + expect( + refer('foo').call([ + literal(1), + literal(2), + literal(3), + ]), + equalsDart('foo(1, 2, 3)'), + ); + }); + + test('should emit invoking a method with a single named argument', () { + expect( + refer('foo').call([], { + 'bar': literal(1), + }), + equalsDart('foo(bar: 1)'), + ); + }); + + test('should emit invoking a method with named arguments', () { + expect( + refer('foo').call([], { + 'bar': literal(1), + 'baz': literal(2), + }), + equalsDart('foo(bar: 1, baz: 2)'), + ); + }); + + test('should emit invoking a method with positional and named arguments', () { + expect( + refer('foo').call([ + literal(1) + ], { + 'bar': literal(2), + 'baz': literal(3), + }), + equalsDart('foo(1, bar: 2, baz: 3)'), + ); + }); } diff --git a/pkgs/code_builder/test/specs/field_test.dart b/pkgs/code_builder/test/specs/field_test.dart index 3cd4fb768..2f132ea91 100644 --- a/pkgs/code_builder/test/specs/field_test.dart +++ b/pkgs/code_builder/test/specs/field_test.dart @@ -19,7 +19,7 @@ void main() { expect( new Field((b) => b ..name = 'foo' - ..type = const Reference('String')), + ..type = refer('String')), equalsDart(r''' String foo; '''), diff --git a/pkgs/code_builder/test/specs/file_test.dart b/pkgs/code_builder/test/specs/file_test.dart index fb32f60ad..cfdf3e286 100644 --- a/pkgs/code_builder/test/specs/file_test.dart +++ b/pkgs/code_builder/test/specs/file_test.dart @@ -7,7 +7,7 @@ import 'package:test/test.dart'; void main() { group('File', () { - const $linkedHashMap = const Reference('LinkedHashMap', 'dart:collection'); + final $LinkedHashMap = refer('LinkedHashMap', 'dart:collection'); test('should emit a source file with manual imports', () { expect( @@ -16,8 +16,7 @@ void main() { ..body.add(new Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ - ..assignment = - new Code.scope((a) => 'new ${a($linkedHashMap)}()')))), + ..assignment = $LinkedHashMap.newInstance([]).asCode()))), equalsDart(r''' import 'dart:collection'; @@ -84,7 +83,7 @@ void main() { ..name = 'test' ..modifier = FieldModifier.final$ ..assignment = - new Code.scope((a) => 'new ${a($linkedHashMap)}()')))), + new Code.scope((a) => 'new ${a($LinkedHashMap)}()')))), equalsDart(r''' import 'dart:collection'; @@ -100,7 +99,7 @@ void main() { ..name = 'test' ..modifier = FieldModifier.final$ ..assignment = - new Code.scope((a) => 'new ${a($linkedHashMap)}()')))), + new Code.scope((a) => 'new ${a($LinkedHashMap)}()')))), equalsDart(r''' import 'dart:collection' as _1; diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 91dd5f71e..f73f2fd38 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -83,7 +83,7 @@ void main() { expect( new Method((b) => b ..name = 'foo' - ..returns = const Reference('String')), + ..returns = refer('String')), equalsDart(r''' String foo(); '''), @@ -103,7 +103,7 @@ void main() { expect( new Method((b) => b ..name = 'foo' - ..types.add(const Reference('T'))), + ..types.add(refer('T'))), equalsDart(r''' foo(); '''), @@ -147,12 +147,12 @@ void main() { }); test('should create a method with a body with references', () { - final linkedHashMap = const Reference('LinkedHashMap', 'dart:collection'); + final $LinkedHashMap = refer('LinkedHashMap', 'dart:collection'); expect( new Method((b) => b ..name = 'foo' ..body = new Code.scope( - (a) => 'return new ${a(linkedHashMap)}();', + (a) => 'return new ${a($LinkedHashMap)}();', )), equalsDart(r''' foo() { @@ -204,7 +204,7 @@ void main() { new Parameter( (b) => b ..name = 'i' - ..type = const Reference('int').toType(), + ..type = refer('int').toType(), ), ), ), @@ -221,18 +221,18 @@ void main() { ..name = 'foo' ..types.add(new TypeReference((b) => b ..symbol = 'T' - ..bound = const Reference('Iterable'))) + ..bound = refer('Iterable'))) ..requiredParameters.addAll([ new Parameter( (b) => b ..name = 't' - ..type = const Reference('T'), + ..type = refer('T'), ), new Parameter((b) => b ..name = 'x' ..type = new TypeReference((b) => b ..symbol = 'X' - ..types.add(const Reference('T')))), + ..types.add(refer('T')))), ]), ), equalsDart(r''' From 445ec57cb1ee01ba0c27ab7c5c0c9413b573da0a Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 13 Oct 2017 14:08:05 -0700 Subject: [PATCH 068/271] Add Block + BlockBuilder, some utilities. (dart-lang/code_builder#134) * Initial support for Expression(s). * More in changelog. * Add context everywhere. * All tests passing. * More cleanup. * More expression work. * Improve calls, add property access. * Update README. * Actually update it. * Be nice to users. * Add literalString, literalMap. * Add blocks of code (statements). --- pkgs/code_builder/lib/code_builder.dart | 4 +- pkgs/code_builder/lib/src/emitter.dart | 5 +- pkgs/code_builder/lib/src/matchers.dart | 2 +- pkgs/code_builder/lib/src/specs/code.dart | 50 ++++++++++ pkgs/code_builder/lib/src/specs/code.g.dart | 92 +++++++++++++++++++ .../lib/src/specs/expression.dart | 32 ++++++- .../lib/src/specs/expression/invoke.dart | 4 + .../lib/src/specs/expression/literal.dart | 9 ++ .../test/specs/code/statement_test.dart | 38 ++++++++ 9 files changed, 228 insertions(+), 8 deletions(-) create mode 100644 pkgs/code_builder/lib/src/specs/code.g.dart create mode 100644 pkgs/code_builder/test/specs/code/statement_test.dart diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index c52a07855..077d5c2e5 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -8,12 +8,14 @@ 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 Code, StaticCode, ScopedCode; +export 'src/specs/code.dart' + show Block, BlockBuilder, Code, StaticCode, ScopedCode; export 'src/specs/constructor.dart' show Constructor, ConstructorBuilder; export 'src/specs/directive.dart' show Directive, DirectiveType, DirectiveBuilder; export 'src/specs/expression.dart' show + AsCodeExpression, BinaryExpression, CodeExpression, Expression, diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index d408571a4..f3ec44c2c 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -25,7 +25,7 @@ import 'visitors.dart'; /// /// If [elements] is at least 2 elements, inserts [separator] delimiting them. @visibleForTesting -void visitAll( +StringSink visitAll( Iterable elements, StringSink output, void visit(T element), [ @@ -36,7 +36,7 @@ void visitAll( // // ... which would allocate more StringBuffer(s) for a one-time use. if (elements.isEmpty) { - return; + return output; } final iterator = elements.iterator..moveNext(); visit(iterator.current); @@ -44,6 +44,7 @@ void visitAll( output.write(separator); visit(iterator.current); } + return output; } class DartEmitter extends Object diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index 3183f4ffe..8c96df62f 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -19,7 +19,7 @@ String _dartfmt(String source) { } catch (_) { // Ignored on purpose, probably not exactly valid Dart code. } finally { - source = source.replaceAll(' ', ' ').replaceAll('\n', '').trim(); + source = collapseWhitespace(source); } return source; } diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index afbd5daee..a8414c4a7 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -4,14 +4,20 @@ library code_builder.src.specs.code; +import 'package:built_value/built_value.dart'; +import 'package:built_collection/built_collection.dart'; import 'package:meta/meta.dart'; import '../allocator.dart'; import '../base.dart'; +import '../emitter.dart'; import '../visitors.dart'; +import 'expression.dart'; import 'reference.dart'; +part 'code.g.dart'; + /// Returns a scoped symbol to [Reference], with an import prefix if needed. /// /// This is short-hand for [Allocator.allocate] in most implementations. @@ -41,10 +47,40 @@ abstract class Code implements Spec { R accept(covariant CodeVisitor visitor, [R context]); } +/// Represents blocks of statements of Dart code. +abstract class Block implements Built, Spec { + factory Block([void updates(BlockBuilder b)]) = _$Block; + + Block._(); + + @override + R accept(covariant CodeVisitor visitor, [R context]) { + return visitor.visitBlock(this, context); + } + + BuiltList get statements; +} + +abstract class BlockBuilder implements Builder { + factory BlockBuilder() = _$BlockBuilder; + + BlockBuilder._(); + + /// Adds an [expression] to [statements]. + /// + /// **NOTE**: Not all expressions are _useful_ statements. + void addExpression(Expression expression) { + statements.add(expression.asStatement()); + } + + ListBuilder statements = new ListBuilder(); +} + /// Knowledge of different types of blocks of code in Dart. /// /// **INTERNAL ONLY**. abstract class CodeVisitor implements SpecVisitor { + T visitBlock(Block code, [T context]); T visitStaticCode(StaticCode code, [T context]); T visitScopedCode(ScopedCode code, [T context]); } @@ -54,6 +90,14 @@ abstract class CodeEmitter implements CodeVisitor { @protected Allocator get allocator; + @override + visitBlock(Block block, [StringSink output]) { + output ??= new StringBuffer(); + return visitAll(block.statements, output, (statement) { + statement.accept(this, output); + }, '\n'); + } + @override visitStaticCode(StaticCode code, [StringSink output]) { output ??= new StringBuffer(); @@ -77,6 +121,9 @@ class StaticCode implements Code { R accept(CodeVisitor visitor, [R context]) { return visitor.visitStaticCode(this, context); } + + @override + String toString() => code; } /// Represents a [code] block that may require scoping. @@ -89,4 +136,7 @@ class ScopedCode implements Code { R accept(CodeVisitor visitor, [R context]) { return visitor.visitScopedCode(this, context); } + + @override + String toString() => code((ref) => ref.symbol); } diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart new file mode 100644 index 000000000..c8d74bc46 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -0,0 +1,92 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.code; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// ************************************************************************** + +// ignore_for_file: annotate_overrides +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + +class _$Block extends Block { + @override + final BuiltList statements; + + factory _$Block([void updates(BlockBuilder b)]) => + (new BlockBuilder()..update(updates)).build() as _$Block; + + _$Block._({this.statements}) : super._() { + if (statements == null) throw new ArgumentError.notNull('statements'); + } + + @override + Block rebuild(void updates(BlockBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$BlockBuilder toBuilder() => new _$BlockBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! Block) return false; + return statements == other.statements; + } + + @override + int get hashCode { + return $jf($jc(0, statements.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Block')..add('statements', statements)) + .toString(); + } +} + +class _$BlockBuilder extends BlockBuilder { + _$Block _$v; + + @override + ListBuilder get statements { + _$this; + return super.statements ??= new ListBuilder(); + } + + @override + set statements(ListBuilder statements) { + _$this; + super.statements = statements; + } + + _$BlockBuilder() : super._(); + + BlockBuilder get _$this { + if (_$v != null) { + super.statements = _$v.statements?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(Block other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$Block; + } + + @override + void update(void updates(BlockBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$Block build() { + final _$result = _$v ?? new _$Block._(statements: statements?.build()); + replace(_$result); + return _$result; + } +} diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 5daf622bb..a9c11e6a9 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -27,7 +27,12 @@ abstract class Expression implements Spec { R accept(covariant ExpressionVisitor visitor, [R context]); /// Returns the expression as a valid [Code] block. - Code asCode() => new _AsExpressionCode(this); + /// + /// Also see [asStatement]. + Code asCode() => new AsCodeExpression(this, false); + + /// Returns the expression asa valid [Code] block with a trailing `;`. + Code asStatement() => new AsCodeExpression(this, true); /// Returns the result of [this] `&&` [other]. Expression and(Expression other) { @@ -86,21 +91,30 @@ abstract class Expression implements Spec { } /// Represents a [code] block that wraps an [Expression]. -class _AsExpressionCode implements Code { +class AsCodeExpression implements Code { final Expression code; - const _AsExpressionCode(this.code); + /// Whether this code should be considered a _statement_. + final bool isStatement; + + @visibleForTesting + const AsCodeExpression(this.code, [this.isStatement = false]); @override R accept(CodeVisitor visitor, [R context]) { - return code.accept(visitor as ExpressionVisitor, context); + return (visitor as ExpressionVisitor) + .visitAsCodeExpression(this, context); } + + @override + String toString() => code.toString(); } /// Knowledge of different types of expressions in Dart. /// /// **INTERNAL ONLY**. abstract class ExpressionVisitor implements SpecVisitor { + T visitAsCodeExpression(AsCodeExpression code, [T context]); T visitBinaryExpression(BinaryExpression expression, [T context]); T visitCodeExpression(CodeExpression expression, [T context]); T visitInvokeExpression(InvokeExpression expression, [T context]); @@ -113,6 +127,16 @@ abstract class ExpressionVisitor implements SpecVisitor { /// /// **INTERNAL ONLY**. abstract class ExpressionEmitter implements ExpressionVisitor { + @override + visitAsCodeExpression(AsCodeExpression expression, [StringSink output]) { + output ??= new StringBuffer(); + expression.code.accept(this, output); + if (expression.isStatement) { + output.write(';'); + } + return output; + } + @override visitBinaryExpression(BinaryExpression expression, [StringSink output]) { output ??= new StringBuffer(); diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index b9e0edb0b..40dd7856b 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -41,6 +41,10 @@ class InvokeExpression extends Expression { R accept(ExpressionVisitor visitor, [R context]) { return visitor.visitInvokeExpression(this, context); } + + @override + String toString() => + '${type ?? ''} $target($positionalArguments, $namedArguments)'; } enum InvokeExpressionType { diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index fc02d80df..92c17a11d 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -95,6 +95,9 @@ class LiteralExpression extends Expression { R accept(ExpressionVisitor visitor, [R context]) { return visitor.visitLiteralExpression(this, context); } + + @override + String toString() => literal; } class LiteralListExpression extends Expression { @@ -108,6 +111,9 @@ class LiteralListExpression extends Expression { R accept(ExpressionVisitor visitor, [R context]) { return visitor.visitLiteralListExpression(this, context); } + + @override + String toString() => '[${values.map(literal).join(', ')}]'; } class LiteralMapExpression extends Expression { @@ -127,4 +133,7 @@ class LiteralMapExpression extends Expression { R accept(ExpressionVisitor visitor, [R context]) { return visitor.visitLiteralMapExpression(this, context); } + + @override + String toString() => '{$values}'; } diff --git a/pkgs/code_builder/test/specs/code/statement_test.dart b/pkgs/code_builder/test/specs/code/statement_test.dart new file mode 100644 index 000000000..834d2c75c --- /dev/null +++ b/pkgs/code_builder/test/specs/code/statement_test.dart @@ -0,0 +1,38 @@ +// 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: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('}'), + ])), + equalsDart(r''' + if (foo) { + print(true); + } + '''), + ); + }); + + test('should emit a block of code including expressions', () { + expect( + new Block((b) => b.statements.addAll([ + const Code('if (foo) {'), + refer('print')([literalTrue]).asStatement(), + const Code('}'), + ])), + equalsDart(r''' + if (foo) { + print(true); + } + '''), + ); + }); +} From 9124fd0618a2a93ae8bbaca0d8b4e2fc7462dba1 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 16 Oct 2017 10:35:47 -0700 Subject: [PATCH 069/271] Fix a number of issues. (dart-lang/code_builder#140) * Fix a number of issues. * OK, add some tests. * Dartfmt. --- pkgs/code_builder/CHANGELOG.md | 9 ++ pkgs/code_builder/lib/src/emitter.dart | 6 +- pkgs/code_builder/lib/src/specs/code.dart | 2 +- .../lib/src/specs/expression.dart | 133 +++++++++++++++++- .../lib/src/specs/expression/invoke.dart | 11 +- pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 90 ++++++++++++ pkgs/code_builder/test/specs/file_test.dart | 2 +- 8 files changed, 247 insertions(+), 8 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 51465cfbe..0f7839e97 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,12 @@ +## 2.0.0-alpha+3 + +* Added `{new|const}InstanceNamed` to `Expression` [#135](https://github.com/dart-lang/code_builder/issues/135). + * Also added a `typeArguments` option to all invocations. +* **BUG FIX**: `Block` now implements `Code` [#136](https://github.com/dart-lang/code_builder/issues/136). +* Added `assign{...}` variants to `Expression` [#137](https://github.com/dart-lang/code_builder/issues/137). +* Added `.awaited` and `.returned` to `Expression` [#138](https://github.com/dart-lang/code_builder/issues/138). +* **BUG FIX**: `new DartEmitter.scoped()` applies prefixing [#139](https://github.com/dart-lang/code_builder/issues/139). + ## 2.0.0-alpha+2 * Upgraded `build_runner` from `^0.3.0` to `>=0.4.0 <0.6.0`. diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index f3ec44c2c..611798bd3 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -58,8 +58,10 @@ class DartEmitter extends Object /// May specify an [Allocator] to use for symbols, otherwise uses a no-op. DartEmitter([this.allocator = Allocator.none]); - /// Creates a new instance of [DartEmitter] with a default [Allocator]. - factory DartEmitter.scoped() => new DartEmitter(new Allocator()); + /// Creates a new instance of [DartEmitter] with simple automatic imports. + factory DartEmitter.scoped() { + return new DartEmitter(new Allocator.simplePrefixing()); + } @override visitAnnotation(Annotation spec, [StringSink output]) { diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index a8414c4a7..1cbafca8a 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -48,7 +48,7 @@ abstract class Code implements Spec { } /// Represents blocks of statements of Dart code. -abstract class Block implements Built, Spec { +abstract class Block implements Built, Code, Spec { factory Block([void updates(BlockBuilder b)]) = _$Block; Block._(); diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index a9c11e6a9..189a43848 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -39,15 +39,89 @@ abstract class Expression implements Spec { return new BinaryExpression._(toExpression(), other, '&&'); } + /// This expression preceding by `await`. + Expression get awaited { + return new BinaryExpression._( + const LiteralExpression._('await'), + this, + '', + ); + } + + /// Return `{other} = {this}`. + Expression assign(Expression other) { + return new BinaryExpression._( + other, + this, + '=', + ); + } + + /// Return `{other} ??= {this}`. + Expression assignNullAware(Expression other) { + return new BinaryExpression._( + other, + this, + '??=', + ); + } + + /// Return `var {name} = {this}`. + Expression assignVar(String name, [Reference type]) { + return new BinaryExpression._( + type == null + ? new LiteralExpression._('var $name') + : new BinaryExpression._( + type.toExpression(), + new LiteralExpression._(name), + '', + ), + this, + '=', + ); + } + + /// Return `final {name} = {this}`. + Expression assignFinal(String name, [Reference type]) { + return new BinaryExpression._( + type == null + ? const LiteralExpression._('final') + : new BinaryExpression._( + const LiteralExpression._('final'), + type.toExpression(), + '', + ), + this, + '$name =', + ); + } + + /// Return `const {name} = {this}`. + Expression assignConst(String name, [Reference type]) { + return new BinaryExpression._( + type == null + ? const LiteralExpression._('const') + : new BinaryExpression._( + const LiteralExpression._('const'), + type.toExpression(), + '', + ), + this, + '$name =', + ); + } + /// Call this expression as a method. Expression call( List positionalArguments, [ Map namedArguments = const {}, + List typeArguments = const [], ]) { return new InvokeExpression._( this, positionalArguments, namedArguments, + typeArguments, ); } @@ -65,11 +139,30 @@ abstract class Expression implements Spec { Expression newInstance( List positionalArguments, [ Map namedArguments = const {}, + List typeArguments = const [], ]) { return new InvokeExpression._new( this, positionalArguments, namedArguments, + typeArguments, + null, + ); + } + + /// Returns a new instance of this expression with a named constructor. + Expression newInstanceNamed( + String name, + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) { + return new InvokeExpression._new( + this, + positionalArguments, + namedArguments, + typeArguments, + name, ); } @@ -77,15 +170,43 @@ abstract class Expression implements Spec { Expression constInstance( List positionalArguments, [ Map namedArguments = const {}, + List typeArguments = const [], ]) { return new InvokeExpression._const( this, positionalArguments, namedArguments, + typeArguments, + null, ); } - /// May be overriden to support other types implementing [Expression]. + /// Returns a const instance of this expression with a named constructor. + Expression constInstanceNamed( + String name, + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) { + return new InvokeExpression._const( + this, + positionalArguments, + namedArguments, + typeArguments, + name, + ); + } + + /// This expression preceding by `return`. + Expression get returned { + return new BinaryExpression._( + const LiteralExpression._('return'), + this, + '', + ); + } + + /// May be overridden to support other types implementing [Expression]. @visibleForOverriding Expression toExpression() => this; } @@ -171,6 +292,16 @@ abstract class ExpressionEmitter implements ExpressionVisitor { break; } expression.target.accept(this, output); + if (expression.name != null) { + output..write('.')..write(expression.name); + } + if (expression.typeArguments.isNotEmpty) { + output.write('<'); + visitAll(expression.typeArguments, output, (type) { + type.accept(this, output); + }); + output.write('>'); + } output.write('('); visitAll(expression.positionalArguments, output, (spec) { spec.accept(this, output); diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index 40dd7856b..a81f5ccf7 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -13,20 +13,25 @@ class InvokeExpression extends Expression { final InvokeExpressionType type; final List positionalArguments; - final Map namedArguments; + final List typeArguments; + final String name; const InvokeExpression._( this.target, this.positionalArguments, [ this.namedArguments = const {}, + this.typeArguments, ]) - : type = null; + : type = null, + name = null; const InvokeExpression._new( this.target, this.positionalArguments, [ this.namedArguments = const {}, + this.typeArguments, + this.name, ]) : type = InvokeExpressionType.newInstance; @@ -34,6 +39,8 @@ class InvokeExpression extends Expression { this.target, this.positionalArguments, [ this.namedArguments = const {}, + this.typeArguments, + this.name, ]) : type = InvokeExpressionType.constInstance; diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 38ac24b6a..3fef70372 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.0.0-alpha+2 +version: 2.0.0-alpha+3 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index a12323bb4..d5e5476af 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -78,6 +78,20 @@ void main() { ); }); + test('should emit invoking new named constructor', () { + expect( + refer('Foo').newInstanceNamed('bar', []), + equalsDart('new Foo.bar()'), + ); + }); + + test('should emit invoking const Type()', () { + expect( + refer('Object').constInstance([]), + equalsDart('const Object()'), + ); + }); + test('should emit invoking a property accessor', () { expect(refer('foo').property('bar'), equalsDart('foo.bar')); }); @@ -132,4 +146,80 @@ void main() { equalsDart('foo(1, bar: 2, baz: 3)'), ); }); + + test('should emit invoking a method with a single type argument', () { + expect( + refer('foo').call( + [], + {}, + [ + refer('String'), + ], + ), + equalsDart('foo()'), + ); + }); + + test('should emit invoking a method with type arguments', () { + expect( + refer('foo').call( + [], + {}, + [ + refer('String'), + refer('int'), + ], + ), + equalsDart('foo()'), + ); + }); + + test('should emit an assignment', () { + expect( + literalTrue.assign(refer('foo')), + equalsDart('foo = true'), + ); + }); + + test('should emit assigning to a var', () { + expect( + literalTrue.assignVar('foo'), + equalsDart('var foo = true'), + ); + }); + + test('should emit assigning to a type', () { + expect( + literalTrue.assignVar('foo', refer('bool')), + equalsDart('bool foo = true'), + ); + }); + + test('should emit assigning to a final', () { + expect( + literalTrue.assignFinal('foo'), + equalsDart('final foo = true'), + ); + }); + + test('should emit assigning to a const', () { + expect( + literalTrue.assignConst('foo'), + equalsDart('const foo = true'), + ); + }); + + test('should emit await', () { + expect( + refer('future').awaited, + equalsDart('await future'), + ); + }); + + test('should emit return', () { + expect( + literalNull.returned, + equalsDart('return null'), + ); + }); } diff --git a/pkgs/code_builder/test/specs/file_test.dart b/pkgs/code_builder/test/specs/file_test.dart index cfdf3e286..0818a0fef 100644 --- a/pkgs/code_builder/test/specs/file_test.dart +++ b/pkgs/code_builder/test/specs/file_test.dart @@ -88,7 +88,7 @@ void main() { import 'dart:collection'; final test = new LinkedHashMap(); - ''', new DartEmitter.scoped()), + ''', new DartEmitter(new Allocator())), ); }); From 439971709a9370e5dcd8614d120af9a99b7ad65e Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 16 Oct 2017 10:50:09 -0700 Subject: [PATCH 070/271] Next update: closer to a final release. (dart-lang/code_builder#141) * Fix a number of issues. * OK, add some tests. * Add closures, some getters. * Another refactor. * Added FunctionType. * Updated README. * Dartfmt. * Fix CHANGELOG. --- pkgs/code_builder/CHANGELOG.md | 13 +- pkgs/code_builder/README.md | 8 +- pkgs/code_builder/lib/code_builder.dart | 3 +- pkgs/code_builder/lib/src/emitter.dart | 94 +++++++-- .../lib/src/specs/annotation.g.dart | 4 + pkgs/code_builder/lib/src/specs/class.g.dart | 4 + pkgs/code_builder/lib/src/specs/code.dart | 2 +- pkgs/code_builder/lib/src/specs/code.g.dart | 4 + .../lib/src/specs/constructor.g.dart | 4 + .../lib/src/specs/directive.g.dart | 4 + .../lib/src/specs/expression.dart | 130 ++++++------ .../lib/src/specs/expression/closure.dart | 25 +++ .../lib/src/specs/expression/code.dart | 1 + .../lib/src/specs/expression/invoke.dart | 10 +- pkgs/code_builder/lib/src/specs/field.g.dart | 4 + pkgs/code_builder/lib/src/specs/file.g.dart | 4 + pkgs/code_builder/lib/src/specs/method.dart | 7 + pkgs/code_builder/lib/src/specs/method.g.dart | 5 +- .../code_builder/lib/src/specs/reference.dart | 66 +++++- .../lib/src/specs/type_function.dart | 119 +++++++++++ .../lib/src/specs/type_function.g.dart | 189 ++++++++++++++++++ .../lib/src/specs/type_reference.dart | 66 +++++- .../lib/src/specs/type_reference.g.dart | 4 + pkgs/code_builder/lib/src/visitors.dart | 3 + .../code_builder/test/e2e/injection_test.dart | 4 +- pkgs/code_builder/test/specs/class_test.dart | 14 +- .../test/specs/code/expression_test.dart | 71 ++++++- .../test/specs/code/statement_test.dart | 2 +- pkgs/code_builder/test/specs/file_test.dart | 2 +- pkgs/code_builder/test/specs/method_test.dart | 10 +- 30 files changed, 753 insertions(+), 123 deletions(-) create mode 100644 pkgs/code_builder/lib/src/specs/expression/closure.dart create mode 100644 pkgs/code_builder/lib/src/specs/type_function.dart create mode 100644 pkgs/code_builder/lib/src/specs/type_function.g.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 0f7839e97..74d96c856 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,12 +1,23 @@ ## 2.0.0-alpha+3 +* Added `Expression.annotation` and `Expression.annotationNamed`. +* Added `Method.closure` to create an `Expression`. +* Added `FunctionType`. * Added `{new|const}InstanceNamed` to `Expression` [#135](https://github.com/dart-lang/code_builder/issues/135). * Also added a `typeArguments` option to all invocations. -* **BUG FIX**: `Block` now implements `Code` [#136](https://github.com/dart-lang/code_builder/issues/136). * Added `assign{...}` variants to `Expression` [#137](https://github.com/dart-lang/code_builder/issues/137). * Added `.awaited` and `.returned` to `Expression` [#138](https://github.com/dart-lang/code_builder/issues/138). + +* **BUG FIX**: `Block` now implements `Code` [#136](https://github.com/dart-lang/code_builder/issues/136). * **BUG FIX**: `new DartEmitter.scoped()` applies prefixing [#139](https://github.com/dart-lang/code_builder/issues/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`. + ## 2.0.0-alpha+2 * Upgraded `build_runner` from `^0.3.0` to `>=0.4.0 <0.6.0`. diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index b06de52d2..7f959be86 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -40,12 +40,12 @@ import 'package:dart_style/dart_style.dart'; void main() { final animal = new Class((b) => b ..name = 'Animal' - ..extend = refer('Organism').toType() + ..extend = refer('Organism') ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' ..lambda = true ..body = const Code('print(\'Yum\')')))); - final emitter = const DartEmitter(); + final emitter = new DartEmitter(); print(new DartFormatter().format('${animal.accept(emitter)}')); } ``` @@ -68,11 +68,11 @@ import 'package:dart_style/dart_style.dart'; void main() { final library = new File((b) => b.body.addAll([ new Method((b) => b - ..body = new Code((b) => b.code = '') + ..body = const Code('') ..name = 'doThing' ..returns = refer('Thing', 'package:a/a.dart')), new Method((b) => b - ..body = new Code((b) => b..code = '') + ..body = const Code('') ..name = 'doOther' ..returns = refer('Other', 'package:b/b.dart')), ])); diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 077d5c2e5..e8acbbe02 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -15,7 +15,7 @@ export 'src/specs/directive.dart' show Directive, DirectiveType, DirectiveBuilder; export 'src/specs/expression.dart' show - AsCodeExpression, + ToCodeExpression, BinaryExpression, CodeExpression, Expression, @@ -46,4 +46,5 @@ export 'src/specs/method.dart' Parameter, ParameterBuilder; export 'src/specs/reference.dart' show refer, Reference; +export 'src/specs/type_function.dart' show FunctionType, FunctionTypeBuilder; export 'src/specs/type_reference.dart' show TypeReference, TypeReferenceBuilder; diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 611798bd3..79650b89c 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -16,6 +16,7 @@ import 'specs/field.dart'; import 'specs/file.dart'; import 'specs/method.dart'; import 'specs/reference.dart'; +import 'specs/type_function.dart'; import 'specs/type_reference.dart'; import 'visitors.dart'; @@ -80,27 +81,38 @@ class DartEmitter extends Object output.write('abstract '); } output.write('class ${spec.name}'); - visitTypeParameters(spec.types.map((r) => r.toType()), output); + visitTypeParameters(spec.types.map((r) => r.type), output); if (spec.extend != null) { output.write(' extends '); - visitType(spec.extend.toType(), output); + visitType(spec.extend.type, output); } if (spec.mixins.isNotEmpty) { output ..write(' with ') - ..writeAll( - spec.mixins.map((m) => visitType(m.toType())), ','); + ..writeAll(spec.mixins.map((m) => visitType(m.type)), ','); } if (spec.implements.isNotEmpty) { output ..write(' implements ') ..writeAll( - spec.implements.map((m) => visitType(m.toType())), ','); + spec.implements.map((m) => visitType(m.type)), ','); } output.write(' {'); - spec.constructors.forEach((c) => visitConstructor(c, spec.name, output)); - spec.fields.forEach((f) => visitField(f, output)); - spec.methods.forEach((m) => visitMethod(m, output)); + spec.constructors.forEach((c) { + visitConstructor(c, spec.name, output); + output.writeln(); + }); + spec.fields.forEach((f) { + visitField(f, output); + output.writeln(); + }); + spec.methods.forEach((m) { + visitMethod(m, output); + if (m.lambda) { + output.write(';'); + } + output.writeln(); + }); output.writeln(' }'); return output; } @@ -170,7 +182,7 @@ class DartEmitter extends Object } if (spec.redirect != null) { output.write(' = '); - visitType(spec.redirect.toType(), output); + visitType(spec.redirect.type, output); output.write(';'); } else if (spec.body != null) { if (spec.lambda) { @@ -239,7 +251,7 @@ class DartEmitter extends Object break; } if (spec.type != null) { - visitType(spec.type.toType(), output); + visitType(spec.type.type, output); output.write(' '); } output.write(spec.name); @@ -258,6 +270,9 @@ class DartEmitter extends Object final body = new StringBuffer(); for (final spec in spec.body) { body.write(visitSpec(spec)); + if (spec is Method && spec.lambda) { + output.write(';'); + } } // TODO: Allow some sort of logical ordering. for (final directive in spec.directives) { @@ -270,6 +285,46 @@ class DartEmitter extends Object return output; } + @override + visitFunctionType(FunctionType spec, [StringSink output]) { + output ??= new StringBuffer(); + if (spec.returnType != null) { + spec.returnType.accept(this, output); + output.write(' '); + } + output.write('Function'); + if (spec.types.isNotEmpty) { + output.write('<'); + visitAll(spec.types, output, (spec) { + spec.accept(this, output); + }); + output.write('>'); + } + output.write('('); + visitAll(spec.requiredParameters, output, (spec) { + spec.accept(this, output); + }); + if (spec.optionalParameters.isNotEmpty || + spec.namedParameters.isNotEmpty && spec.requiredParameters.isNotEmpty) { + output.write(', '); + } + if (spec.optionalParameters.isNotEmpty) { + output.write('['); + visitAll(spec.optionalParameters, output, (spec) { + spec.accept(this, output); + }); + output.write(']'); + } else if (spec.namedParameters.isNotEmpty) { + output.write('{'); + visitAll(spec.namedParameters.keys, output, (name) { + spec.namedParameters[name].accept(this, output); + output..write(' ')..write(name); + }); + output.write('}'); + } + return output..write(')'); + } + @override visitMethod(Method spec, [StringSink output]) { output ??= new StringBuffer(); @@ -282,7 +337,7 @@ class DartEmitter extends Object output.write('static '); } if (spec.returns != null) { - visitType(spec.returns.toType(), output); + visitType(spec.returns.type, output); output.write(' '); } if (spec.type == MethodType.getter) { @@ -291,8 +346,10 @@ class DartEmitter extends Object if (spec.type == MethodType.setter) { output.write('set '); } - output.write(spec.name); - visitTypeParameters(spec.types.map((r) => r.toType()), output); + if (spec.name != null) { + output.write(spec.name); + } + visitTypeParameters(spec.types.map((r) => r.type), output); output.write('('); if (spec.requiredParameters.isNotEmpty) { var count = 0; @@ -348,15 +405,12 @@ class DartEmitter extends Object output.write(' { '); } spec.body.accept(this, output); - if (spec.lambda) { - output.write(';'); - } else { + if (!spec.lambda) { output.write(' } '); } } else { output.write(';'); } - output.writeln(); return output; } @@ -370,7 +424,7 @@ class DartEmitter extends Object spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); if (spec.type != null) { - visitType(spec.type.toType(), output); + visitType(spec.type.type, output); output.write(' '); } if (spec.toThis) { @@ -401,9 +455,9 @@ class DartEmitter extends Object visitReference(spec, output); if (spec.bound != null) { output.write(' extends '); - visitType(spec.bound.toType(), output); + visitType(spec.bound.type, output); } - visitTypeParameters(spec.types.map((r) => r.toType()), output); + visitTypeParameters(spec.types.map((r) => r.type), output); return output; } diff --git a/pkgs/code_builder/lib/src/specs/annotation.g.dart b/pkgs/code_builder/lib/src/specs/annotation.g.dart index f5ff5c755..4a572ec7f 100644 --- a/pkgs/code_builder/lib/src/specs/annotation.g.dart +++ b/pkgs/code_builder/lib/src/specs/annotation.g.dart @@ -6,7 +6,11 @@ part of code_builder.src.specs.annotation; // Generator: BuiltValueGenerator // ************************************************************************** +// ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index f0ea47cd4..25d4ba891 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -6,7 +6,11 @@ part of code_builder.src.specs.class_; // Generator: BuiltValueGenerator // ************************************************************************** +// ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index 1cbafca8a..9160b2d75 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -70,7 +70,7 @@ abstract class BlockBuilder implements Builder { /// /// **NOTE**: Not all expressions are _useful_ statements. void addExpression(Expression expression) { - statements.add(expression.asStatement()); + statements.add(expression.statement); } ListBuilder statements = new ListBuilder(); diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart index c8d74bc46..b012536a3 100644 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -6,7 +6,11 @@ part of code_builder.src.specs.code; // Generator: BuiltValueGenerator // ************************************************************************** +// ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index b33795d28..8b2cd4b59 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -6,7 +6,11 @@ part of code_builder.src.specs.constructor; // Generator: BuiltValueGenerator // ************************************************************************** +// ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart index 035c7acdd..2a59c6630 100644 --- a/pkgs/code_builder/lib/src/specs/directive.g.dart +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -6,7 +6,11 @@ part of code_builder.src.specs.directive; // Generator: BuiltValueGenerator // ************************************************************************** +// ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 189a43848..6203ed363 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -9,14 +9,20 @@ import 'package:meta/meta.dart'; import '../base.dart'; import '../emitter.dart'; import '../visitors.dart'; +import 'annotation.dart'; import 'code.dart'; +import 'method.dart'; import 'reference.dart'; +import 'type_function.dart'; part 'expression/binary.dart'; +part 'expression/closure.dart'; part 'expression/code.dart'; part 'expression/invoke.dart'; part 'expression/literal.dart'; +/// Represents a [code] block that wraps an [Expression]. + /// Represents a Dart expression. /// /// See various concrete implementations for details. @@ -26,20 +32,20 @@ abstract class Expression implements Spec { @override R accept(covariant ExpressionVisitor visitor, [R context]); - /// Returns the expression as a valid [Code] block. + /// The expression as a valid [Code] block. /// - /// Also see [asStatement]. - Code asCode() => new AsCodeExpression(this, false); + /// Also see [statement]. + Code get code => new ToCodeExpression(this, false); - /// Returns the expression asa valid [Code] block with a trailing `;`. - Code asStatement() => new AsCodeExpression(this, true); + /// The expression as a valid [Code] block with a trailing `;`. + Code get statement => new ToCodeExpression(this, true); /// Returns the result of [this] `&&` [other]. Expression and(Expression other) { - return new BinaryExpression._(toExpression(), other, '&&'); + return new BinaryExpression._(expression, other, '&&'); } - /// This expression preceding by `await`. + /// This expression preceded by `await`. Expression get awaited { return new BinaryExpression._( const LiteralExpression._('await'), @@ -51,8 +57,8 @@ abstract class Expression implements Spec { /// Return `{other} = {this}`. Expression assign(Expression other) { return new BinaryExpression._( - other, this, + other, '=', ); } @@ -60,8 +66,8 @@ abstract class Expression implements Spec { /// Return `{other} ??= {this}`. Expression assignNullAware(Expression other) { return new BinaryExpression._( - other, this, + other, '??=', ); } @@ -72,7 +78,7 @@ abstract class Expression implements Spec { type == null ? new LiteralExpression._('var $name') : new BinaryExpression._( - type.toExpression(), + type.expression, new LiteralExpression._(name), '', ), @@ -88,7 +94,7 @@ abstract class Expression implements Spec { ? const LiteralExpression._('final') : new BinaryExpression._( const LiteralExpression._('final'), - type.toExpression(), + type.expression, '', ), this, @@ -103,7 +109,7 @@ abstract class Expression implements Spec { ? const LiteralExpression._('const') : new BinaryExpression._( const LiteralExpression._('const'), - type.toExpression(), + type.expression, '', ), this, @@ -135,69 +141,42 @@ abstract class Expression implements Spec { ); } - /// Returns a new instance of this expression. - Expression newInstance( - List positionalArguments, [ + /// Returns an annotation as a result of calling this constructor. + Annotation annotation([ + List positionalArguments, Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression._new( - this, - positionalArguments, - namedArguments, - typeArguments, - null, - ); - } - - /// Returns a new instance of this expression with a named constructor. - Expression newInstanceNamed( - String name, - List positionalArguments, [ - Map namedArguments = const {}, - List typeArguments = const [], - ]) { - return new InvokeExpression._new( - this, - positionalArguments, - namedArguments, - typeArguments, - name, - ); - } - - /// Returns a const instance of this expression. - Expression constInstance( - List positionalArguments, [ - Map namedArguments = const {}, - List typeArguments = const [], - ]) { - return new InvokeExpression._const( - this, - positionalArguments, - namedArguments, - typeArguments, - null, - ); + if (positionalArguments == null) { + return new Annotation((b) { + b.code = code; + }); + } + return new Annotation((b) { + b.code = new InvokeExpression._( + this, + positionalArguments, + namedArguments, + typeArguments, + ) + .code; + }); } - /// Returns a const instance of this expression with a named constructor. - Expression constInstanceNamed( + /// Returns an annotation as a result of calling a named constructor. + Annotation annotationNamed( String name, List positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression._const( - this, - positionalArguments, - namedArguments, - typeArguments, - name, - ); + return new Annotation((b) => b + ..code = new InvokeExpression._( + this, positionalArguments, namedArguments, typeArguments, name) + .code); } - /// This expression preceding by `return`. + /// This expression preceded by `return`. Expression get returned { return new BinaryExpression._( const LiteralExpression._('return'), @@ -208,23 +187,27 @@ abstract class Expression implements Spec { /// May be overridden to support other types implementing [Expression]. @visibleForOverriding - Expression toExpression() => this; + Expression get expression => this; } -/// Represents a [code] block that wraps an [Expression]. -class AsCodeExpression implements Code { +/// Creates `typedef {name} =`. +Code createTypeDef(String name, FunctionType type) => new BinaryExpression._( + new LiteralExpression._('typedef $name'), type.expression, '=') + .statement; + +class ToCodeExpression implements Code { final Expression code; /// Whether this code should be considered a _statement_. final bool isStatement; @visibleForTesting - const AsCodeExpression(this.code, [this.isStatement = false]); + const ToCodeExpression(this.code, [this.isStatement = false]); @override R accept(CodeVisitor visitor, [R context]) { return (visitor as ExpressionVisitor) - .visitAsCodeExpression(this, context); + .visitToCodeExpression(this, context); } @override @@ -235,8 +218,9 @@ class AsCodeExpression implements Code { /// /// **INTERNAL ONLY**. abstract class ExpressionVisitor implements SpecVisitor { - T visitAsCodeExpression(AsCodeExpression code, [T context]); + T visitToCodeExpression(ToCodeExpression code, [T context]); T visitBinaryExpression(BinaryExpression expression, [T context]); + T visitClosureExpression(ClosureExpression expression, [T context]); T visitCodeExpression(CodeExpression expression, [T context]); T visitInvokeExpression(InvokeExpression expression, [T context]); T visitLiteralExpression(LiteralExpression expression, [T context]); @@ -249,7 +233,7 @@ abstract class ExpressionVisitor implements SpecVisitor { /// **INTERNAL ONLY**. abstract class ExpressionEmitter implements ExpressionVisitor { @override - visitAsCodeExpression(AsCodeExpression expression, [StringSink output]) { + visitToCodeExpression(ToCodeExpression expression, [StringSink output]) { output ??= new StringBuffer(); expression.code.accept(this, output); if (expression.isStatement) { @@ -273,6 +257,12 @@ abstract class ExpressionEmitter implements ExpressionVisitor { return output; } + @override + visitClosureExpression(ClosureExpression expression, [StringSink output]) { + output ??= new StringBuffer(); + return expression.method.accept(this, output); + } + @override visitCodeExpression(CodeExpression expression, [StringSink output]) { output ??= new StringBuffer(); diff --git a/pkgs/code_builder/lib/src/specs/expression/closure.dart b/pkgs/code_builder/lib/src/specs/expression/closure.dart new file mode 100644 index 000000000..e8600dcec --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/expression/closure.dart @@ -0,0 +1,25 @@ +// 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. + +part of code_builder.src.specs.expression; + +@visibleForTesting +Expression toClosure(Method method) { + final withoutTypes = method.rebuild((b) { + b.returns = null; + b.types.clear(); + }); + return new ClosureExpression._(withoutTypes); +} + +class ClosureExpression extends Expression { + final Method method; + + const ClosureExpression._(this.method); + + @override + R accept(ExpressionVisitor visitor, [R context]) { + return visitor.visitClosureExpression(this, context); + } +} diff --git a/pkgs/code_builder/lib/src/specs/expression/code.dart b/pkgs/code_builder/lib/src/specs/expression/code.dart index aa79b838f..026b859a4 100644 --- a/pkgs/code_builder/lib/src/specs/expression/code.dart +++ b/pkgs/code_builder/lib/src/specs/expression/code.dart @@ -6,6 +6,7 @@ part of code_builder.src.specs.expression; /// Represents a [Code] block as an [Expression]. class CodeExpression extends Expression { + @override final Code code; /// **INTERNAL ONLY**: Used to wrap [Code] as an [Expression]. diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index a81f5ccf7..84148beea 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -22,11 +22,12 @@ class InvokeExpression extends Expression { this.positionalArguments, [ this.namedArguments = const {}, this.typeArguments, + this.name, ]) - : type = null, - name = null; + : type = null; - const InvokeExpression._new( + @visibleForTesting + const InvokeExpression.newOf( this.target, this.positionalArguments, [ this.namedArguments = const {}, @@ -35,7 +36,8 @@ class InvokeExpression extends Expression { ]) : type = InvokeExpressionType.newInstance; - const InvokeExpression._const( + @visibleForTesting + const InvokeExpression.constOf( this.target, this.positionalArguments, [ this.namedArguments = const {}, diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 1d662b237..407ac8942 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -6,7 +6,11 @@ part of code_builder.src.specs.field; // Generator: BuiltValueGenerator // ************************************************************************** +// ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/file.g.dart b/pkgs/code_builder/lib/src/specs/file.g.dart index d2540ef0b..bbe5c77b4 100644 --- a/pkgs/code_builder/lib/src/specs/file.g.dart +++ b/pkgs/code_builder/lib/src/specs/file.g.dart @@ -6,7 +6,11 @@ part of code_builder.src.specs.library; // Generator: BuiltValueGenerator // ************************************************************************** +// ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 3734758ff..1de7dd688 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -15,6 +15,7 @@ import '../mixins/generics.dart'; import '../visitors.dart'; import 'annotation.dart'; import 'code.dart'; +import 'expression.dart'; import 'reference.dart'; part 'method.g.dart'; @@ -69,6 +70,9 @@ abstract class Method extends Object bool get static; /// Name of the method or function. + /// + /// May be `null` when being used as a [closure]. + @nullable String get name; /// Whether this is a getter or setter. @@ -88,6 +92,9 @@ abstract class Method extends Object R context, ]) => visitor.visitMethod(this, context); + + /// This method as a closure. + Expression get closure => toClosure(this); } abstract class MethodBuilder extends Object diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index 1417d4206..1f1946e0b 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -6,7 +6,11 @@ part of code_builder.src.specs.method; // Generator: BuiltValueGenerator // ************************************************************************** +// ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first @@ -66,7 +70,6 @@ class _$Method extends Method { if (external == null) throw new ArgumentError.notNull('external'); if (lambda == null) throw new ArgumentError.notNull('lambda'); if (static == null) throw new ArgumentError.notNull('static'); - if (name == null) throw new ArgumentError.notNull('name'); } @override diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 78aa22092..9bf296abd 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -49,8 +49,70 @@ class Reference extends Expression implements Spec { bool operator ==(Object o) => o is Reference && o.url == url && o.symbol == symbol; + /// Returns a new instance of this expression. + Expression newInstance( + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) { + return new InvokeExpression.newOf( + this, + positionalArguments, + namedArguments, + typeArguments, + null, + ); + } + + /// Returns a new instance of this expression with a named constructor. + Expression newInstanceNamed( + String name, + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) { + return new InvokeExpression.newOf( + this, + positionalArguments, + namedArguments, + typeArguments, + name, + ); + } + + /// Returns a const instance of this expression. + Expression constInstance( + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) { + return new InvokeExpression.constOf( + this, + positionalArguments, + namedArguments, + typeArguments, + null, + ); + } + + /// Returns a const instance of this expression with a named constructor. + Expression constInstanceNamed( + String name, + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) { + return new InvokeExpression.constOf( + this, + positionalArguments, + namedArguments, + typeArguments, + name, + ); + } + @override - Expression toExpression() { + Expression get expression { return new CodeExpression(new Code.scope((a) => a(this))); } @@ -61,7 +123,7 @@ class Reference extends Expression implements Spec { .toString(); /// Returns as a [TypeReference], which allows adding generic type parameters. - TypeReference toType() => new TypeReference((b) => b + TypeReference get type => new TypeReference((b) => b ..url = url ..symbol = symbol); } diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart new file mode 100644 index 000000000..3abc4db5d --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -0,0 +1,119 @@ +// 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. + +library code_builder.src.specs.type_function; + +import 'package:built_value/built_value.dart'; +import 'package:built_collection/built_collection.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../mixins/generics.dart'; +import '../visitors.dart'; +import 'code.dart'; +import 'expression.dart'; +import 'reference.dart'; +import 'type_reference.dart'; + +part 'type_function.g.dart'; + +@immutable +abstract class FunctionType extends Expression + with HasGenerics + implements Built, Reference, Spec { + factory FunctionType([ + void updates(FunctionTypeBuilder b), + ]) = _$FunctionType; + + FunctionType._(); + + @override + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitFunctionType(this, context); + + /// Return type. + @nullable + Reference get returnType; + + @override + BuiltList get types; + + /// Required positional arguments to this function type. + BuiltList get requiredParameters; + + /// Optional positional arguments to this function type. + BuiltList get optionalParameters; + + /// Named optional arguments to this function type. + BuiltMap get namedParameters; + + @override + String get url => null; + + @override + String get symbol => null; + + @override + TypeReference get type => null; + + @override + Expression newInstance( + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) => + throw new UnsupportedError('Cannot "new" a function type.'); + + @override + Expression newInstanceNamed( + String name, + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) => + throw new UnsupportedError('Cannot "new" a function type.'); + + @override + Expression constInstance( + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) => + throw new UnsupportedError('Cannot "const" a function type.'); + + @override + Expression constInstanceNamed( + String name, + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) => + throw new UnsupportedError('Cannot "const" a function type.'); + + /// A typedef assignment to this type. + Code toTypeDef(String name) => createTypeDef(name, this); +} + +abstract class FunctionTypeBuilder extends Object + with HasGenericsBuilder + implements Builder { + factory FunctionTypeBuilder() = _$FunctionTypeBuilder; + + FunctionTypeBuilder._(); + + Reference returnType; + + @override + ListBuilder types = new ListBuilder(); + + ListBuilder requiredParameters = new ListBuilder(); + + ListBuilder optionalParameters = new ListBuilder(); + + MapBuilder namedParameters = + new MapBuilder(); +} diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart new file mode 100644 index 000000000..2faa2d273 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -0,0 +1,189 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of code_builder.src.specs.type_function; + +// ************************************************************************** +// Generator: BuiltValueGenerator +// ************************************************************************** + +// ignore_for_file: always_put_control_body_on_new_line +// ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types +// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: sort_constructors_first + +class _$FunctionType extends FunctionType { + @override + final Reference returnType; + @override + final BuiltList types; + @override + final BuiltList requiredParameters; + @override + final BuiltList optionalParameters; + @override + final BuiltMap namedParameters; + + factory _$FunctionType([void updates(FunctionTypeBuilder b)]) => + (new FunctionTypeBuilder()..update(updates)).build() as _$FunctionType; + + _$FunctionType._( + {this.returnType, + this.types, + this.requiredParameters, + this.optionalParameters, + this.namedParameters}) + : super._() { + if (types == null) throw new ArgumentError.notNull('types'); + if (requiredParameters == null) + throw new ArgumentError.notNull('requiredParameters'); + if (optionalParameters == null) + throw new ArgumentError.notNull('optionalParameters'); + if (namedParameters == null) + throw new ArgumentError.notNull('namedParameters'); + } + + @override + FunctionType rebuild(void updates(FunctionTypeBuilder b)) => + (toBuilder()..update(updates)).build(); + + @override + _$FunctionTypeBuilder toBuilder() => + new _$FunctionTypeBuilder()..replace(this); + + @override + bool operator ==(dynamic other) { + if (identical(other, this)) return true; + if (other is! FunctionType) return false; + return returnType == other.returnType && + types == other.types && + requiredParameters == other.requiredParameters && + optionalParameters == other.optionalParameters && + namedParameters == other.namedParameters; + } + + @override + int get hashCode { + return $jf($jc( + $jc( + $jc($jc($jc(0, returnType.hashCode), types.hashCode), + requiredParameters.hashCode), + optionalParameters.hashCode), + namedParameters.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('FunctionType') + ..add('returnType', returnType) + ..add('types', types) + ..add('requiredParameters', requiredParameters) + ..add('optionalParameters', optionalParameters) + ..add('namedParameters', namedParameters)) + .toString(); + } +} + +class _$FunctionTypeBuilder extends FunctionTypeBuilder { + _$FunctionType _$v; + + @override + Reference get returnType { + _$this; + return super.returnType; + } + + @override + set returnType(Reference returnType) { + _$this; + super.returnType = returnType; + } + + @override + ListBuilder get types { + _$this; + return super.types ??= new ListBuilder(); + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + + @override + ListBuilder get requiredParameters { + _$this; + return super.requiredParameters ??= new ListBuilder(); + } + + @override + set requiredParameters(ListBuilder requiredParameters) { + _$this; + super.requiredParameters = requiredParameters; + } + + @override + ListBuilder get optionalParameters { + _$this; + return super.optionalParameters ??= new ListBuilder(); + } + + @override + set optionalParameters(ListBuilder optionalParameters) { + _$this; + super.optionalParameters = optionalParameters; + } + + @override + MapBuilder get namedParameters { + _$this; + return super.namedParameters ??= new MapBuilder(); + } + + @override + set namedParameters(MapBuilder namedParameters) { + _$this; + super.namedParameters = namedParameters; + } + + _$FunctionTypeBuilder() : super._(); + + FunctionTypeBuilder get _$this { + if (_$v != null) { + super.returnType = _$v.returnType; + super.types = _$v.types?.toBuilder(); + super.requiredParameters = _$v.requiredParameters?.toBuilder(); + super.optionalParameters = _$v.optionalParameters?.toBuilder(); + super.namedParameters = _$v.namedParameters?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(FunctionType other) { + if (other == null) throw new ArgumentError.notNull('other'); + _$v = other as _$FunctionType; + } + + @override + void update(void updates(FunctionTypeBuilder b)) { + if (updates != null) updates(this); + } + + @override + _$FunctionType build() { + final _$result = _$v ?? + new _$FunctionType._( + returnType: returnType, + types: types?.build(), + requiredParameters: requiredParameters?.build(), + optionalParameters: optionalParameters?.build(), + namedParameters: namedParameters?.build()); + replace(_$result); + return _$result; + } +} diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index 68eedb110..d09d0930c 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -49,12 +49,74 @@ abstract class TypeReference extends Expression visitor.visitType(this, context); @override - Expression toExpression() { + Expression get expression { return new CodeExpression(new Code.scope((a) => a(this))); } @override - TypeReference toType() => this; + TypeReference get type => this; + + @override + Expression newInstance( + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) { + return new InvokeExpression.newOf( + this, + positionalArguments, + namedArguments, + typeArguments, + null, + ); + } + + @override + Expression newInstanceNamed( + String name, + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) { + return new InvokeExpression.newOf( + this, + positionalArguments, + namedArguments, + typeArguments, + name, + ); + } + + @override + Expression constInstance( + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) { + return new InvokeExpression.constOf( + this, + positionalArguments, + namedArguments, + typeArguments, + null, + ); + } + + @override + Expression constInstanceNamed( + String name, + List positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) { + return new InvokeExpression.constOf( + this, + positionalArguments, + namedArguments, + typeArguments, + name, + ); + } } abstract class TypeReferenceBuilder extends Object diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index 3b658ecf2..05d271904 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -6,7 +6,11 @@ part of code_builder.src.specs.type_reference; // Generator: BuiltValueGenerator // ************************************************************************** +// ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides +// ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_returning_this +// ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 03aea23a5..111f4975d 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -13,6 +13,7 @@ import 'specs/field.dart'; import 'specs/file.dart'; import 'specs/method.dart'; import 'specs/reference.dart'; +import 'specs/type_function.dart'; import 'specs/type_reference.dart'; @optionalTypeArgs @@ -31,6 +32,8 @@ abstract class SpecVisitor { T visitFile(File spec, [T context]); + T visitFunctionType(FunctionType spec, [T context]); + T visitMethod(Method spec, [T context]); T visitReference(Reference spec, [T context]); diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index dc45ef40c..a4a1ae6a8 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -18,7 +18,7 @@ void main() { ..fields.add(new Field((b) => b ..modifier = FieldModifier.final$ ..name = '_module' - ..type = $Module.toType())) + ..type = $Module.type)) ..constructors.add(new Constructor((b) => b ..requiredParameters.add(new Parameter((b) => b ..name = '_module' @@ -28,7 +28,7 @@ void main() { ..body = $Thing.newInstance([ refer('_module').property('get1').call([]), refer('_module').property('get2').call([]), - ]).asCode() + ]).code ..lambda = true ..returns = $Thing ..annotations diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 54ba0a3e9..f05c41a86 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -45,19 +45,19 @@ void main() { }); test('should create a class with annotations', () { - final $deprecated = refer('deprecated'); expect( new Class( (b) => b ..name = 'Foo' - ..annotations.add( - new Annotation( - (b) => b..code = new Code.scope((a) => a($deprecated)), - ), - ), + ..annotations.addAll([ + refer('deprecated').annotation(), + refer('Deprecated') + .annotation([literalString('This is an old class')]) + ]), ), equalsDart(r''' @deprecated + @Deprecated('This is an old class') class Foo {} '''), ); @@ -98,7 +98,7 @@ void main() { ..symbol = 'T' ..bound = new TypeReference((b) => b ..symbol = 'Comparable' - ..types.add(refer('T').toType()))))), + ..types.add(refer('T').type))))), equalsDart(r''' class Comparable> {} '''), diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index d5e5476af..b93f6cfe7 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -174,13 +174,82 @@ void main() { ); }); + test('should emit a function type', () { + expect( + new FunctionType((b) => b.returnType = refer('void')), + equalsDart('void Function()'), + ); + }); + + test('should emit a typedef statement', () { + expect( + new FunctionType((b) => b.returnType = refer('void')).toTypeDef('Void0'), + equalsDart('typedef Void0 = void Function();'), + ); + }); + + test('should emit a function type with type parameters', () { + expect( + new FunctionType((b) => b + ..returnType = refer('T') + ..types.add(refer('T'))), + equalsDart('T Function()'), + ); + }); + + test('should emit a function type a single parameter', () { + expect( + new FunctionType((b) => b..requiredParameters.add(refer('String'))), + equalsDart('Function(String)'), + ); + }); + + test('should emit a function type with parameters', () { + expect( + new FunctionType((b) => b + ..requiredParameters.add(refer('String')) + ..optionalParameters.add(refer('int'))), + equalsDart('Function(String, [int])'), + ); + }); + + test('should emit a function type with named parameters', () { + expect( + new FunctionType((b) => b + ..namedParameters.addAll({ + 'x': refer('int'), + 'y': refer('int'), + })), + equalsDart('Function({int x, int y})'), + ); + }); + + test('should emit a closure', () { + expect( + refer('map').property('putIfAbsent').call([ + literalString('foo'), + new Method((b) => b + ..lambda = true + ..body = literalTrue.code).closure, + ]), + equalsDart("map.putIfAbsent('foo', () => true)"), + ); + }); + test('should emit an assignment', () { expect( - literalTrue.assign(refer('foo')), + refer('foo').assign(literalTrue), equalsDart('foo = true'), ); }); + test('should emit a null-aware assignment', () { + expect( + refer('foo').assignNullAware(literalTrue), + equalsDart('foo ??= true'), + ); + }); + test('should emit assigning to a var', () { expect( literalTrue.assignVar('foo'), diff --git a/pkgs/code_builder/test/specs/code/statement_test.dart b/pkgs/code_builder/test/specs/code/statement_test.dart index 834d2c75c..d233bea33 100644 --- a/pkgs/code_builder/test/specs/code/statement_test.dart +++ b/pkgs/code_builder/test/specs/code/statement_test.dart @@ -25,7 +25,7 @@ void main() { expect( new Block((b) => b.statements.addAll([ const Code('if (foo) {'), - refer('print')([literalTrue]).asStatement(), + refer('print')([literalTrue]).statement, const Code('}'), ])), equalsDart(r''' diff --git a/pkgs/code_builder/test/specs/file_test.dart b/pkgs/code_builder/test/specs/file_test.dart index 0818a0fef..85b151f7e 100644 --- a/pkgs/code_builder/test/specs/file_test.dart +++ b/pkgs/code_builder/test/specs/file_test.dart @@ -16,7 +16,7 @@ void main() { ..body.add(new Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ - ..assignment = $LinkedHashMap.newInstance([]).asCode()))), + ..assignment = $LinkedHashMap.newInstance([]).code))), equalsDart(r''' import 'dart:collection'; diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index f73f2fd38..cea286e75 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -23,7 +23,7 @@ void main() { ..lambda = true ..body = const Code('null')), equalsDart(r''' - foo() async => null; + foo() async => null '''), ); }); @@ -36,7 +36,7 @@ void main() { ..lambda = true ..body = const Code('null')), equalsDart(r''' - foo() async* => null; + foo() async* => null '''), ); }); @@ -49,7 +49,7 @@ void main() { ..lambda = true ..body = const Code('null')), equalsDart(r''' - foo() sync* => null; + foo() sync* => null '''), ); }); @@ -141,7 +141,7 @@ void main() { ..lambda = true ..body = const Code('1 + 2')), equalsDart(r''' - foo() => 1 + 2; + foo() => 1 + 2 '''), ); }); @@ -204,7 +204,7 @@ void main() { new Parameter( (b) => b ..name = 'i' - ..type = refer('int').toType(), + ..type = refer('int').type, ), ), ), From b2e1a3bb5654a6b1ab20db55824c3df820a0ba08 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 24 Oct 2017 10:35:38 -0700 Subject: [PATCH 071/271] Beta release fixes and feature. (dart-lang/code_builder#149) * Beta release fixes and feature. * Dartfmt. --- pkgs/code_builder/CHANGELOG.md | 7 ++++ pkgs/code_builder/lib/code_builder.dart | 4 +- pkgs/code_builder/lib/src/allocator.dart | 2 + pkgs/code_builder/lib/src/base.dart | 14 +++++++ pkgs/code_builder/lib/src/emitter.dart | 2 +- pkgs/code_builder/lib/src/matchers.dart | 3 +- pkgs/code_builder/lib/src/specs/code.dart | 36 ++++++++++++++-- pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/statement_test.dart | 41 ++++++++++++++----- 9 files changed, 92 insertions(+), 19 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 74d96c856..a11fe3710 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -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`. diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index e8acbbe02..53473a208 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -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; diff --git a/pkgs/code_builder/lib/src/allocator.dart b/pkgs/code_builder/lib/src/allocator.dart index aaf1c6900..3d0b2d1f3 100644 --- a/pkgs/code_builder/lib/src/allocator.dart +++ b/pkgs/code_builder/lib/src/allocator.dart @@ -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'; diff --git a/pkgs/code_builder/lib/src/base.dart b/pkgs/code_builder/lib/src/base.dart index c164ae0da..c11d5491b 100644 --- a/pkgs/code_builder/lib/src/base.dart +++ b/pkgs/code_builder/lib/src/base.dart @@ -7,3 +7,17 @@ import 'visitors.dart'; abstract class Spec { R accept(SpecVisitor 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(SpecVisitor visitor, [R context]) { + return generate().accept(visitor, context); + } +} diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 79650b89c..22b6ed887 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -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. diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index 8c96df62f..fa4991f61 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -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; @@ -54,7 +53,7 @@ class _EqualsDart extends Matcher { final result = _dart(item, _emitter); return equals(result).describeMismatch( _source, - mismatchDescription, + mismatchDescription.add(result), state, verbose, ); diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index 9160b2d75..4814ebfd0 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -51,6 +51,10 @@ abstract class Code implements Spec { abstract class Block implements Built, Code, Spec { factory Block([void updates(BlockBuilder b)]) = _$Block; + factory Block.of(Iterable statements) { + return new Block((b) => b..statements.addAll(statements)); + } + Block._(); @override @@ -111,7 +115,33 @@ abstract class CodeEmitter implements CodeVisitor { } } -/// 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(CodeVisitor visitor, [R context]) { + return generate(visitor).accept(visitor, context); + } +} + +/// 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(CodeVisitor visitor, [R context]) { + return generate().accept(visitor, context); + } +} + +/// Represents a simple, literal code block to be inserted as-is. class StaticCode implements Code { final String code; @@ -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); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 3fef70372..74486e688 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -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 homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/statement_test.dart b/pkgs/code_builder/test/specs/code/statement_test.dart index d233bea33..11a830a1c 100644 --- a/pkgs/code_builder/test/specs/code/statement_test.dart +++ b/pkgs/code_builder/test/specs/code/statement_test.dart @@ -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); @@ -23,11 +23,11 @@ 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); @@ -35,4 +35,25 @@ void main() { '''), ); }); + + 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); + } + } + '''), + ); + }); } From cf2adb48d7140afb4413ac5eb6a85331c9fd4390 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 24 Oct 2017 10:37:46 -0700 Subject: [PATCH 072/271] Update allocator.dart Remove unused import. /tbr @yjbanov. --- pkgs/code_builder/lib/src/allocator.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/code_builder/lib/src/allocator.dart b/pkgs/code_builder/lib/src/allocator.dart index 3d0b2d1f3..aaf1c6900 100644 --- a/pkgs/code_builder/lib/src/allocator.dart +++ b/pkgs/code_builder/lib/src/allocator.dart @@ -2,8 +2,6 @@ // 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'; From 96a28187fbdd13e1c38e31560800b05d577aafa0 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 27 Oct 2017 17:28:39 -0700 Subject: [PATCH 073/271] Prepare to publish. (dart-lang/code_builder#150) --- pkgs/code_builder/CHANGELOG.md | 60 +++++++++++++++++++++++++++++++ pkgs/code_builder/CONTRIBUTING.md | 2 +- pkgs/code_builder/pubspec.yaml | 3 +- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index a11fe3710..76ca9b541 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,63 @@ +## 2.0.0 + +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. + +```dart +// 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... + +```dart +class Animal extends Organism { + void eat() => print('Yum!'); +} +``` + +**Major changes**: + +* Builders now use `built_value`, and have a more consistent, friendly API. +* Builders are now consistent - they don't any work until code is emitted. +* It's possible to overwrite the built-in code emitting, formatting, etc by + providing your own visitors. See `DartEmitter` as an example of the built-in + visitor/emitter. +* Most of the expression and statement level helpers were removed; in practice + they were difficult to write and maintain, and many users commonly asked for + opt-out type APIs. See the `Code` example below: + +```dart +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! + ## 2.0.0-beta * Added `lazySpec` and `lazyCode` to lazily create code on visit [#145](https://github.com/dart-lang/code_builder/issues/145). diff --git a/pkgs/code_builder/CONTRIBUTING.md b/pkgs/code_builder/CONTRIBUTING.md index 0bf17f075..0dfd0f763 100644 --- a/pkgs/code_builder/CONTRIBUTING.md +++ b/pkgs/code_builder/CONTRIBUTING.md @@ -23,7 +23,7 @@ All submissions, including submissions by project members, require review. ### File headers All files in the project must start with the following header. - // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file + // 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. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 74486e688..5dd0f7736 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.0.0-beta +version: 2.0.0 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -17,6 +17,5 @@ dependencies: dev_dependencies: build_runner: '>=0.4.0 <0.6.0' built_value_generator: '>=2.0.0 <5.0.0' - io: '>=0.1.0 <0.3.0' source_gen: '^0.7.0' test: ^0.12.0 From 9c16fbf68b1a89b354be92cfc0c22307509dd7b8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sat, 28 Oct 2017 10:05:08 -0700 Subject: [PATCH 074/271] Add support for raw String in `literalString` (dart-lang/code_builder#152) Fixes https://github.com/dart-lang/code_builder/issues/151 --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/lib/src/specs/expression/literal.dart | 5 ++++- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/code/expression_test.dart | 8 ++++++++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 76ca9b541..55e76730e 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0 + +* Added support for raw `String` literals. + ## 2.0.0 Re-released without a direct dependency on `package:analyzer`! diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 92c17a11d..9385ac220 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -47,7 +47,10 @@ Expression literalNum(num value) => new LiteralExpression._('$value'); /// Create a literal expression from a string [value]. /// /// **NOTE**: The string is always formatted `''`. -Expression literalString(String value) => new LiteralExpression._("'$value'"); +/// +/// If [raw] is `true`, creates a raw String formatted `r''`. +Expression literalString(String value, {bool raw: false}) => + new LiteralExpression._("${raw ? 'r' : ''}'$value'"); /// Creates a literal list expression from [values]. LiteralListExpression literalList(List values, [Reference type]) { diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 5dd0f7736..10c9e9d3c 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.0.0 +version: 2.1.0-dev description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index b93f6cfe7..9ef9d761c 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -10,6 +10,14 @@ void main() { expect(literalNull, equalsDart('null')); }); + test('should emit a String', () { + expect(literalString(r'$monkey'), equalsDart(r"'$monkey'")); + }); + + test('should emit a raw String', () { + expect(literalString(r'$monkey', raw: true), equalsDart(r"r'$monkey'")); + }); + test('should emit a && expression', () { expect(literalTrue.and(literalFalse), equalsDart('true && false')); }); From 637b80dee4bd1c829e831b474402d8ecb0391433 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 30 Oct 2017 21:58:42 -0700 Subject: [PATCH 075/271] Use .accept not visitFoo where possible. (dart-lang/code_builder#153) --- pkgs/code_builder/lib/src/emitter.dart | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 22b6ed887..77fd6ee2b 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -251,7 +251,7 @@ class DartEmitter extends Object break; } if (spec.type != null) { - visitType(spec.type.type, output); + spec.type.type.accept(this, output); output.write(' '); } output.write(spec.name); @@ -269,17 +269,17 @@ class DartEmitter extends Object // Process the body first in order to prime the allocators. final body = new StringBuffer(); for (final spec in spec.body) { - body.write(visitSpec(spec)); + spec.accept(this, body); if (spec is Method && spec.lambda) { body.write(';'); } } // TODO: Allow some sort of logical ordering. for (final directive in spec.directives) { - visitDirective(directive, output); + directive.accept(this, output); } for (final directive in allocator.imports) { - visitDirective(directive, output); + directive.accept(this, output); } output.write(body); return output; @@ -329,7 +329,9 @@ class DartEmitter extends Object visitMethod(Method spec, [StringSink output]) { output ??= new StringBuffer(); spec.docs.forEach(output.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, output)); + for (final annotation in spec.annotations) { + annotation.accept(this, output); + } if (spec.external) { output.write('external '); } @@ -337,7 +339,7 @@ class DartEmitter extends Object output.write('static '); } if (spec.returns != null) { - visitType(spec.returns.type, output); + spec.returns.type.accept(this, output); output.write(' '); } if (spec.type == MethodType.getter) { @@ -422,9 +424,11 @@ class DartEmitter extends Object bool named: false, }) { spec.docs.forEach(output.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, output)); + for (final annotation in spec.annotations) { + annotation.accept(this, output); + } if (spec.type != null) { - visitType(spec.type.type, output); + spec.type.type.accept(this, output); output.write(' '); } if (spec.toThis) { @@ -452,10 +456,11 @@ class DartEmitter extends Object @override visitType(TypeReference spec, [StringSink output]) { output ??= new StringBuffer(); + // Intentionally not .accept to avoid stack overflow. visitReference(spec, output); if (spec.bound != null) { output.write(' extends '); - visitType(spec.bound.type, output); + spec.bound.type.accept(this, output); } visitTypeParameters(spec.types.map((r) => r.type), output); return output; From 29eb0d5b2862bef7b6b5808128daaebf4901e95c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 3 Nov 2017 14:47:53 -0700 Subject: [PATCH 076/271] Escape single quotes in String literals (dart-lang/code_builder#156) Closes dart-lang/code_builder#155 If there is an unescaped literal in a String the code would otherwise be invalid. If some code is doing the escaping before creating the literal this will end up double-escaping. --- pkgs/code_builder/CHANGELOG.md | 1 + .../lib/src/specs/expression/literal.dart | 13 ++++++++++--- .../test/specs/code/expression_test.dart | 8 ++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 55e76730e..4ce3ff0c9 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ ## 2.1.0 * Added support for raw `String` literals. +* Automatically escapes single quotes in now-raw `String` literals. ## 2.0.0 diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 9385ac220..fc33826c0 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -48,9 +48,16 @@ Expression literalNum(num value) => new LiteralExpression._('$value'); /// /// **NOTE**: The string is always formatted `''`. /// -/// If [raw] is `true`, creates a raw String formatted `r''`. -Expression literalString(String value, {bool raw: false}) => - new LiteralExpression._("${raw ? 'r' : ''}'$value'"); +/// If [raw] is `true`, creates a raw String formatted `r''` and the +/// value may not contain a single quote. +/// If [raw] is `false` escapes single quotes in the value. +Expression literalString(String value, {bool raw: false}) { + if (raw && value.contains('\'')) { + throw new ArgumentError('Cannot include a single quote in a raw string'); + } + final escaped = value.replaceAll('\'', '\\\''); + return new LiteralExpression._("${raw ? 'r' : ''}'$escaped'"); +} /// Creates a literal list expression from [values]. LiteralListExpression literalList(List values, [Reference type]) { diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 9ef9d761c..23d7d3673 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -18,6 +18,14 @@ void main() { expect(literalString(r'$monkey', raw: true), equalsDart(r"r'$monkey'")); }); + test('should escape single quotes in a String', () { + expect(literalString(r"don't"), equalsDart(r"'don\'t'")); + }); + + test('does not allow single quote in raw string', () { + expect(() => literalString(r"don't", raw: true), throwsArgumentError); + }); + test('should emit a && expression', () { expect(literalTrue.and(literalFalse), equalsDart('true && false')); }); From 7f2240b69762ef62fc8cf4f8ffeccb8e59f3601d Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 3 Nov 2017 14:55:38 -0700 Subject: [PATCH 077/271] Deprecate `File` --> `Library` (dart-lang/code_builder#157) * Got it working. * Fix bizarre VM bug. --- pkgs/code_builder/.travis.yml | 15 +-- pkgs/code_builder/CHANGELOG.md | 12 +++ pkgs/code_builder/README.md | 2 +- pkgs/code_builder/example/scope.dart | 2 +- pkgs/code_builder/lib/code_builder.dart | 4 +- pkgs/code_builder/lib/src/emitter.dart | 7 +- .../lib/src/specs/expression.dart | 2 +- pkgs/code_builder/lib/src/specs/file.dart | 41 -------- pkgs/code_builder/lib/src/specs/library.dart | 94 +++++++++++++++++++ .../src/specs/{file.g.dart => library.g.dart} | 0 pkgs/code_builder/lib/src/visitors.dart | 5 +- .../{file_test.dart => library_test.dart} | 12 +-- 12 files changed, 129 insertions(+), 67 deletions(-) delete mode 100644 pkgs/code_builder/lib/src/specs/file.dart create mode 100644 pkgs/code_builder/lib/src/specs/library.dart rename pkgs/code_builder/lib/src/specs/{file.g.dart => library.g.dart} (100%) rename pkgs/code_builder/test/specs/{file_test.dart => library_test.dart} (95%) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index d489071b4..87aaa5713 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -1,7 +1,6 @@ language: dart dart: - dev - - stable cache: directories: - $HOME/.pub-cache @@ -12,7 +11,7 @@ addons: chrome: stable branches: - only: [master, v2] + only: [master] # Check for analysis issues, run the test cases, and ensure `dartfmt` is run. dart_task: @@ -21,15 +20,3 @@ dart_task: - dartfmt # TODO: Test with dartdevc once https://github.com/dart-lang/sdk/issues/30810. - -# The Dart language is constantly being worked on, and sometimes the dev and -# stable builds don't agree on what is considered formatted or what is analysis -# warning free (though this does not effect _using_ the library, likely). -# -# We exclude `dev` from analysis and formatting checks. -matrix: - allow_failure: - - dart: dev - dart_task: dartfmt - - dart: dev - dart_task: dartanalyzer diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 4ce3ff0c9..28c8251c6 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -2,6 +2,18 @@ * Added support for raw `String` literals. * Automatically escapes single quotes in now-raw `String` literals. +* Deprecated `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: + +```dart +import 'dart:io'; + +import 'package:code_builder/code_builder.dart' hide File; +``` + +We will remove `File` in `3.0.0`, so use `Library` instead. ## 2.0.0 diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 7f959be86..f9002326c 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -66,7 +66,7 @@ import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; void main() { - final library = new File((b) => b.body.addAll([ + final library = new Library((b) => b.body.addAll([ new Method((b) => b ..body = const Code('') ..name = 'doThing' diff --git a/pkgs/code_builder/example/scope.dart b/pkgs/code_builder/example/scope.dart index 90207a8a7..8efff2c66 100644 --- a/pkgs/code_builder/example/scope.dart +++ b/pkgs/code_builder/example/scope.dart @@ -6,7 +6,7 @@ import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; void main() { - final library = new File((b) => b.body.addAll([ + final library = new Library((b) => b.body.addAll([ new Method((b) => b ..body = const Code('') ..name = 'doThing' diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 53473a208..69f651ab1 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -36,7 +36,9 @@ export 'src/specs/expression.dart' literalTrue, literalFalse; export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; -export 'src/specs/file.dart' show File, FileBuilder; +// TODO: Remove File, FileBuilder in 3.0.0. +// ignore: deprecated_member_use +export 'src/specs/library.dart' show File, FileBuilder, Library, LibraryBuilder; export 'src/specs/method.dart' show Method, diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 77fd6ee2b..e60307a01 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -13,7 +13,7 @@ import 'specs/constructor.dart'; import 'specs/directive.dart'; import 'specs/expression.dart'; import 'specs/field.dart'; -import 'specs/file.dart'; +import 'specs/library.dart'; import 'specs/method.dart'; import 'specs/reference.dart'; import 'specs/type_function.dart'; @@ -264,6 +264,11 @@ class DartEmitter extends Object } @override + visitLibrary(Library spec, [StringSink output]) => visitFile(spec, output); + + @override + // TODO: Remove File in 3.0.0. + // ignore: deprecated_member_use visitFile(File spec, [StringSink output]) { output ??= new StringBuffer(); // Process the body first in order to prime the allocators. diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 6203ed363..c1ae4504e 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -40,7 +40,7 @@ abstract class Expression implements Spec { /// The expression as a valid [Code] block with a trailing `;`. Code get statement => new ToCodeExpression(this, true); - /// Returns the result of [this] `&&` [other]. + /// Returns the result of `this` `&&` [other]. Expression and(Expression other) { return new BinaryExpression._(expression, other, '&&'); } diff --git a/pkgs/code_builder/lib/src/specs/file.dart b/pkgs/code_builder/lib/src/specs/file.dart deleted file mode 100644 index 39b5356f1..000000000 --- a/pkgs/code_builder/lib/src/specs/file.dart +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -library code_builder.src.specs.library; - -import 'package:built_collection/built_collection.dart'; -import 'package:built_value/built_value.dart'; -import 'package:meta/meta.dart'; - -import '../base.dart'; -import '../visitors.dart'; -import 'directive.dart'; - -part 'file.g.dart'; - -@immutable -abstract class File implements Built, Spec { - factory File([void updates(FileBuilder b)]) = _$File; - - File._(); - - BuiltList get directives; - BuiltList get body; - - @override - R accept( - SpecVisitor visitor, [ - R context, - ]) => - visitor.visitFile(this, context); -} - -abstract class FileBuilder implements Builder { - factory FileBuilder() = _$FileBuilder; - - FileBuilder._(); - - ListBuilder directives = new ListBuilder(); - ListBuilder body = new ListBuilder(); -} diff --git a/pkgs/code_builder/lib/src/specs/library.dart b/pkgs/code_builder/lib/src/specs/library.dart new file mode 100644 index 000000000..ae63180ec --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/library.dart @@ -0,0 +1,94 @@ +// 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. + +library code_builder.src.specs.library; + +import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../visitors.dart'; +import 'directive.dart'; + +part 'library.g.dart'; + +@Deprecated('Replace with "Library" by 3.0.0') +abstract class File implements Built, Spec { + factory File([void updates(FileBuilder b)]) = _$File; + File._(); + + BuiltList get directives; + BuiltList get body; + + @override + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitFile(this, context); +} + +@Deprecated('Replace with "LibraryBuilder" by 3.0.0') +abstract class FileBuilder implements Builder { + factory FileBuilder() = _$FileBuilder; + FileBuilder._(); + + ListBuilder directives = new ListBuilder(); + ListBuilder body = new ListBuilder(); +} + +@immutable +// TODO: Remove File in 3.0.0. +// ignore: deprecated_member_use +class Library extends _$File implements Spec { + factory Library([void updates(LibraryBuilder b)]) { + return (new LibraryBuilder()..update(updates)).build(); + } + + Library._({ + BuiltList directives, + BuiltList body, + }) + : super._(directives: directives, body: body); +} + +// TODO: Remove File in 3.0.0. +// +// This implementation is imperfect (not identical to the code emitted by +// the built_value package but seems to the only way to adhere to the +// inheritance chain without breaking the code generator). +// +// May be changed as a result of +// https://github.com/google/built_value.dart/issues/257. +// +// ignore: deprecated_member_use +class LibraryBuilder implements FileBuilder { + @override + ListBuilder body = new ListBuilder(); + + @override + ListBuilder directives = new ListBuilder(); + + @override + Library build() { + return new Library._(directives: directives.build(), body: body.build()); + } + + @override + void replace(covariant Library other) { + if (other == null) { + throw new ArgumentError.notNull('other'); + } + body = other.body.toBuilder(); + directives = other.directives.toBuilder(); + } + + @override + void update(void updates(LibraryBuilder builder)) { + if (updates != null) { + updates(this); + } + } +} diff --git a/pkgs/code_builder/lib/src/specs/file.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart similarity index 100% rename from pkgs/code_builder/lib/src/specs/file.g.dart rename to pkgs/code_builder/lib/src/specs/library.g.dart diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 111f4975d..d1160bc33 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -10,7 +10,7 @@ import 'specs/class.dart'; import 'specs/constructor.dart'; import 'specs/directive.dart'; import 'specs/field.dart'; -import 'specs/file.dart'; +import 'specs/library.dart'; import 'specs/method.dart'; import 'specs/reference.dart'; import 'specs/type_function.dart'; @@ -30,8 +30,11 @@ abstract class SpecVisitor { T visitField(Field spec, [T context]); + @Deprecated('Replace with visitLibrary by 3.0.0') T visitFile(File spec, [T context]); + T visitLibrary(Library spec, [T context]); + T visitFunctionType(FunctionType spec, [T context]); T visitMethod(Method spec, [T context]); diff --git a/pkgs/code_builder/test/specs/file_test.dart b/pkgs/code_builder/test/specs/library_test.dart similarity index 95% rename from pkgs/code_builder/test/specs/file_test.dart rename to pkgs/code_builder/test/specs/library_test.dart index 85b151f7e..ebc66c2d2 100644 --- a/pkgs/code_builder/test/specs/file_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -11,7 +11,7 @@ void main() { test('should emit a source file with manual imports', () { expect( - new File((b) => b + new Library((b) => b ..directives.add(new Directive.import('dart:collection')) ..body.add(new Field((b) => b ..name = 'test' @@ -27,7 +27,7 @@ void main() { test('should emit a source file with a deferred import', () { expect( - new File( + new Library( (b) => b ..directives.add( new Directive.importDeferredAs( @@ -44,7 +44,7 @@ void main() { test('should emit a source file with a "show" combinator', () { expect( - new File( + new Library( (b) => b ..directives.add( new Directive.import( @@ -61,7 +61,7 @@ void main() { test('should emit a source file with a "hide" combinator', () { expect( - new File( + new Library( (b) => b ..directives.add( new Directive.import( @@ -78,7 +78,7 @@ void main() { test('should emit a source file with allocation', () { expect( - new File((b) => b + new Library((b) => b ..body.add(new Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ @@ -94,7 +94,7 @@ void main() { test('should emit a source file with allocation + prefixing', () { expect( - new File((b) => b + new Library((b) => b ..body.add(new Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ From 78a79a71963197e0b7533d219f4708964ab54fd7 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 3 Nov 2017 15:40:49 -0700 Subject: [PATCH 078/271] Only support 2.0.0-dev. (dart-lang/code_builder#158) --- pkgs/code_builder/.travis.yml | 7 +++---- pkgs/code_builder/CHANGELOG.md | 2 ++ pkgs/code_builder/pubspec.yaml | 10 +++++++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index 87aaa5713..d206571e5 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -5,7 +5,6 @@ cache: directories: - $HOME/.pub-cache -# TODO: Use chrome in --headless mode once supported by pub run test. dist: trusty addons: chrome: stable @@ -13,10 +12,10 @@ addons: branches: only: [master] -# Check for analysis issues, run the test cases, and ensure `dartfmt` is run. +# TODO: Give up the dream of running with dartdevc until... +# https://github.com/dart-lang/sdk/issues/31280 + dart_task: - test: --platform vm - dartanalyzer - dartfmt - -# TODO: Test with dartdevc once https://github.com/dart-lang/sdk/issues/30810. diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 28c8251c6..2d5d6604e 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,7 @@ ## 2.1.0 +We now require the Dart 2.0-dev branch SDK (`>= 2.0.0-dev`). + * Added support for raw `String` literals. * Automatically escapes single quotes in now-raw `String` literals. * Deprecated `File`, which is now a redirect to the preferred class, `Library`. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 10c9e9d3c..bbec4bb9f 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -5,7 +5,11 @@ author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=1.24.0 <2.0.0' + sdk: '>=2.0.0-dev <2.0.0' + +web: + compiler: + debug: dartdevc dependencies: built_collection: ^1.0.0 @@ -19,3 +23,7 @@ dev_dependencies: built_value_generator: '>=2.0.0 <5.0.0' source_gen: '^0.7.0' test: ^0.12.0 + +transformers: + - test/pub_serve: + $include: test/**_test.dart From 1f9280af0a757f0ff1ea43c27d330f896955bcb7 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Sat, 4 Nov 2017 11:59:57 -0700 Subject: [PATCH 079/271] TBR: Actually publish. --- pkgs/code_builder/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index bbec4bb9f..aff8f0e88 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.1.0-dev +version: 2.1.0 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From 0e4b44774a2885511c036c5ebe31188ebfec4dd9 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 14 Nov 2017 14:28:50 -0800 Subject: [PATCH 080/271] Add '_i' to import prefixes (dart-lang/code_builder#160) This matches old behavior and is a little more clear than just a digit. This will also satisfy the lint on the latest SDK. See https://github.com/dart-lang/linter/issues/684#issuecomment-343543273 --- pkgs/code_builder/CHANGELOG.md | 5 +++++ pkgs/code_builder/README.md | 10 +++++----- pkgs/code_builder/lib/src/allocator.dart | 7 +++++-- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/allocator_test.dart | 4 ++-- pkgs/code_builder/test/e2e/injection_test.dart | 6 +++--- pkgs/code_builder/test/specs/code/expression_test.dart | 2 +- pkgs/code_builder/test/specs/library_test.dart | 4 ++-- 8 files changed, 24 insertions(+), 16 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 2d5d6604e..e94ccd74a 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.1.1-dev + +* Imports are prefixed with `_i1` rather than `_1` which satisfies the lint + `lowercase_with_underscores`. + ## 2.1.0 We now require the Dart 2.0-dev branch SDK (`>= 2.0.0-dev`). diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index f9002326c..de5393cd0 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -83,9 +83,9 @@ void main() { Outputs: ```dart -import 'package:a/a.dart' as _1; -import 'package:b/b.dart' as _2; +import 'package:a/a.dart' as _i1; +import 'package:b/b.dart' as _i2; -_1.Thing doThing() {} -_2.Other doOther() {} -``` \ No newline at end of file +_i1.Thing doThing() {} +_i2.Other doOther() {} +``` diff --git a/pkgs/code_builder/lib/src/allocator.dart b/pkgs/code_builder/lib/src/allocator.dart index aaf1c6900..f6289daa4 100644 --- a/pkgs/code_builder/lib/src/allocator.dart +++ b/pkgs/code_builder/lib/src/allocator.dart @@ -23,6 +23,9 @@ abstract class Allocator { /// style and instead takes a conservative approach of prefixing _every_ /// import except references to `dart:core` (which are considered always /// imported). + /// + /// The prefixes are not guaranteed to be stable and cannot be expected to + /// have any particular value. factory Allocator.simplePrefixing() = _PrefixedAllocator; /// Returns a reference string given a [reference] object. @@ -81,7 +84,7 @@ class _PrefixedAllocator implements Allocator { if (reference.url == null || _doNotPrefix.contains(reference.url)) { return symbol; } - return '_${_imports.putIfAbsent(reference.url, _nextKey)}.$symbol'; + return '_i${_imports.putIfAbsent(reference.url, _nextKey)}.$symbol'; } int _nextKey() => _keys++; @@ -89,7 +92,7 @@ class _PrefixedAllocator implements Allocator { @override Iterable get imports { return _imports.keys.map( - (u) => new Directive.import(u, as: '_${_imports[u]}'), + (u) => new Directive.import(u, as: '_i${_imports[u]}'), ); } } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index aff8f0e88..240786492 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.1.0 +version: 2.1.1-dev description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/allocator_test.dart b/pkgs/code_builder/test/allocator_test.dart index 0b7dab582..af57540e4 100644 --- a/pkgs/code_builder/test/allocator_test.dart +++ b/pkgs/code_builder/test/allocator_test.dart @@ -39,10 +39,10 @@ void main() { ); expect( allocator.allocate(refer('LinkedHashMap', 'dart:collection')), - '_1.LinkedHashMap', + '_i1.LinkedHashMap', ); expect(allocator.imports.map((d) => '${d.url} as ${d.as}'), [ - 'dart:collection as _1', + 'dart:collection as _i1', ]); }); }); diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index a4a1ae6a8..b493ca928 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -51,13 +51,13 @@ void main() { expect( clazz.build(), equalsDart(r''' - class Injector implements _1.App { + class Injector implements _i1.App { Injector(this._module); - final _2.Module _module; + final _i2.Module _module; @override - _3.Thing getThing() => new _3.Thing(_module.get1(), _module.get2()); + _i3.Thing getThing() => new _i3.Thing(_module.get1(), _module.get2()); } ''', new DartEmitter(new Allocator.simplePrefixing())), ); diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 23d7d3673..3aa724c49 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -83,7 +83,7 @@ void main() { test('should emit a scoped type as an expression', () { expect( refer('Foo', 'package:foo/foo.dart'), - equalsDart('_1.Foo', new DartEmitter(new Allocator.simplePrefixing())), + equalsDart('_i1.Foo', new DartEmitter(new Allocator.simplePrefixing())), ); }); diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index ebc66c2d2..4dc5d9944 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -101,9 +101,9 @@ void main() { ..assignment = new Code.scope((a) => 'new ${a($LinkedHashMap)}()')))), equalsDart(r''' - import 'dart:collection' as _1; + import 'dart:collection' as _i1; - final test = new _1.LinkedHashMap(); + final test = new _i1.LinkedHashMap(); ''', new DartEmitter(new Allocator.simplePrefixing())), ); }); From 291ce44ef636917712637602f266e40920bf8087 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 20 Nov 2017 11:03:01 -0800 Subject: [PATCH 081/271] Accept an Iterable in `literalList` (dart-lang/code_builder#162) Since the LiteralListExpression is in the public API we shouldn't change it's field type, so immediately call .toList() --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/specs/expression/literal.dart | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index e94ccd74a..c16cccd07 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -2,6 +2,7 @@ * Imports are prefixed with `_i1` rather than `_1` which satisfies the lint `lowercase_with_underscores`. +* `literalList` accepts an `Iterable` argument. ## 2.1.0 diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index fc33826c0..b98825056 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -60,8 +60,8 @@ Expression literalString(String value, {bool raw: false}) { } /// Creates a literal list expression from [values]. -LiteralListExpression literalList(List values, [Reference type]) { - return new LiteralListExpression._(false, values, type); +LiteralListExpression literalList(Iterable values, [Reference type]) { + return new LiteralListExpression._(false, values.toList(), type); } /// Creates a literal `const` list expression from [values]. From b61259036f193e07cd4b66410a839adfbf0dada7 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 20 Nov 2017 20:37:41 -0800 Subject: [PATCH 082/271] Add index operator access to Expression. (dart-lang/code_builder#161) * Add index operator access to Expression. * Address feedback. --- pkgs/code_builder/CHANGELOG.md | 31 +++++++++++++++++-- .../lib/src/specs/expression.dart | 13 ++++++++ pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 29 +++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index c16cccd07..d82ab65d2 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,7 +1,34 @@ -## 2.1.1-dev +## 2.2.0-dev * Imports are prefixed with `_i1` rather than `_1` which satisfies the lint - `lowercase_with_underscores`. + `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: + +```dart +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. ## 2.1.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index c1ae4504e..50d3ec61d 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -45,6 +45,19 @@ abstract class Expression implements Spec { return new BinaryExpression._(expression, other, '&&'); } + /// Returns accessing the index operator (`[]`) on `this`. + Expression index(Expression index) { + return new BinaryExpression._( + expression, + new CodeExpression(new Block.of([ + const Code('['), + index.code, + const Code(']'), + ])), + '', + ); + } + /// This expression preceded by `await`. Expression get awaited { return new BinaryExpression._( diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 240786492..0e587011b 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.1.1-dev +version: 2.2.0-dev description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 3aa724c49..7cf584562 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -266,6 +266,35 @@ void main() { ); }); + test('should emit an index operator', () { + expect( + refer('bar').index(literalString('key')).assignVar('foo').statement, + equalsDart("var foo = bar['key'];"), + ); + }); + + test('should emit an index operator set', () { + expect( + refer('bar') + .index(literalString('key')) + .assign(literalFalse) + .assignVar('foo') + .statement, + equalsDart("var foo = bar['key'] = false;"), + ); + }); + + test('should emit a null-aware index operator set', () { + expect( + refer('bar') + .index(literalTrue) + .assignNullAware(literalFalse) + .assignVar('foo') + .statement, + equalsDart('var foo = bar[true] ??= false;'), + ); + }); + test('should emit assigning to a var', () { expect( literalTrue.assignVar('foo'), From c64d729e034982236f729b6eea73e7cd92df918e Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 21 Nov 2017 21:03:23 -0800 Subject: [PATCH 083/271] Fix bug and get ready to release. (dart-lang/code_builder#164) --- pkgs/code_builder/CHANGELOG.md | 23 ++++++++++++++++++- pkgs/code_builder/lib/src/emitter.dart | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/method_test.dart | 15 ++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index d82ab65d2..602819247 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.2.0-dev +## 2.2.0 * Imports are prefixed with `_i1` rather than `_1` which satisfies the lint `lowercase_with_underscores`. While not a strictly breaking change you may @@ -31,6 +31,27 @@ void main() { * `literalList` accepts an `Iterable` argument. +* Fixed an NPE when a method had a return type of a `FunctionType`: + +```dart +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(); + '''), + ); + }); +} +``` + ## 2.1.0 We now require the Dart 2.0-dev branch SDK (`>= 2.0.0-dev`). diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index e60307a01..490c8b517 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -344,7 +344,7 @@ class DartEmitter extends Object output.write('static '); } if (spec.returns != null) { - spec.returns.type.accept(this, output); + spec.returns.accept(this, output); output.write(' '); } if (spec.type == MethodType.getter) { diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 0e587011b..42dbfb540 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.2.0-dev +version: 2.2.0 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index cea286e75..6cfe11c0f 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -99,6 +99,21 @@ 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(); + '''), + ); + }); + test('should create a method with generic types', () { expect( new Method((b) => b From a9460725101a9ea244e80fb44623ca3f23540608 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 22 Nov 2017 12:35:08 -0800 Subject: [PATCH 084/271] Update README.md Trivial update for badging. --- pkgs/code_builder/README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index de5393cd0..b0af2900c 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -1,8 +1,9 @@ # 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/github/dart-lang/code_builder/badge.svg?branch=master)](https://coveralls.io/github/dart-lang/code_builder?branch=master) +[![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) +[![Latest docs](https://img.shields.io/badge/dartdocs-latest-blue.svg)](https://www.dartdocs.org/documentation/code_builder/latest) +[![Gitter chat](https://badges.gitter.im/dart-lang/source_gen.svg)](https://gitter.im/dart-lang/source_gen) `code_builder` is a fluent Dart API for generating valid Dart source code. @@ -18,10 +19,10 @@ will be on a best-effort basis. > **NOTE**: Due to the evolving Dart SDK the local `dartfmt` must be used to > format this repository. You can run it simply from the command-line: - -```sh -$ pub run dart_style:format -w . -``` +> +> ```sh +> $ pub run dart_style:format -w . +> ``` [wiki]: https://github.com/dart-lang/code_builder/wiki [issue]: https://github.com/dart-lang/code_builder/issues From ac8beb57c93f9dcd6bd5738452422b2fcd8e5139 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 22 Nov 2017 13:10:46 -0800 Subject: [PATCH 085/271] Add isA and isNotA. (dart-lang/code_builder#166) * Add isA and isNotA. * Fix pubspec. --- pkgs/code_builder/CHANGELOG.md | 17 ++++++++++++++++- .../code_builder/lib/src/specs/expression.dart | 18 ++++++++++++++++++ pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 14 ++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 602819247..d0ef2674f 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,18 @@ +## 2.3.0-dev + +* Added `Expression.isA` and `Expression.isNotA`: + +```dart +void main() { + test('should emit an is check', () { + expect( + refer('foo').isA(refer('String')), + equalsDart('foo is String'), + ); + }); +} +``` + ## 2.2.0 * Imports are prefixed with `_i1` rather than `_1` which satisfies the lint @@ -14,7 +29,7 @@ void main() { refer('bar').index(literalTrue).assignVar('foo').statement, equalsDart('var foo = bar[true];'), ); -} ); + }); test('should emit an index operator set', () { expect( diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 50d3ec61d..72d8693d0 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -58,6 +58,24 @@ abstract class Expression implements Spec { ); } + /// Returns the result of `this` `is` [other]. + Expression isA(Expression other) { + return new BinaryExpression._( + expression, + other, + 'is', + ); + } + + /// Returns the result of `this` `is!` [other]. + Expression isNotA(Expression other) { + return new BinaryExpression._( + expression, + other, + 'is!', + ); + } + /// This expression preceded by `await`. Expression get awaited { return new BinaryExpression._( diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 42dbfb540..d471cf602 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.2.0 +version: 2.3.0-dev description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 7cf584562..6bd1d3c0d 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -336,4 +336,18 @@ void main() { equalsDart('return null'), ); }); + + test('should emit an is check', () { + expect( + refer('foo').isA(refer('String')), + equalsDart('foo is String'), + ); + }); + + test('should emit an is! check', () { + expect( + refer('foo').isNotA(refer('String')), + equalsDart('foo is! String'), + ); + }); } From a9a40e18a1c50810a4bc486185d265499ee515ac Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 22 Nov 2017 16:11:27 -0800 Subject: [PATCH 086/271] Add EqualsDart and EqualsDart.format. (dart-lang/code_builder#167) * Add EqualsDart and EqualsDart.format. * Fix pubspec. --- pkgs/code_builder/CHANGELOG.md | 27 ++++++++++ pkgs/code_builder/lib/code_builder.dart | 2 +- pkgs/code_builder/lib/src/matchers.dart | 54 ++++++++++++------- pkgs/code_builder/pubspec.yaml | 1 + pkgs/code_builder/test/allocator_test.dart | 4 ++ pkgs/code_builder/test/common.dart | 18 +++++++ .../code_builder/test/e2e/injection_test.dart | 4 ++ pkgs/code_builder/test/specs/class_test.dart | 4 ++ .../test/specs/code/expression_test.dart | 4 ++ .../test/specs/code/statement_test.dart | 4 ++ pkgs/code_builder/test/specs/field_test.dart | 4 ++ .../code_builder/test/specs/library_test.dart | 4 ++ pkgs/code_builder/test/specs/method_test.dart | 4 ++ 13 files changed, 114 insertions(+), 20 deletions(-) create mode 100644 pkgs/code_builder/test/common.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index d0ef2674f..1e07124c7 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,32 @@ ## 2.3.0-dev +* Using `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: + +```dart +// 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; +``` + * Added `Expression.isA` and `Expression.isNotA`: ```dart diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 69f651ab1..bc93e6bc5 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -5,7 +5,7 @@ export 'src/allocator.dart' show Allocator; export 'src/base.dart' show lazySpec, Spec; export 'src/emitter.dart' show DartEmitter; -export 'src/matchers.dart' show equalsDart; +export 'src/matchers.dart' show equalsDart, EqualsDart; export 'src/specs/annotation.dart' show Annotation, AnnotationBuilder; export 'src/specs/class.dart' show Class, ClassBuilder; export 'src/specs/code.dart' diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index fa4991f61..49796c3b4 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -8,37 +8,53 @@ import 'package:matcher/matcher.dart'; import 'base.dart'; import 'emitter.dart'; -final _formatter = new DartFormatter(); - -/// Runs dartfmt. -String _dartfmt(String source) { - try { - source = _formatter.format(source); - } on FormatException catch (_) { - source = _formatter.formatStatement(source); - } catch (_) { - // Ignored on purpose, probably not exactly valid Dart code. - source = collapseWhitespace(source); - } - return source; -} - /// Encodes [spec] as Dart source code. String _dart(Spec spec, DartEmitter emitter) => - _dartfmt(spec.accept(emitter).toString()).trim(); + EqualsDart._format(spec.accept(emitter).toString()); /// Returns a matcher for Dart source code. Matcher equalsDart( String source, [ DartEmitter emitter, ]) => - new _EqualsDart(_dartfmt(source).trim(), emitter ?? new DartEmitter()); + new EqualsDart._(EqualsDart._format(source), emitter ?? new DartEmitter()); + +/// Implementation detail of using the [equalsDart] matcher. +/// +/// See [EqualsDart.format] to specify the default source code formatter. +class EqualsDart extends Matcher { + // TODO: Remove in 3.0.0. + static final _formatter = new DartFormatter(); + + /// May override to provide a function to format Dart on [equalsDart]. + /// + /// As of `2.x.x`, this defaults to using `dartfmt`, but in an upcoming + /// release (`3.x.x`) it will default to [collapseWhitespace]. This is in + /// order to avoid a dependency on specific versions of `dartfmt` and the + /// `analyzer` package. + /// + /// To future proof, see an example in code_builder's `test/common.dart`. + static String Function(String) format = (String source) { + try { + return _formatter.format(source); + } on FormatException catch (_) { + return _formatter.formatStatement(source); + } + }; + + static String _format(String source) { + try { + return format(source).trim(); + } catch (_) { + // Ignored on purpose, probably not exactly valid Dart code. + return collapseWhitespace(source).trim(); + } + } -class _EqualsDart extends Matcher { final DartEmitter _emitter; final String _source; - const _EqualsDart(this._source, this._emitter); + const EqualsDart._(this._source, this._emitter); @override Description describe(Description description) => description.add(_source); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index d471cf602..f9a45ac4b 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -14,6 +14,7 @@ web: dependencies: built_collection: ^1.0.0 built_value: '>=2.0.0 <5.0.0' + # TODO: Move to dev_dependency in 3.0.0. dart_style: ^1.0.0 matcher: ^0.12.0 meta: ^1.0.5 diff --git a/pkgs/code_builder/test/allocator_test.dart b/pkgs/code_builder/test/allocator_test.dart index af57540e4..25ca1f401 100644 --- a/pkgs/code_builder/test/allocator_test.dart +++ b/pkgs/code_builder/test/allocator_test.dart @@ -5,7 +5,11 @@ import 'package:code_builder/code_builder.dart'; import 'package:test/test.dart'; +import 'common.dart'; + void main() { + useDartfmt(); + group('Allocator', () { Allocator allocator; diff --git a/pkgs/code_builder/test/common.dart b/pkgs/code_builder/test/common.dart new file mode 100644 index 000000000..de8dde16b --- /dev/null +++ b/pkgs/code_builder/test/common.dart @@ -0,0 +1,18 @@ +// 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; diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index b493ca928..2580d7d7f 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -5,7 +5,11 @@ import 'package:code_builder/code_builder.dart'; import 'package:test/test.dart'; +import '../common.dart'; + void main() { + useDartfmt(); + test('should generate a complex generated file', () { // Imports from an existing Dart library. final $App = refer('App', 'package:app/app.dart'); diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index f05c41a86..0744f11c4 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -5,7 +5,11 @@ import 'package:code_builder/code_builder.dart'; import 'package:test/test.dart'; +import '../common.dart'; + void main() { + useDartfmt(); + test('should create a class', () { expect( new Class((b) => b..name = 'Foo'), diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 6bd1d3c0d..11607af52 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -5,7 +5,11 @@ import 'package:code_builder/code_builder.dart'; import 'package:test/test.dart'; +import '../../common.dart'; + void main() { + useDartfmt(); + test('should emit a simple expression', () { expect(literalNull, equalsDart('null')); }); diff --git a/pkgs/code_builder/test/specs/code/statement_test.dart b/pkgs/code_builder/test/specs/code/statement_test.dart index 11a830a1c..a31d5565c 100644 --- a/pkgs/code_builder/test/specs/code/statement_test.dart +++ b/pkgs/code_builder/test/specs/code/statement_test.dart @@ -5,7 +5,11 @@ import 'package:code_builder/code_builder.dart'; import 'package:test/test.dart'; +import '../../common.dart'; + void main() { + useDartfmt(); + test('should emit a block of code', () { expect( new Block.of([ diff --git a/pkgs/code_builder/test/specs/field_test.dart b/pkgs/code_builder/test/specs/field_test.dart index 2f132ea91..afda0b2f7 100644 --- a/pkgs/code_builder/test/specs/field_test.dart +++ b/pkgs/code_builder/test/specs/field_test.dart @@ -5,7 +5,11 @@ import 'package:code_builder/code_builder.dart'; import 'package:test/test.dart'; +import '../common.dart'; + void main() { + useDartfmt(); + test('should create a field', () { expect( new Field((b) => b..name = 'foo'), diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index 4dc5d9944..29ef147ca 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -5,7 +5,11 @@ import 'package:code_builder/code_builder.dart'; import 'package:test/test.dart'; +import '../common.dart'; + void main() { + useDartfmt(); + group('File', () { final $LinkedHashMap = refer('LinkedHashMap', 'dart:collection'); diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 6cfe11c0f..43dbf1fee 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -5,7 +5,11 @@ import 'package:code_builder/code_builder.dart'; import 'package:test/test.dart'; +import '../common.dart'; + void main() { + useDartfmt(); + test('should create a method', () { expect( new Method((b) => b..name = 'foo'), From 50a91e56c5034da6bb31c037c262f8b927861e95 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 22 Nov 2017 16:14:58 -0800 Subject: [PATCH 087/271] Deprecate the Annotation class. (dart-lang/code_builder#168) * Deprecate the Annotation class. * Use @protected with a field. --- pkgs/code_builder/CHANGELOG.md | 23 ++++++++++++++ pkgs/code_builder/lib/code_builder.dart | 2 ++ pkgs/code_builder/lib/src/emitter.dart | 16 +++++----- .../lib/src/mixins/annotations.dart | 10 +++++-- .../lib/src/specs/annotation.dart | 30 +++++++++++++++---- .../lib/src/specs/annotation.g.dart | 27 +++++++++-------- pkgs/code_builder/lib/src/specs/class.dart | 6 ++-- pkgs/code_builder/lib/src/specs/class.g.dart | 8 ++--- .../lib/src/specs/constructor.dart | 6 ++-- .../lib/src/specs/constructor.g.dart | 8 ++--- .../lib/src/specs/expression.dart | 7 +++-- pkgs/code_builder/lib/src/specs/field.dart | 6 ++-- pkgs/code_builder/lib/src/specs/field.g.dart | 8 ++--- pkgs/code_builder/lib/src/specs/method.dart | 9 +++--- pkgs/code_builder/lib/src/specs/method.g.dart | 16 +++++----- pkgs/code_builder/lib/src/visitors.dart | 4 +-- .../code_builder/test/e2e/injection_test.dart | 3 +- pkgs/code_builder/test/specs/class_test.dart | 25 ++++++++++++---- pkgs/code_builder/test/specs/method_test.dart | 19 +++++++++++- 19 files changed, 158 insertions(+), 75 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 1e07124c7..59e6e9bf5 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -40,6 +40,29 @@ void main() { } ``` +* Deprecated `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: + +```dart +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(); + } + '''), + ); + }); +} +``` + ## 2.2.0 * Imports are prefixed with `_i1` rather than `_1` which satisfies the lint diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index bc93e6bc5..77edcbf1d 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -6,6 +6,8 @@ export 'src/allocator.dart' show Allocator; export 'src/base.dart' show lazySpec, Spec; export 'src/emitter.dart' show DartEmitter; export 'src/matchers.dart' show equalsDart, EqualsDart; +export 'src/matchers.dart' show equalsDart; +// ignore: deprecated_member_use export 'src/specs/annotation.dart' show Annotation, AnnotationBuilder; export 'src/specs/class.dart' show Class, ClassBuilder; export 'src/specs/code.dart' diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 490c8b517..fd8a9b443 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -65,9 +65,13 @@ class DartEmitter extends Object } @override - visitAnnotation(Annotation spec, [StringSink output]) { + visitAnnotation(Expression spec, [StringSink output]) { (output ??= new StringBuffer()).write('@'); - spec.code.accept(this, output); + if (spec is Annotation) { + spec.code.accept(this, output); + } else { + spec.accept(this, output); + } output.write(' '); return output; } @@ -334,9 +338,7 @@ class DartEmitter extends Object visitMethod(Method spec, [StringSink output]) { output ??= new StringBuffer(); spec.docs.forEach(output.writeln); - for (final annotation in spec.annotations) { - annotation.accept(this, output); - } + spec.annotations.forEach((a) => visitAnnotation(a, output)); if (spec.external) { output.write('external '); } @@ -429,9 +431,7 @@ class DartEmitter extends Object bool named: false, }) { spec.docs.forEach(output.writeln); - for (final annotation in spec.annotations) { - annotation.accept(this, output); - } + spec.annotations.forEach((a) => visitAnnotation(a, output)); if (spec.type != null) { spec.type.type.accept(this, output); output.write(' '); diff --git a/pkgs/code_builder/lib/src/mixins/annotations.dart b/pkgs/code_builder/lib/src/mixins/annotations.dart index 05d41fe67..f8bc94836 100644 --- a/pkgs/code_builder/lib/src/mixins/annotations.dart +++ b/pkgs/code_builder/lib/src/mixins/annotations.dart @@ -4,12 +4,16 @@ import 'package:built_collection/built_collection.dart'; -import '../specs/annotation.dart'; +import '../specs/expression.dart'; +/// A type of AST node that can have metadata [annotations]. abstract class HasAnnotations { - BuiltList get annotations; + /// Annotations as metadata on the node. + BuiltList get annotations; } +/// Compliment to the [HasAnnotations] mixin for metadata [annotations]. abstract class HasAnnotationsBuilder { - ListBuilder annotations; + /// Annotations as metadata on the node. + ListBuilder annotations; } diff --git a/pkgs/code_builder/lib/src/specs/annotation.dart b/pkgs/code_builder/lib/src/specs/annotation.dart index 83c5f85ec..1bf330bc0 100644 --- a/pkgs/code_builder/lib/src/specs/annotation.dart +++ b/pkgs/code_builder/lib/src/specs/annotation.dart @@ -10,29 +10,47 @@ import 'package:meta/meta.dart'; import '../base.dart'; import '../visitors.dart'; import 'code.dart'; +import 'expression.dart'; part 'annotation.g.dart'; +@Deprecated('Use an Expression node instead. Will be removed in 3.0.0.') @immutable -abstract class Annotation +abstract class Annotation extends Expression implements Built, Spec { factory Annotation([void updates(AnnotationBuilder b)]) = _$Annotation; Annotation._(); /// Part after the `@` in annotation. - Code get code; + @override + Code get code => codeForAnnotation; + + /// Use [code] instead. + /// + /// This property exists in order to keep compatibility with having a concrete + /// [Annotation] class, but also allow migrating to using [Expression] instead + /// to add annotations. + @protected + Code get codeForAnnotation; @override - R accept(SpecVisitor visitor, [R context]) => - visitor.visitAnnotation(this, context); + R accept(SpecVisitor visitor, [R context]) { + return visitor.visitAnnotation(this, context); + } } abstract class AnnotationBuilder - implements Builder { + // ignore: deprecated_member_use + implements + Builder { factory AnnotationBuilder() = _$AnnotationBuilder; AnnotationBuilder._(); - Code code; + Code get code => codeForAnnotation; + set code(Code code) => codeForAnnotation = code; + + @protected + Code codeForAnnotation; } diff --git a/pkgs/code_builder/lib/src/specs/annotation.g.dart b/pkgs/code_builder/lib/src/specs/annotation.g.dart index 4a572ec7f..63689232f 100644 --- a/pkgs/code_builder/lib/src/specs/annotation.g.dart +++ b/pkgs/code_builder/lib/src/specs/annotation.g.dart @@ -16,13 +16,14 @@ part of code_builder.src.specs.annotation; class _$Annotation extends Annotation { @override - final Code code; + final Code codeForAnnotation; factory _$Annotation([void updates(AnnotationBuilder b)]) => (new AnnotationBuilder()..update(updates)).build() as _$Annotation; - _$Annotation._({this.code}) : super._() { - if (code == null) throw new ArgumentError.notNull('code'); + _$Annotation._({this.codeForAnnotation}) : super._() { + if (codeForAnnotation == null) + throw new ArgumentError.notNull('codeForAnnotation'); } @override @@ -36,17 +37,18 @@ class _$Annotation extends Annotation { bool operator ==(dynamic other) { if (identical(other, this)) return true; if (other is! Annotation) return false; - return code == other.code; + return codeForAnnotation == other.codeForAnnotation; } @override int get hashCode { - return $jf($jc(0, code.hashCode)); + return $jf($jc(0, codeForAnnotation.hashCode)); } @override String toString() { - return (newBuiltValueToStringHelper('Annotation')..add('code', code)) + return (newBuiltValueToStringHelper('Annotation') + ..add('codeForAnnotation', codeForAnnotation)) .toString(); } } @@ -55,22 +57,22 @@ class _$AnnotationBuilder extends AnnotationBuilder { _$Annotation _$v; @override - Code get code { + Code get codeForAnnotation { _$this; - return super.code; + return super.codeForAnnotation; } @override - set code(Code code) { + set codeForAnnotation(Code codeForAnnotation) { _$this; - super.code = code; + super.codeForAnnotation = codeForAnnotation; } _$AnnotationBuilder() : super._(); AnnotationBuilder get _$this { if (_$v != null) { - super.code = _$v.code; + super.codeForAnnotation = _$v.codeForAnnotation; _$v = null; } return this; @@ -89,7 +91,8 @@ class _$AnnotationBuilder extends AnnotationBuilder { @override _$Annotation build() { - final _$result = _$v ?? new _$Annotation._(code: code); + final _$result = + _$v ?? new _$Annotation._(codeForAnnotation: codeForAnnotation); replace(_$result); return _$result; } diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart index 41d4ae6ea..5e12ec1f9 100644 --- a/pkgs/code_builder/lib/src/specs/class.dart +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -13,8 +13,8 @@ import '../mixins/annotations.dart'; import '../mixins/dartdoc.dart'; import '../mixins/generics.dart'; import '../visitors.dart'; -import 'annotation.dart'; import 'constructor.dart'; +import 'expression.dart'; import 'field.dart'; import 'method.dart'; import 'reference.dart'; @@ -33,7 +33,7 @@ abstract class Class extends Object bool get abstract; @override - BuiltList get annotations; + BuiltList get annotations; @override BuiltList get docs; @@ -74,7 +74,7 @@ abstract class ClassBuilder extends Object bool abstract = false; @override - ListBuilder annotations = new ListBuilder(); + ListBuilder annotations = new ListBuilder(); @override ListBuilder docs = new ListBuilder(); diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index 25d4ba891..4baa92c5f 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -18,7 +18,7 @@ class _$Class extends Class { @override final bool abstract; @override - final BuiltList annotations; + final BuiltList annotations; @override final BuiltList docs; @override @@ -148,13 +148,13 @@ class _$ClassBuilder extends ClassBuilder { } @override - ListBuilder get annotations { + ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations ??= new ListBuilder(); } @override - set annotations(ListBuilder annotations) { + set annotations(ListBuilder annotations) { _$this; super.annotations = annotations; } diff --git a/pkgs/code_builder/lib/src/specs/constructor.dart b/pkgs/code_builder/lib/src/specs/constructor.dart index 3256fd071..590ecfb64 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.dart @@ -10,8 +10,8 @@ import 'package:meta/meta.dart'; import '../mixins/annotations.dart'; import '../mixins/dartdoc.dart'; -import 'annotation.dart'; import 'code.dart'; +import 'expression.dart'; import 'method.dart'; import 'reference.dart'; @@ -26,7 +26,7 @@ abstract class Constructor extends Object Constructor._(); @override - BuiltList get annotations; + BuiltList get annotations; @override BuiltList get docs; @@ -73,7 +73,7 @@ abstract class ConstructorBuilder extends Object ConstructorBuilder._(); @override - ListBuilder annotations = new ListBuilder(); + ListBuilder annotations = new ListBuilder(); @override ListBuilder docs = new ListBuilder(); diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index 8b2cd4b59..fa60d56d9 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -16,7 +16,7 @@ part of code_builder.src.specs.constructor; class _$Constructor extends Constructor { @override - final BuiltList annotations; + final BuiltList annotations; @override final BuiltList docs; @override @@ -144,13 +144,13 @@ class _$ConstructorBuilder extends ConstructorBuilder { _$Constructor _$v; @override - ListBuilder get annotations { + ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations ??= new ListBuilder(); } @override - set annotations(ListBuilder annotations) { + set annotations(ListBuilder annotations) { _$this; super.annotations = annotations; } diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 72d8693d0..9bfc9f5aa 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -173,7 +173,8 @@ abstract class Expression implements Spec { } /// Returns an annotation as a result of calling this constructor. - Annotation annotation([ + @Deprecated('Use "call" instead. Will be removed in 3.0.0.') + Expression annotation([ List positionalArguments, Map namedArguments = const {}, List typeArguments = const [], @@ -195,12 +196,14 @@ abstract class Expression implements Spec { } /// Returns an annotation as a result of calling a named constructor. - Annotation annotationNamed( + @Deprecated('Use a combination of "property" and "call". Removing in 3.0.0.') + Expression annotationNamed( String name, List positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { + // ignore: deprecated_member_use return new Annotation((b) => b ..code = new InvokeExpression._( this, positionalArguments, namedArguments, typeArguments, name) diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index 661537a36..201ae9c98 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -12,8 +12,8 @@ import '../base.dart'; import '../mixins/annotations.dart'; import '../mixins/dartdoc.dart'; import '../visitors.dart'; -import 'annotation.dart'; import 'code.dart'; +import 'expression.dart'; import 'reference.dart'; part 'field.g.dart'; @@ -27,7 +27,7 @@ abstract class Field extends Object Field._(); @override - BuiltList get annotations; + BuiltList get annotations; @override BuiltList get docs; @@ -71,7 +71,7 @@ abstract class FieldBuilder extends Object FieldBuilder._(); @override - ListBuilder annotations = new ListBuilder(); + ListBuilder annotations = new ListBuilder(); @override ListBuilder docs = new ListBuilder(); diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 407ac8942..75d88be12 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -16,7 +16,7 @@ part of code_builder.src.specs.field; class _$Field extends Field { @override - final BuiltList annotations; + final BuiltList annotations; @override final BuiltList docs; @override @@ -101,13 +101,13 @@ class _$FieldBuilder extends FieldBuilder { _$Field _$v; @override - ListBuilder get annotations { + ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations ??= new ListBuilder(); } @override - set annotations(ListBuilder annotations) { + set annotations(ListBuilder annotations) { _$this; super.annotations = annotations; } diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 1de7dd688..754700df4 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -13,7 +13,6 @@ import '../mixins/annotations.dart'; import '../mixins/dartdoc.dart'; import '../mixins/generics.dart'; import '../visitors.dart'; -import 'annotation.dart'; import 'code.dart'; import 'expression.dart'; import 'reference.dart'; @@ -40,7 +39,7 @@ abstract class Method extends Object Method._(); @override - BuiltList get annotations; + BuiltList get annotations; @override BuiltList get docs; @@ -105,7 +104,7 @@ abstract class MethodBuilder extends Object MethodBuilder._(); @override - ListBuilder annotations = new ListBuilder(); + ListBuilder annotations = new ListBuilder(); @override ListBuilder docs = new ListBuilder(); @@ -179,7 +178,7 @@ abstract class Parameter extends Object bool get toThis; @override - BuiltList get annotations; + BuiltList get annotations; @override BuiltList get docs; @@ -214,7 +213,7 @@ abstract class ParameterBuilder extends Object bool toThis = false; @override - ListBuilder annotations = new ListBuilder(); + ListBuilder annotations = new ListBuilder(); @override ListBuilder docs = new ListBuilder(); diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index 1f1946e0b..7914ba2d3 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -16,7 +16,7 @@ part of code_builder.src.specs.method; class _$Method extends Method { @override - final BuiltList annotations; + final BuiltList annotations; @override final BuiltList docs; @override @@ -152,13 +152,13 @@ class _$MethodBuilder extends MethodBuilder { _$Method _$v; @override - ListBuilder get annotations { + ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations ??= new ListBuilder(); } @override - set annotations(ListBuilder annotations) { + set annotations(ListBuilder annotations) { _$this; super.annotations = annotations; } @@ -372,7 +372,7 @@ class _$Parameter extends Parameter { @override final bool toThis; @override - final BuiltList annotations; + final BuiltList annotations; @override final BuiltList docs; @override @@ -505,13 +505,13 @@ class _$ParameterBuilder extends ParameterBuilder { } @override - ListBuilder get annotations { + ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations ??= new ListBuilder(); } @override - set annotations(ListBuilder annotations) { + set annotations(ListBuilder annotations) { _$this; super.annotations = annotations; } diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index d1160bc33..882fa8774 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -5,10 +5,10 @@ import 'package:meta/meta.dart'; import 'base.dart'; -import 'specs/annotation.dart'; import 'specs/class.dart'; import 'specs/constructor.dart'; import 'specs/directive.dart'; +import 'specs/expression.dart'; import 'specs/field.dart'; import 'specs/library.dart'; import 'specs/method.dart'; @@ -20,7 +20,7 @@ import 'specs/type_reference.dart'; abstract class SpecVisitor { const SpecVisitor._(); - T visitAnnotation(Annotation spec, [T context]); + T visitAnnotation(Expression spec, [T context]); T visitClass(Class spec, [T context]); diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index 2580d7d7f..0858e5374 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -35,8 +35,7 @@ void main() { ]).code ..lambda = true ..returns = $Thing - ..annotations - .add(new Annotation((b) => b..code = const Code('override'))))); + ..annotations.add(refer('override')))); expect( clazz.build(), diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 0744f11c4..3ae497443 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -54,9 +54,8 @@ void main() { (b) => b ..name = 'Foo' ..annotations.addAll([ - refer('deprecated').annotation(), - refer('Deprecated') - .annotation([literalString('This is an old class')]) + refer('deprecated'), + refer('Deprecated').call([literalString('This is an old class')]) ]), ), equalsDart(r''' @@ -180,13 +179,29 @@ void main() { ); }); - test('should create a class with a constructor with an annotation', () { + test('should create a class with an annotated constructor [deprecated]', () { expect( new Class((b) => b ..name = 'Foo' ..constructors.add(new Constructor((b) => b ..annotations.add( - new Annotation((b) => b..code = const Code('deprecated')))))), + new Annotation((b) => b..code = const Code('deprecated')), + )))), + equalsDart(r''' + class Foo { + @deprecated + Foo(); + } + '''), + ); + }); + + 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 diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 43dbf1fee..85a9bdf4c 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -196,7 +196,7 @@ void main() { ); }); - test('should create a method with a paremter with an annotation', () { + test('should create a method with an annotated parameter [deprecated]', () { expect( new Method( (b) => b @@ -214,6 +214,23 @@ void main() { ); }); + test('should create a method with an annotated parameter', () { + expect( + new Method( + (b) => b + ..name = 'fib' + ..requiredParameters.add( + new Parameter((b) => b + ..name = 'i' + ..annotations.add(refer('deprecated'))), + ), + ), + equalsDart(r''' + fib(@deprecated i); + '''), + ); + }); + test('should create a method with a parameter with a type', () { expect( new Method( From d0812a6d61d6052ad60b9c10c911846044fc1d57 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 22 Nov 2017 20:24:38 -0800 Subject: [PATCH 088/271] Infer Method.lamba when `null` is passed. (dart-lang/code_builder#169) * Deprecate the Annotation class. * Use @protected with a field. * Infer Method.lambda when null. * Add another test, and fix a bug :) --- pkgs/code_builder/CHANGELOG.md | 21 ++++++++++++ pkgs/code_builder/example/animal.dart | 4 +-- pkgs/code_builder/lib/src/emitter.dart | 22 ++++++++++--- pkgs/code_builder/lib/src/specs/method.dart | 3 ++ pkgs/code_builder/lib/src/specs/method.g.dart | 1 - pkgs/code_builder/test/specs/method_test.dart | 33 +++++++++++++++++-- 6 files changed, 73 insertions(+), 11 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 59e6e9bf5..d49fdaa18 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -63,6 +63,27 @@ void main() { } ``` +* Added inference support for `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: + +```dart +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)}')); +} +``` + ## 2.2.0 * Imports are prefixed with `_i1` rather than `_1` which satisfies the lint diff --git a/pkgs/code_builder/example/animal.dart b/pkgs/code_builder/example/animal.dart index 15fd3a6c9..a5fc3325f 100644 --- a/pkgs/code_builder/example/animal.dart +++ b/pkgs/code_builder/example/animal.dart @@ -11,8 +11,8 @@ void main() { ..extend = refer('Organism') ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' - ..lambda = true - ..body = const Code('print(\'Yum\')')))); + ..lambda = null + ..body = refer('print').call([literalString('Yum!')]).code))); final emitter = new DartEmitter(); print(new DartFormatter().format('${animal.accept(emitter)}')); } diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index fd8a9b443..692e8365a 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -64,6 +64,18 @@ class DartEmitter extends Object return new DartEmitter(new Allocator.simplePrefixing()); } + static bool _isLambdaBody(Code code) => + code is ToCodeExpression && !code.isStatement; + + /// Whether the provided [method] is considered a lambda method. + static bool _isLambdaMethod(Method method) => + method.lambda ?? _isLambdaBody(method.body); + + /// Whether the provided [constructor] is considered a lambda method. + static bool _isLambdaConstructor(Constructor constructor) => + constructor.lambda ?? + constructor.factory && _isLambdaBody(constructor.body); + @override visitAnnotation(Expression spec, [StringSink output]) { (output ??= new StringBuffer()).write('@'); @@ -112,7 +124,7 @@ class DartEmitter extends Object }); spec.methods.forEach((m) { visitMethod(m, output); - if (m.lambda) { + if (_isLambdaMethod(m)) { output.write(';'); } output.writeln(); @@ -189,7 +201,7 @@ class DartEmitter extends Object visitType(spec.redirect.type, output); output.write(';'); } else if (spec.body != null) { - if (spec.lambda) { + if (_isLambdaConstructor(spec)) { output.write(' => '); spec.body.accept(this, output); output.write(';'); @@ -279,7 +291,7 @@ class DartEmitter extends Object final body = new StringBuffer(); for (final spec in spec.body) { spec.accept(this, body); - if (spec is Method && spec.lambda) { + if (spec is Method && _isLambdaMethod(spec)) { body.write(';'); } } @@ -408,13 +420,13 @@ class DartEmitter extends Object break; } } - if (spec.lambda) { + if (_isLambdaMethod(spec)) { output.write(' => '); } else { output.write(' { '); } spec.body.accept(this, output); - if (!spec.lambda) { + if (!_isLambdaMethod(spec)) { output.write(' } '); } } else { diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 754700df4..7e3483e6a 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -61,6 +61,9 @@ abstract class Method extends Object bool get external; /// Whether this method is a simple lambda expression. + /// + /// May be `null` to be inferred based on the value of [body]. + @nullable bool get lambda; /// Whether this method should be prefixed with `static`. diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index 7914ba2d3..2535c79ed 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -68,7 +68,6 @@ class _$Method extends Method { if (requiredParameters == null) throw new ArgumentError.notNull('requiredParameters'); if (external == null) throw new ArgumentError.notNull('external'); - if (lambda == null) throw new ArgumentError.notNull('lambda'); if (static == null) throw new ArgumentError.notNull('static'); } diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 85a9bdf4c..c75f15238 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -25,7 +25,7 @@ void main() { ..name = 'foo' ..modifier = MethodModifier.async ..lambda = true - ..body = const Code('null')), + ..body = literalNull.code), equalsDart(r''' foo() async => null '''), @@ -38,7 +38,7 @@ void main() { ..name = 'foo' ..modifier = MethodModifier.asyncStar ..lambda = true - ..body = const Code('null')), + ..body = literalNull.code), equalsDart(r''' foo() async* => null '''), @@ -51,13 +51,40 @@ void main() { ..name = 'foo' ..modifier = MethodModifier.syncStar ..lambda = true - ..body = const Code('null')), + ..body = literalNull.code), equalsDart(r''' foo() sync* => null '''), ); }); + test('should create a lambda method implicitly', () { + expect( + new Method((b) => b + ..name = 'returnsTrue' + ..lambda = null + ..returns = refer('bool') + ..body = literalTrue.code), + equalsDart(r''' + bool returnsTrue() => true + '''), + ); + }); + + test('should create a normal method implicitly', () { + expect( + new Method.returnsVoid((b) => b + ..name = 'assignTrue' + ..lambda = null + ..body = refer('topLevelFoo').assign(literalTrue).statement), + equalsDart(r''' + void assignTrue() { + topLevelFoo = true; + } + '''), + ); + }); + test('should create a getter', () { expect( new Method((b) => b From 1e91ac7189de6612a7a62646d87cf245c05f7de5 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 23 Nov 2017 20:23:21 -0800 Subject: [PATCH 089/271] Follow the example/* syntax for the new pub site. (dart-lang/code_builder#170) --- pkgs/code_builder/README.md | 2 + pkgs/code_builder/example/animal.dart | 18 --------- pkgs/code_builder/example/example.dart | 55 ++++++++++++++++++++++++++ pkgs/code_builder/example/scope.dart | 21 ---------- 4 files changed, 57 insertions(+), 39 deletions(-) delete mode 100644 pkgs/code_builder/example/animal.dart create mode 100644 pkgs/code_builder/example/example.dart delete mode 100644 pkgs/code_builder/example/scope.dart diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index b0af2900c..177cab7dd 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -32,6 +32,8 @@ will be on a best-effort basis. `code_builder` has a narrow and user-friendly API. +See the `example` and `test` folders for additional examples. + For example creating a class with a method: ```dart diff --git a/pkgs/code_builder/example/animal.dart b/pkgs/code_builder/example/animal.dart deleted file mode 100644 index a5fc3325f..000000000 --- a/pkgs/code_builder/example/animal.dart +++ /dev/null @@ -1,18 +0,0 @@ -// 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 = null - ..body = refer('print').call([literalString('Yum!')]).code))); - final emitter = new DartEmitter(); - print(new DartFormatter().format('${animal.accept(emitter)}')); -} diff --git a/pkgs/code_builder/example/example.dart b/pkgs/code_builder/example/example.dart new file mode 100644 index 000000000..abf2be030 --- /dev/null +++ b/pkgs/code_builder/example/example.dart @@ -0,0 +1,55 @@ +// 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 _dartfmt = new DartFormatter(); + +void main() { + print('animalClass():\n${'=' * 40}\n${animalClass()}'); + print('scopedLibrary():\n${'=' * 40}\n${scopedLibrary()}'); +} + +/// Outputs: +/// +/// ```dart +/// class Animal extends Organism { +/// void eat() => print('Yum!'); +/// } +/// ``` +String animalClass() { + final animal = new Class((b) => b + ..name = 'Animal' + ..extend = refer('Organism') + ..methods.add(new Method.returnsVoid((b) => b + ..name = 'eat' + ..lambda = null + ..body = refer('print').call([literalString('Yum!')]).code))); + return _dartfmt.format('${animal.accept(new DartEmitter())}'); +} + +/// Outputs: +/// +/// ```dart +/// import 'package:a/a.dart' as _i1; +/// import 'package:b/b.dart' as _i2; +/// +/// _i1.Thing doThing() {} +/// _i2.Other doOther() {} +/// ``` +String scopedLibrary() { + final methods = [ + new Method((b) => b + ..body = const Code('') + ..name = 'doThing' + ..returns = refer('Thing', 'package:a/a.dart')), + new Method((b) => b + ..body = const Code('') + ..name = 'doOther' + ..returns = refer('Other', 'package:b/b.dart')), + ]; + final library = new Library((b) => b.body.addAll(methods)); + return _dartfmt.format('${library.accept(new DartEmitter.scoped())}'); +} diff --git a/pkgs/code_builder/example/scope.dart b/pkgs/code_builder/example/scope.dart deleted file mode 100644 index 8efff2c66..000000000 --- a/pkgs/code_builder/example/scope.dart +++ /dev/null @@ -1,21 +0,0 @@ -// 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 library = new Library((b) => b.body.addAll([ - new Method((b) => b - ..body = const Code('') - ..name = 'doThing' - ..returns = refer('Thing', 'package:a/a.dart')), - new Method((b) => b - ..body = const Code('') - ..name = 'doOther' - ..returns = refer('Other', 'package:b/b.dart')), - ])); - final emitter = new DartEmitter(new Allocator.simplePrefixing()); - print(new DartFormatter().format('${library.accept(emitter)}')); -} From a3cc0b6ef22f69d122e9c431080303d845f59dd5 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sun, 26 Nov 2017 11:52:07 -0800 Subject: [PATCH 090/271] Add `nullSafeProperty` (dart-lang/code_builder#171) --- pkgs/code_builder/CHANGELOG.md | 2 ++ pkgs/code_builder/lib/src/specs/expression.dart | 10 ++++++++++ pkgs/code_builder/test/specs/code/expression_test.dart | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index d49fdaa18..051f06eab 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -84,6 +84,8 @@ void main() { } ``` +* Added `nullSafeProperty` to `Expression` to access properties with `?.` + ## 2.2.0 * Imports are prefixed with `_i1` rather than `_1` which satisfies the lint diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 9bfc9f5aa..9ef750d0d 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -172,6 +172,16 @@ abstract class Expression implements Spec { ); } + /// Returns an expression accessing `?.` on this expression. + Expression nullSafeProperty(String name) { + return new BinaryExpression._( + this, + new LiteralExpression._(name), + '?.', + false, + ); + } + /// Returns an annotation as a result of calling this constructor. @Deprecated('Use "call" instead. Will be removed in 3.0.0.') Expression annotation([ diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 11607af52..00598cb99 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -116,6 +116,10 @@ void main() { expect(refer('foo').property('bar'), equalsDart('foo.bar')); }); + test('should emit invoking a null safe property accessor', () { + expect(refer('foo').nullSafeProperty('bar'), equalsDart('foo?.bar')); + }); + test('should emit invoking a method with a single positional argument', () { expect( refer('foo').call([ From 0adce1918efc7a9e27fab4d1fb1d45aeefcde95a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sun, 26 Nov 2017 12:35:41 -0800 Subject: [PATCH 091/271] Add conditional operator (dart-lang/code_builder#172) --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/specs/expression.dart | 8 ++++++++ pkgs/code_builder/test/specs/code/expression_test.dart | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 051f06eab..9a425b209 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -85,6 +85,7 @@ void main() { ``` * Added `nullSafeProperty` to `Expression` to access properties with `?.` +* Added `conditional` to `Expression` to use the ternary operator `? : ` ## 2.2.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 9ef750d0d..1f6a0bee9 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -76,6 +76,14 @@ abstract class Expression implements Spec { ); } + Expression conditional(Expression whenTrue, Expression whenFalse) { + return new BinaryExpression._( + expression, + new BinaryExpression._(whenTrue, whenFalse, ':'), + '?', + ); + } + /// This expression preceded by `await`. Expression get awaited { return new BinaryExpression._( diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 00598cb99..7f04c73d6 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -358,4 +358,11 @@ void main() { equalsDart('foo is! String'), ); }); + + test('should emit a conditional', () { + expect( + refer('foo').conditional(literal(1), literal(2)), + equalsDart('foo ? 1 : 2'), + ); + }); } From 169b6a429677129df998055640d9350f7119d1dc Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sun, 26 Nov 2017 13:30:03 -0800 Subject: [PATCH 092/271] Accept `Iterable` for positionalArguments (dart-lang/code_builder#173) --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/specs/expression.dart | 14 +++++++------- pkgs/code_builder/lib/src/specs/reference.dart | 16 ++++++++-------- .../lib/src/specs/type_function.dart | 8 ++++---- .../lib/src/specs/type_reference.dart | 16 ++++++++-------- 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 9a425b209..d0a3ac85c 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -86,6 +86,7 @@ void main() { * Added `nullSafeProperty` to `Expression` to access properties with `?.` * Added `conditional` to `Expression` to use the ternary operator `? : ` +* Methods taking `positionalArguments` accept `Iterable` ## 2.2.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 1f6a0bee9..8566ea5df 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -158,13 +158,13 @@ abstract class Expression implements Spec { /// Call this expression as a method. Expression call( - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { return new InvokeExpression._( this, - positionalArguments, + positionalArguments.toList(), namedArguments, typeArguments, ); @@ -193,7 +193,7 @@ abstract class Expression implements Spec { /// Returns an annotation as a result of calling this constructor. @Deprecated('Use "call" instead. Will be removed in 3.0.0.') Expression annotation([ - List positionalArguments, + Iterable positionalArguments, Map namedArguments = const {}, List typeArguments = const [], ]) { @@ -205,7 +205,7 @@ abstract class Expression implements Spec { return new Annotation((b) { b.code = new InvokeExpression._( this, - positionalArguments, + positionalArguments.toList(), namedArguments, typeArguments, ) @@ -217,14 +217,14 @@ abstract class Expression implements Spec { @Deprecated('Use a combination of "property" and "call". Removing in 3.0.0.') Expression annotationNamed( String name, - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { // ignore: deprecated_member_use return new Annotation((b) => b - ..code = new InvokeExpression._( - this, positionalArguments, namedArguments, typeArguments, name) + ..code = new InvokeExpression._(this, positionalArguments.toList(), + namedArguments, typeArguments, name) .code); } diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 9bf296abd..8af1d02bd 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -51,13 +51,13 @@ class Reference extends Expression implements Spec { /// Returns a new instance of this expression. Expression newInstance( - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { return new InvokeExpression.newOf( this, - positionalArguments, + positionalArguments.toList(), namedArguments, typeArguments, null, @@ -67,13 +67,13 @@ class Reference extends Expression implements Spec { /// Returns a new instance of this expression with a named constructor. Expression newInstanceNamed( String name, - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { return new InvokeExpression.newOf( this, - positionalArguments, + positionalArguments.toList(), namedArguments, typeArguments, name, @@ -82,13 +82,13 @@ class Reference extends Expression implements Spec { /// Returns a const instance of this expression. Expression constInstance( - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { return new InvokeExpression.constOf( this, - positionalArguments, + positionalArguments.toList(), namedArguments, typeArguments, null, @@ -98,13 +98,13 @@ class Reference extends Expression implements Spec { /// Returns a const instance of this expression with a named constructor. Expression constInstanceNamed( String name, - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { return new InvokeExpression.constOf( this, - positionalArguments, + positionalArguments.toList(), namedArguments, typeArguments, name, diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index 3abc4db5d..619b6e6c0 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -62,7 +62,7 @@ abstract class FunctionType extends Expression @override Expression newInstance( - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) => @@ -71,7 +71,7 @@ abstract class FunctionType extends Expression @override Expression newInstanceNamed( String name, - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) => @@ -79,7 +79,7 @@ abstract class FunctionType extends Expression @override Expression constInstance( - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) => @@ -88,7 +88,7 @@ abstract class FunctionType extends Expression @override Expression constInstanceNamed( String name, - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) => diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index d09d0930c..cb1415b85 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -58,13 +58,13 @@ abstract class TypeReference extends Expression @override Expression newInstance( - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { return new InvokeExpression.newOf( this, - positionalArguments, + positionalArguments.toList(), namedArguments, typeArguments, null, @@ -74,13 +74,13 @@ abstract class TypeReference extends Expression @override Expression newInstanceNamed( String name, - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { return new InvokeExpression.newOf( this, - positionalArguments, + positionalArguments.toList(), namedArguments, typeArguments, name, @@ -89,13 +89,13 @@ abstract class TypeReference extends Expression @override Expression constInstance( - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { return new InvokeExpression.constOf( this, - positionalArguments, + positionalArguments.toList(), namedArguments, typeArguments, null, @@ -105,13 +105,13 @@ abstract class TypeReference extends Expression @override Expression constInstanceNamed( String name, - List positionalArguments, [ + Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], ]) { return new InvokeExpression.constOf( this, - positionalArguments, + positionalArguments.toList(), namedArguments, typeArguments, name, From 56a1f5a040cb7647f92fe885e992503d72a6bc07 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sun, 26 Nov 2017 16:00:41 -0800 Subject: [PATCH 093/271] Make `Reference.type` return `Reference` (dart-lang/code_builder#175) Fixes dart-lang/code_builder#174 While these changes are technically breaking we expect clients won't be impacted. - Add a test which fails before this change and passes after - Add tests for nested function types since that was untested previously - Make `Reference.type` return `Reference`, update call sites. - Return `this` from the `type` getter. --- pkgs/code_builder/CHANGELOG.md | 3 ++ pkgs/code_builder/lib/src/emitter.dart | 13 ++--- .../code_builder/lib/src/specs/reference.dart | 2 +- .../lib/src/specs/type_function.dart | 3 +- pkgs/code_builder/lib/src/visitors.dart | 2 +- pkgs/code_builder/test/specs/method_test.dart | 47 +++++++++++++++++++ 6 files changed, 60 insertions(+), 10 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index d0a3ac85c..b1e403f20 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -87,6 +87,9 @@ void main() { * Added `nullSafeProperty` to `Expression` to access properties with `?.` * Added `conditional` to `Expression` to use the ternary operator `? : ` * Methods taking `positionalArguments` accept `Iterable` +* **BUG FIX**: Parameters can take a `FunctionType` as a `type`. + `Reference.type` now returns a `Reference`. Note that this change is + technically breaking but should not impacts most clients. ## 2.2.0 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 692e8365a..814df8995 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -100,18 +100,19 @@ class DartEmitter extends Object visitTypeParameters(spec.types.map((r) => r.type), output); if (spec.extend != null) { output.write(' extends '); - visitType(spec.extend.type, output); + spec.extend.type.accept(this, output); } if (spec.mixins.isNotEmpty) { output ..write(' with ') - ..writeAll(spec.mixins.map((m) => visitType(m.type)), ','); + ..writeAll( + spec.mixins.map((m) => m.type.accept(this)), ','); } if (spec.implements.isNotEmpty) { output ..write(' implements ') ..writeAll( - spec.implements.map((m) => visitType(m.type)), ','); + spec.implements.map((m) => m.type.accept(this)), ','); } output.write(' {'); spec.constructors.forEach((c) { @@ -198,7 +199,7 @@ class DartEmitter extends Object } if (spec.redirect != null) { output.write(' = '); - visitType(spec.redirect.type, output); + spec.redirect.type.accept(this, output); output.write(';'); } else if (spec.body != null) { if (_isLambdaConstructor(spec)) { @@ -484,12 +485,12 @@ class DartEmitter extends Object } @override - visitTypeParameters(Iterable specs, [StringSink output]) { + visitTypeParameters(Iterable specs, [StringSink output]) { output ??= new StringBuffer(); if (specs.isNotEmpty) { output ..write('<') - ..writeAll(specs.map(visitType), ',') + ..writeAll(specs.map((s) => s.accept(this)), ',') ..write('>'); } return output; diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 8af1d02bd..3a71f819c 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -123,7 +123,7 @@ class Reference extends Expression implements Spec { .toString(); /// Returns as a [TypeReference], which allows adding generic type parameters. - TypeReference get type => new TypeReference((b) => b + Reference get type => new TypeReference((b) => b ..url = url ..symbol = symbol); } diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index 619b6e6c0..44dac42ed 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -14,7 +14,6 @@ import '../visitors.dart'; import 'code.dart'; import 'expression.dart'; import 'reference.dart'; -import 'type_reference.dart'; part 'type_function.g.dart'; @@ -58,7 +57,7 @@ abstract class FunctionType extends Expression String get symbol => null; @override - TypeReference get type => null; + Reference get type => this; @override Expression newInstance( diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 882fa8774..ab80f8d42 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -45,5 +45,5 @@ abstract class SpecVisitor { T visitType(TypeReference spec, [T context]); - T visitTypeParameters(Iterable specs, [T context]); + T visitTypeParameters(Iterable specs, [T context]); } diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index c75f15238..1ebcb85cb 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -145,6 +145,53 @@ void main() { ); }); + test('should create a method with a nested function type return type', () { + expect( + new Method((b) => b + ..name = 'foo' + ..returns = new FunctionType((b) => b + ..returnType = new FunctionType((b) => b + ..returnType = refer('String') + ..requiredParameters.add(refer('String'))) + ..requiredParameters.addAll([ + refer('int'), + ]))), + equalsDart(r''' + String Function(String) Function(int) foo(); + '''), + ); + }); + + test('should create a method with a function type argument', () { + expect( + new Method((b) => b + ..name = 'foo' + ..requiredParameters.add(new Parameter((b) => b + ..type = new FunctionType((b) => b + ..returnType = refer('String') + ..requiredParameters.add(refer('int'))) + ..name = 'argument'))), + equalsDart(r''' + foo(String Function(int) argument); + ''')); + }); + + test('should create a method with a nested function type argument', () { + expect( + new Method((b) => b + ..name = 'foo' + ..requiredParameters.add(new Parameter((b) => b + ..type = new FunctionType((b) => b + ..returnType = new FunctionType((b) => b + ..returnType = refer('String') + ..requiredParameters.add(refer('String'))) + ..requiredParameters.add(refer('int'))) + ..name = 'argument'))), + equalsDart(r''' + foo(String Function(String) Function(int) argument); + ''')); + }); + test('should create a method with generic types', () { expect( new Method((b) => b From 1bfd8ac2a36b1df1a6ae8e7ed7f39d2d397c39b8 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 27 Nov 2017 13:27:06 -0800 Subject: [PATCH 094/271] Update CHANGELOG.md --- pkgs/code_builder/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index b1e403f20..f06f8c1e5 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.3.0-dev +## 2.3.0 * Using `equalsDart` and expecting `dartfmt` by default is *deprecated*. This requires this package to have a direct dependency on specific versions of From bc294f6ccd07c6cbc9aa93267cf5bd72eb8482dc Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 27 Nov 2017 13:27:55 -0800 Subject: [PATCH 095/271] Update pubspec.yaml --- pkgs/code_builder/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index f9a45ac4b..5b84a70d4 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.3.0-dev +version: 2.3.0 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From 10b10bcbeaf9b0d1dc7e4717d9cf70049011458f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 29 Nov 2017 21:37:25 -0800 Subject: [PATCH 096/271] Add comparison operators (dart-lang/code_builder#177) --- pkgs/code_builder/CHANGELOG.md | 5 ++ .../lib/src/specs/expression.dart | 54 +++++++++++++++++++ pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 42 +++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index f06f8c1e5..20eb42c09 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.4.0 + +* Add `equalTo`, `notEqualTo`, `greaterThan`, `lessThan`, `greateOrEqualTo`, and + `lessOrEqualTo` to `Expression`. + ## 2.3.0 * Using `equalsDart` and expecting `dartfmt` by default is *deprecated*. This diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 8566ea5df..4b82fd666 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -76,6 +76,60 @@ abstract class Expression implements Spec { ); } + /// Returns the result of `this` `==` [other]. + Expression equalTo(Expression other) { + return new BinaryExpression._( + expression, + other, + '==', + ); + } + + /// Returns the result of `this` `!=` [other]. + Expression notEqualTo(Expression other) { + return new BinaryExpression._( + expression, + other, + '!=', + ); + } + + /// Returns the result of `this` `>` [other]. + Expression greaterThan(Expression other) { + return new BinaryExpression._( + expression, + other, + '>', + ); + } + + /// Returns the result of `this` `<` [other]. + Expression lessThan(Expression other) { + return new BinaryExpression._( + expression, + other, + '<', + ); + } + + /// Returns the result of `this` `>=` [other]. + Expression greaterOrEqualTo(Expression other) { + return new BinaryExpression._( + expression, + other, + '>=', + ); + } + + /// Returns the result of `this` `<=` [other]. + Expression lessOrEqualTo(Expression other) { + return new BinaryExpression._( + expression, + other, + '<=', + ); + } + Expression conditional(Expression whenTrue, Expression whenFalse) { return new BinaryExpression._( expression, diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 5b84a70d4..4c0a6ae28 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.3.0 +version: 2.4.0-dev description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 7f04c73d6..920f1a644 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -359,6 +359,48 @@ void main() { ); }); + test('should emit an equality check', () { + expect( + refer('foo').equalTo(literalString('bar')), + equalsDart("foo == 'bar'"), + ); + }); + + test('should emit an inequality check', () { + expect( + refer('foo').notEqualTo(literalString('bar')), + equalsDart("foo != 'bar'"), + ); + }); + + test('should emit an greater than check', () { + expect( + refer('foo').greaterThan(literalString('bar')), + equalsDart("foo > 'bar'"), + ); + }); + + test('should emit an less than check', () { + expect( + refer('foo').lessThan(literalString('bar')), + equalsDart("foo < 'bar'"), + ); + }); + + test('should emit an greater or equals check', () { + expect( + refer('foo').greaterOrEqualTo(literalString('bar')), + equalsDart("foo >= 'bar'"), + ); + }); + + test('should emit an less or equals check', () { + expect( + refer('foo').lessOrEqualTo(literalString('bar')), + equalsDart("foo <= 'bar'"), + ); + }); + test('should emit a conditional', () { expect( refer('foo').conditional(literal(1), literal(2)), From 4ec10fd9e7dfa3a593bb908bd6f8c856f4db69dc Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sun, 10 Dec 2017 18:31:30 -0800 Subject: [PATCH 097/271] Prepare to publish 2.4.0 (dart-lang/code_builder#178) --- pkgs/code_builder/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 4c0a6ae28..890f1004b 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.4.0-dev +version: 2.4.0 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From 3a6ce4b446aa70432e9fef9f04312ddbe1d1306b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 13 Dec 2017 10:42:32 -0800 Subject: [PATCH 098/271] Reorder README - Fixes dart-lang/code_builder#176 (dart-lang/code_builder#179) --- pkgs/code_builder/README.md | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 177cab7dd..8c80d6a40 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -7,27 +7,6 @@ `code_builder` is a fluent Dart API for generating valid Dart source code. -## Contributing - -* Read and help us document common patterns over [at the wiki][wiki]. -* Is there a *bug* in the code? [File an issue][issue]. - -If a feature is missing (the Dart language is always evolving) or you'd like an -easier or better way to do something, consider [opening a pull request][pull]. -You can always [file an issue][issue], but generally speaking feature requests -will be on a best-effort basis. - -> **NOTE**: Due to the evolving Dart SDK the local `dartfmt` must be used to -> format this repository. You can run it simply from the command-line: -> -> ```sh -> $ pub run dart_style:format -w . -> ``` - -[wiki]: https://github.com/dart-lang/code_builder/wiki -[issue]: https://github.com/dart-lang/code_builder/issues -[pull]: https://github.com/dart-lang/code_builder/pulls - ## Usage `code_builder` has a narrow and user-friendly API. @@ -92,3 +71,24 @@ import 'package:b/b.dart' as _i2; _i1.Thing doThing() {} _i2.Other doOther() {} ``` + +## Contributing + +* Read and help us document common patterns over [at the wiki][wiki]. +* Is there a *bug* in the code? [File an issue][issue]. + +If a feature is missing (the Dart language is always evolving) or you'd like an +easier or better way to do something, consider [opening a pull request][pull]. +You can always [file an issue][issue], but generally speaking feature requests +will be on a best-effort basis. + +> **NOTE**: Due to the evolving Dart SDK the local `dartfmt` must be used to +> format this repository. You can run it simply from the command-line: +> +> ```sh +> $ pub run dart_style:format -w . +> ``` + +[wiki]: https://github.com/dart-lang/code_builder/wiki +[issue]: https://github.com/dart-lang/code_builder/issues +[pull]: https://github.com/dart-lang/code_builder/pulls From 5a1b7b5aeab626ad821c1b0737e1b626b9249664 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 13 Dec 2017 12:02:38 -0800 Subject: [PATCH 099/271] Support the latest built_collection and build_runner packages (dart-lang/code_builder#181) --- pkgs/code_builder/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 890f1004b..8f50da99f 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -12,7 +12,7 @@ web: debug: dartdevc dependencies: - built_collection: ^1.0.0 + built_collection: '>=1.0.0 <3.0.0' built_value: '>=2.0.0 <5.0.0' # TODO: Move to dev_dependency in 3.0.0. dart_style: ^1.0.0 @@ -20,7 +20,7 @@ dependencies: meta: ^1.0.5 dev_dependencies: - build_runner: '>=0.4.0 <0.6.0' + build_runner: '>=0.4.0 <0.7.0' built_value_generator: '>=2.0.0 <5.0.0' source_gen: '^0.7.0' test: ^0.12.0 From 1f956489e4b4f14f53c4cd4926fbed2aaa638c0c Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 22 Dec 2017 12:20:41 -0800 Subject: [PATCH 100/271] Remove deprecated code and classes. (dart-lang/code_builder#182) --- pkgs/code_builder/CHANGELOG.md | 9 ++ pkgs/code_builder/README.md | 1 - pkgs/code_builder/example/example.dart | 1 - pkgs/code_builder/lib/code_builder.dart | 6 +- pkgs/code_builder/lib/src/emitter.dart | 14 +-- pkgs/code_builder/lib/src/matchers.dart | 19 +--- .../lib/src/specs/annotation.dart | 56 ----------- .../lib/src/specs/annotation.g.dart | 99 ------------------- .../lib/src/specs/expression.dart | 39 -------- pkgs/code_builder/lib/src/specs/library.dart | 71 ++----------- .../code_builder/lib/src/specs/library.g.dart | 34 +++---- pkgs/code_builder/lib/src/specs/method.dart | 4 +- pkgs/code_builder/lib/src/visitors.dart | 3 - pkgs/code_builder/pubspec.yaml | 5 +- .../code_builder/test/e2e/injection_test.dart | 1 - pkgs/code_builder/test/specs/class_test.dart | 17 ---- .../test/specs/code/expression_test.dart | 4 +- pkgs/code_builder/test/specs/method_test.dart | 25 +---- pkgs/code_builder/tool/src/codegen.dart | 2 +- 19 files changed, 49 insertions(+), 361 deletions(-) delete mode 100644 pkgs/code_builder/lib/src/specs/annotation.dart delete mode 100644 pkgs/code_builder/lib/src/specs/annotation.g.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 20eb42c09..2e0e1296d 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,12 @@ +## 3.0.0-alpha + +* 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`. + ## 2.4.0 * Add `equalTo`, `notEqualTo`, `greaterThan`, `lessThan`, `greateOrEqualTo`, and diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 8c80d6a40..036be72ac 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -25,7 +25,6 @@ void main() { ..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)}')); diff --git a/pkgs/code_builder/example/example.dart b/pkgs/code_builder/example/example.dart index abf2be030..ccb77dfc3 100644 --- a/pkgs/code_builder/example/example.dart +++ b/pkgs/code_builder/example/example.dart @@ -25,7 +25,6 @@ String animalClass() { ..extend = refer('Organism') ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' - ..lambda = null ..body = refer('print').call([literalString('Yum!')]).code))); return _dartfmt.format('${animal.accept(new DartEmitter())}'); } diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 77edcbf1d..2b16c23e7 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -7,8 +7,6 @@ export 'src/base.dart' show lazySpec, Spec; export 'src/emitter.dart' show DartEmitter; export 'src/matchers.dart' show equalsDart, EqualsDart; export 'src/matchers.dart' show equalsDart; -// ignore: deprecated_member_use -export 'src/specs/annotation.dart' show Annotation, AnnotationBuilder; export 'src/specs/class.dart' show Class, ClassBuilder; export 'src/specs/code.dart' show lazyCode, Block, BlockBuilder, Code, StaticCode, ScopedCode; @@ -38,9 +36,7 @@ export 'src/specs/expression.dart' literalTrue, literalFalse; export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; -// TODO: Remove File, FileBuilder in 3.0.0. -// ignore: deprecated_member_use -export 'src/specs/library.dart' show File, FileBuilder, Library, LibraryBuilder; +export 'src/specs/library.dart' show Library, LibraryBuilder; export 'src/specs/method.dart' show Method, diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 814df8995..82284a42d 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -6,7 +6,6 @@ import 'package:meta/meta.dart'; import 'allocator.dart'; import 'base.dart'; -import 'specs/annotation.dart'; import 'specs/class.dart'; import 'specs/code.dart'; import 'specs/constructor.dart'; @@ -79,11 +78,7 @@ class DartEmitter extends Object @override visitAnnotation(Expression spec, [StringSink output]) { (output ??= new StringBuffer()).write('@'); - if (spec is Annotation) { - spec.code.accept(this, output); - } else { - spec.accept(this, output); - } + spec.accept(this, output); output.write(' '); return output; } @@ -281,12 +276,7 @@ class DartEmitter extends Object } @override - visitLibrary(Library spec, [StringSink output]) => visitFile(spec, output); - - @override - // TODO: Remove File in 3.0.0. - // ignore: deprecated_member_use - visitFile(File spec, [StringSink output]) { + visitLibrary(Library spec, [StringSink output]) { output ??= new StringBuffer(); // Process the body first in order to prime the allocators. final body = new StringBuffer(); diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index 49796c3b4..92b654706 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -2,7 +2,6 @@ // 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:dart_style/dart_style.dart'; import 'package:matcher/matcher.dart'; import 'base.dart'; @@ -23,23 +22,13 @@ Matcher equalsDart( /// /// See [EqualsDart.format] to specify the default source code formatter. class EqualsDart extends Matcher { - // TODO: Remove in 3.0.0. - static final _formatter = new DartFormatter(); - /// May override to provide a function to format Dart on [equalsDart]. /// - /// As of `2.x.x`, this defaults to using `dartfmt`, but in an upcoming - /// release (`3.x.x`) it will default to [collapseWhitespace]. This is in - /// order to avoid a dependency on specific versions of `dartfmt` and the - /// `analyzer` package. - /// - /// To future proof, see an example in code_builder's `test/common.dart`. + /// By default, uses [collapseWhitespace], but it is recommended to instead + /// use `dart_style` (dartfmt) where possible. See `test/common.dart` for an + /// example. static String Function(String) format = (String source) { - try { - return _formatter.format(source); - } on FormatException catch (_) { - return _formatter.formatStatement(source); - } + return collapseWhitespace(source); }; static String _format(String source) { diff --git a/pkgs/code_builder/lib/src/specs/annotation.dart b/pkgs/code_builder/lib/src/specs/annotation.dart deleted file mode 100644 index 1bf330bc0..000000000 --- a/pkgs/code_builder/lib/src/specs/annotation.dart +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -library code_builder.src.specs.annotation; - -import 'package:built_value/built_value.dart'; -import 'package:meta/meta.dart'; - -import '../base.dart'; -import '../visitors.dart'; -import 'code.dart'; -import 'expression.dart'; - -part 'annotation.g.dart'; - -@Deprecated('Use an Expression node instead. Will be removed in 3.0.0.') -@immutable -abstract class Annotation extends Expression - implements Built, Spec { - factory Annotation([void updates(AnnotationBuilder b)]) = _$Annotation; - - Annotation._(); - - /// Part after the `@` in annotation. - @override - Code get code => codeForAnnotation; - - /// Use [code] instead. - /// - /// This property exists in order to keep compatibility with having a concrete - /// [Annotation] class, but also allow migrating to using [Expression] instead - /// to add annotations. - @protected - Code get codeForAnnotation; - - @override - R accept(SpecVisitor visitor, [R context]) { - return visitor.visitAnnotation(this, context); - } -} - -abstract class AnnotationBuilder - // ignore: deprecated_member_use - implements - Builder { - factory AnnotationBuilder() = _$AnnotationBuilder; - - AnnotationBuilder._(); - - Code get code => codeForAnnotation; - set code(Code code) => codeForAnnotation = code; - - @protected - Code codeForAnnotation; -} diff --git a/pkgs/code_builder/lib/src/specs/annotation.g.dart b/pkgs/code_builder/lib/src/specs/annotation.g.dart deleted file mode 100644 index 63689232f..000000000 --- a/pkgs/code_builder/lib/src/specs/annotation.g.dart +++ /dev/null @@ -1,99 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of code_builder.src.specs.annotation; - -// ************************************************************************** -// Generator: BuiltValueGenerator -// ************************************************************************** - -// ignore_for_file: always_put_control_body_on_new_line -// ignore_for_file: annotate_overrides -// ignore_for_file: avoid_annotating_with_dynamic -// ignore_for_file: avoid_returning_this -// ignore_for_file: omit_local_variable_types -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - -class _$Annotation extends Annotation { - @override - final Code codeForAnnotation; - - factory _$Annotation([void updates(AnnotationBuilder b)]) => - (new AnnotationBuilder()..update(updates)).build() as _$Annotation; - - _$Annotation._({this.codeForAnnotation}) : super._() { - if (codeForAnnotation == null) - throw new ArgumentError.notNull('codeForAnnotation'); - } - - @override - Annotation rebuild(void updates(AnnotationBuilder b)) => - (toBuilder()..update(updates)).build(); - - @override - _$AnnotationBuilder toBuilder() => new _$AnnotationBuilder()..replace(this); - - @override - bool operator ==(dynamic other) { - if (identical(other, this)) return true; - if (other is! Annotation) return false; - return codeForAnnotation == other.codeForAnnotation; - } - - @override - int get hashCode { - return $jf($jc(0, codeForAnnotation.hashCode)); - } - - @override - String toString() { - return (newBuiltValueToStringHelper('Annotation') - ..add('codeForAnnotation', codeForAnnotation)) - .toString(); - } -} - -class _$AnnotationBuilder extends AnnotationBuilder { - _$Annotation _$v; - - @override - Code get codeForAnnotation { - _$this; - return super.codeForAnnotation; - } - - @override - set codeForAnnotation(Code codeForAnnotation) { - _$this; - super.codeForAnnotation = codeForAnnotation; - } - - _$AnnotationBuilder() : super._(); - - AnnotationBuilder get _$this { - if (_$v != null) { - super.codeForAnnotation = _$v.codeForAnnotation; - _$v = null; - } - return this; - } - - @override - void replace(Annotation other) { - if (other == null) throw new ArgumentError.notNull('other'); - _$v = other as _$Annotation; - } - - @override - void update(void updates(AnnotationBuilder b)) { - if (updates != null) updates(this); - } - - @override - _$Annotation build() { - final _$result = - _$v ?? new _$Annotation._(codeForAnnotation: codeForAnnotation); - replace(_$result); - return _$result; - } -} diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 4b82fd666..50600a49f 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -9,7 +9,6 @@ import 'package:meta/meta.dart'; import '../base.dart'; import '../emitter.dart'; import '../visitors.dart'; -import 'annotation.dart'; import 'code.dart'; import 'method.dart'; import 'reference.dart'; @@ -244,44 +243,6 @@ abstract class Expression implements Spec { ); } - /// Returns an annotation as a result of calling this constructor. - @Deprecated('Use "call" instead. Will be removed in 3.0.0.') - Expression annotation([ - Iterable positionalArguments, - Map namedArguments = const {}, - List typeArguments = const [], - ]) { - if (positionalArguments == null) { - return new Annotation((b) { - b.code = code; - }); - } - return new Annotation((b) { - b.code = new InvokeExpression._( - this, - positionalArguments.toList(), - namedArguments, - typeArguments, - ) - .code; - }); - } - - /// Returns an annotation as a result of calling a named constructor. - @Deprecated('Use a combination of "property" and "call". Removing in 3.0.0.') - Expression annotationNamed( - String name, - Iterable positionalArguments, [ - Map namedArguments = const {}, - List typeArguments = const [], - ]) { - // ignore: deprecated_member_use - return new Annotation((b) => b - ..code = new InvokeExpression._(this, positionalArguments.toList(), - namedArguments, typeArguments, name) - .code); - } - /// This expression preceded by `return`. Expression get returned { return new BinaryExpression._( diff --git a/pkgs/code_builder/lib/src/specs/library.dart b/pkgs/code_builder/lib/src/specs/library.dart index ae63180ec..180bc8978 100644 --- a/pkgs/code_builder/lib/src/specs/library.dart +++ b/pkgs/code_builder/lib/src/specs/library.dart @@ -14,10 +14,10 @@ import 'directive.dart'; part 'library.g.dart'; -@Deprecated('Replace with "Library" by 3.0.0') -abstract class File implements Built, Spec { - factory File([void updates(FileBuilder b)]) = _$File; - File._(); +@immutable +abstract class Library implements Built, Spec { + factory Library([void updates(LibraryBuilder b)]) = _$Library; + Library._(); BuiltList get directives; BuiltList get body; @@ -27,68 +27,13 @@ abstract class File implements Built, Spec { SpecVisitor visitor, [ R context, ]) => - visitor.visitFile(this, context); + visitor.visitLibrary(this, context); } -@Deprecated('Replace with "LibraryBuilder" by 3.0.0') -abstract class FileBuilder implements Builder { - factory FileBuilder() = _$FileBuilder; - FileBuilder._(); - - ListBuilder directives = new ListBuilder(); - ListBuilder body = new ListBuilder(); -} - -@immutable -// TODO: Remove File in 3.0.0. -// ignore: deprecated_member_use -class Library extends _$File implements Spec { - factory Library([void updates(LibraryBuilder b)]) { - return (new LibraryBuilder()..update(updates)).build(); - } - - Library._({ - BuiltList directives, - BuiltList body, - }) - : super._(directives: directives, body: body); -} +abstract class LibraryBuilder implements Builder { + factory LibraryBuilder() = _$LibraryBuilder; + LibraryBuilder._(); -// TODO: Remove File in 3.0.0. -// -// This implementation is imperfect (not identical to the code emitted by -// the built_value package but seems to the only way to adhere to the -// inheritance chain without breaking the code generator). -// -// May be changed as a result of -// https://github.com/google/built_value.dart/issues/257. -// -// ignore: deprecated_member_use -class LibraryBuilder implements FileBuilder { - @override ListBuilder body = new ListBuilder(); - - @override ListBuilder directives = new ListBuilder(); - - @override - Library build() { - return new Library._(directives: directives.build(), body: body.build()); - } - - @override - void replace(covariant Library other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } - body = other.body.toBuilder(); - directives = other.directives.toBuilder(); - } - - @override - void update(void updates(LibraryBuilder builder)) { - if (updates != null) { - updates(this); - } - } } diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index bbe5c77b4..1fe24aa55 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -14,31 +14,31 @@ part of code_builder.src.specs.library; // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first -class _$File extends File { +class _$Library extends Library { @override final BuiltList directives; @override final BuiltList body; - factory _$File([void updates(FileBuilder b)]) => - (new FileBuilder()..update(updates)).build() as _$File; + factory _$Library([void updates(LibraryBuilder b)]) => + (new LibraryBuilder()..update(updates)).build() as _$Library; - _$File._({this.directives, this.body}) : super._() { + _$Library._({this.directives, this.body}) : super._() { if (directives == null) throw new ArgumentError.notNull('directives'); if (body == null) throw new ArgumentError.notNull('body'); } @override - File rebuild(void updates(FileBuilder b)) => + Library rebuild(void updates(LibraryBuilder b)) => (toBuilder()..update(updates)).build(); @override - _$FileBuilder toBuilder() => new _$FileBuilder()..replace(this); + _$LibraryBuilder toBuilder() => new _$LibraryBuilder()..replace(this); @override bool operator ==(dynamic other) { if (identical(other, this)) return true; - if (other is! File) return false; + if (other is! Library) return false; return directives == other.directives && body == other.body; } @@ -49,15 +49,15 @@ class _$File extends File { @override String toString() { - return (newBuiltValueToStringHelper('File') + return (newBuiltValueToStringHelper('Library') ..add('directives', directives) ..add('body', body)) .toString(); } } -class _$FileBuilder extends FileBuilder { - _$File _$v; +class _$LibraryBuilder extends LibraryBuilder { + _$Library _$v; @override ListBuilder get directives { @@ -83,9 +83,9 @@ class _$FileBuilder extends FileBuilder { super.body = body; } - _$FileBuilder() : super._(); + _$LibraryBuilder() : super._(); - FileBuilder get _$this { + LibraryBuilder get _$this { if (_$v != null) { super.directives = _$v.directives?.toBuilder(); super.body = _$v.body?.toBuilder(); @@ -95,20 +95,20 @@ class _$FileBuilder extends FileBuilder { } @override - void replace(File other) { + void replace(Library other) { if (other == null) throw new ArgumentError.notNull('other'); - _$v = other as _$File; + _$v = other as _$Library; } @override - void update(void updates(FileBuilder b)) { + void update(void updates(LibraryBuilder b)) { if (updates != null) updates(this); } @override - _$File build() { + _$Library build() { final _$result = _$v ?? - new _$File._(directives: directives?.build(), body: body?.build()); + new _$Library._(directives: directives?.build(), body: body?.build()); replace(_$result); return _$result; } diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 7e3483e6a..31180a29a 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -128,7 +128,9 @@ abstract class MethodBuilder extends Object bool external = false; /// Whether this method is a simple lambda expression. - bool lambda = false; + /// + /// If not specified this is inferred from the [body]. + bool lambda; /// Whether this method should be prefixed with `static`. /// diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index ab80f8d42..62b47bc75 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -30,9 +30,6 @@ abstract class SpecVisitor { T visitField(Field spec, [T context]); - @Deprecated('Replace with visitLibrary by 3.0.0') - T visitFile(File spec, [T context]); - T visitLibrary(Library spec, [T context]); T visitFunctionType(FunctionType spec, [T context]); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 8f50da99f..8766be219 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 2.4.0 +version: 3.0.0-alpha description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -14,14 +14,13 @@ web: dependencies: built_collection: '>=1.0.0 <3.0.0' built_value: '>=2.0.0 <5.0.0' - # TODO: Move to dev_dependency in 3.0.0. - dart_style: ^1.0.0 matcher: ^0.12.0 meta: ^1.0.5 dev_dependencies: build_runner: '>=0.4.0 <0.7.0' built_value_generator: '>=2.0.0 <5.0.0' + dart_style: ^1.0.0 source_gen: '^0.7.0' test: ^0.12.0 diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index 0858e5374..9b45bbf61 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -33,7 +33,6 @@ void main() { refer('_module').property('get1').call([]), refer('_module').property('get2').call([]), ]).code - ..lambda = true ..returns = $Thing ..annotations.add(refer('override')))); diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 3ae497443..49f643931 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -179,23 +179,6 @@ void main() { ); }); - test('should create a class with an annotated constructor [deprecated]', () { - expect( - new Class((b) => b - ..name = 'Foo' - ..constructors.add(new Constructor((b) => b - ..annotations.add( - new Annotation((b) => b..code = const Code('deprecated')), - )))), - equalsDart(r''' - class Foo { - @deprecated - Foo(); - } - '''), - ); - }); - test('should create a class with a annotated constructor', () { expect( new Class((b) => b diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 920f1a644..d64cb6454 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -252,9 +252,7 @@ void main() { expect( refer('map').property('putIfAbsent').call([ literalString('foo'), - new Method((b) => b - ..lambda = true - ..body = literalTrue.code).closure, + new Method((b) => b..body = literalTrue.code).closure, ]), equalsDart("map.putIfAbsent('foo', () => true)"), ); diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 1ebcb85cb..9e87018c0 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -24,7 +24,6 @@ void main() { new Method((b) => b ..name = 'foo' ..modifier = MethodModifier.async - ..lambda = true ..body = literalNull.code), equalsDart(r''' foo() async => null @@ -37,7 +36,6 @@ void main() { new Method((b) => b ..name = 'foo' ..modifier = MethodModifier.asyncStar - ..lambda = true ..body = literalNull.code), equalsDart(r''' foo() async* => null @@ -50,7 +48,6 @@ void main() { new Method((b) => b ..name = 'foo' ..modifier = MethodModifier.syncStar - ..lambda = true ..body = literalNull.code), equalsDart(r''' foo() sync* => null @@ -62,7 +59,6 @@ void main() { expect( new Method((b) => b ..name = 'returnsTrue' - ..lambda = null ..returns = refer('bool') ..body = literalTrue.code), equalsDart(r''' @@ -75,7 +71,6 @@ void main() { expect( new Method.returnsVoid((b) => b ..name = 'assignTrue' - ..lambda = null ..body = refer('topLevelFoo').assign(literalTrue).statement), equalsDart(r''' void assignTrue() { @@ -227,7 +222,7 @@ void main() { ); }); - test('should create a lambda method', () { + test('should create a lambda method (explicitly)', () { expect( new Method((b) => b ..name = 'foo' @@ -270,24 +265,6 @@ void main() { ); }); - test('should create a method with an annotated parameter [deprecated]', () { - expect( - new Method( - (b) => b - ..name = 'fib' - ..requiredParameters.add( - new Parameter((b) => b - ..name = 'i' - ..annotations.add( - new Annotation((a) => a..code = const Code('deprecated')))), - ), - ), - equalsDart(r''' - fib(@deprecated i); - '''), - ); - }); - test('should create a method with an annotated parameter', () { expect( new Method( diff --git a/pkgs/code_builder/tool/src/codegen.dart b/pkgs/code_builder/tool/src/codegen.dart index 80edcf824..8d8bbd2f1 100644 --- a/pkgs/code_builder/tool/src/codegen.dart +++ b/pkgs/code_builder/tool/src/codegen.dart @@ -10,7 +10,7 @@ import 'package:source_gen/source_gen.dart'; BuildAction buildAction() { return new BuildAction( new PartBuilder([ - new BuiltValueGenerator(), + const BuiltValueGenerator(), ]), 'code_builder', inputs: const ['lib/src/specs/**.dart'], From dd3b4db5f5b88836dadbf72eca9932f1dae716f8 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 22 Dec 2017 14:24:42 -0800 Subject: [PATCH 101/271] Support lambda inference for constructors. (dart-lang/code_builder#183) --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/lib/src/specs/constructor.dart | 3 ++- .../code_builder/lib/src/specs/constructor.g.dart | 1 - pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/class_test.dart | 15 +++++++++++++++ 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 2e0e1296d..f7284ccff 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.0-alpha+1 + +* Also infer `Constructor.lambda` for `factory` constructors. + ## 3.0.0-alpha * Using `equalsDart` no longer formats automatically with `dartfmt`. diff --git a/pkgs/code_builder/lib/src/specs/constructor.dart b/pkgs/code_builder/lib/src/specs/constructor.dart index 590ecfb64..3bf9b569b 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.dart @@ -54,6 +54,7 @@ abstract class Constructor extends Object bool get factory; /// Whether this constructor is a simple lambda expression. + @nullable bool get lambda; /// Name of the constructor - optional. @@ -100,7 +101,7 @@ abstract class ConstructorBuilder extends Object bool factory = false; /// Whether this constructor is a simple lambda expression. - bool lambda = false; + bool lambda; /// Name of the constructor - optional. String name; diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index fa60d56d9..9ec7d4413 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -67,7 +67,6 @@ class _$Constructor extends Constructor { if (external == null) throw new ArgumentError.notNull('external'); if (constant == null) throw new ArgumentError.notNull('constant'); if (factory == null) throw new ArgumentError.notNull('factory'); - if (lambda == null) throw new ArgumentError.notNull('lambda'); } @override diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 8766be219..b52dbdc13 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.0.0-alpha +version: 3.0.0-alpha+1 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 49f643931..872a5b931 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -264,6 +264,21 @@ void main() { ); }); + test('should create a class with an implicit factory lambda constructor', () { + expect( + new Class((b) => b + ..name = 'Foo' + ..constructors.add(new Constructor((b) => b + ..factory = true + ..body = refer('_Foo').newInstance([]).code))), + equalsDart(r''' + class Foo { + factory Foo() => new _Foo(); + } + '''), + ); + }); + test('should create a class with a constructor with a body', () { expect( new Class((b) => b From 9c68412a5e13fe13595ab279d60d7a5b8fb8b8ce Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 8 Jan 2018 15:07:11 -0800 Subject: [PATCH 102/271] Support latest built_collection (dart-lang/code_builder#185) Fixes https://github.com/dart-lang/code_builder/issues/184 --- pkgs/code_builder/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index b52dbdc13..e01712e2c 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -12,7 +12,7 @@ web: debug: dartdevc dependencies: - built_collection: '>=1.0.0 <3.0.0' + built_collection: '>=1.0.0 <4.0.0' built_value: '>=2.0.0 <5.0.0' matcher: ^0.12.0 meta: ^1.0.5 From a11440e9db789ea22c4d75861d65f5e8facf0474 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 9 Jan 2018 14:05:54 -0800 Subject: [PATCH 103/271] Prepare to publish. (dart-lang/code_builder#186) --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index f7284ccff..8308672be 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.0.0-alpha+1 +## 3.0.0 * Also infer `Constructor.lambda` for `factory` constructors. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index e01712e2c..ca0ca7fef 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.0.0-alpha+1 +version: 3.0.0 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From 54c5168abd20d3922326b3000527545956ed6d21 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 10 Jan 2018 16:16:15 -0800 Subject: [PATCH 104/271] Export literalNum. (dart-lang/code_builder#189) --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/lib/code_builder.dart | 1 + pkgs/code_builder/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 8308672be..531be6624 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.1 + +* Export the `literalNum` function. + ## 3.0.0 * Also infer `Constructor.lambda` for `factory` constructors. diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 2b16c23e7..79685a7c8 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -27,6 +27,7 @@ export 'src/specs/expression.dart' LiteralListExpression, literal, literalNull, + literalNum, literalBool, literalList, literalConstList, diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index ca0ca7fef..10c3e3585 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.0.0 +version: 3.0.1 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From 2ad93c8847c7a941cac2ccee428da643f1df3151 Mon Sep 17 00:00:00 2001 From: David Morgan Date: Mon, 29 Jan 2018 18:20:47 +0100 Subject: [PATCH 105/271] Upgrade to built_value 5.1.0. (dart-lang/code_builder#192) --- pkgs/code_builder/CHANGELOG.md | 4 + pkgs/code_builder/lib/src/specs/class.g.dart | 78 ++++++++---- pkgs/code_builder/lib/src/specs/code.g.dart | 18 ++- .../lib/src/specs/constructor.g.dart | 70 +++++++---- .../lib/src/specs/directive.g.dart | 11 +- pkgs/code_builder/lib/src/specs/field.g.dart | 45 ++++--- .../code_builder/lib/src/specs/library.g.dart | 24 +++- pkgs/code_builder/lib/src/specs/method.g.dart | 118 ++++++++++++------ .../lib/src/specs/type_function.g.dart | 42 +++++-- .../lib/src/specs/type_reference.g.dart | 25 +++- pkgs/code_builder/pubspec.yaml | 6 +- 11 files changed, 314 insertions(+), 127 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 531be6624..195e96bfc 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.2 + +* Upgrade to `built_value` 5.1.0. + ## 3.0.1 * Export the `literalNum` function. diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index 4baa92c5f..7ab65d15b 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -54,16 +54,20 @@ class _$Class extends Class { this.fields, this.name}) : super._() { - if (abstract == null) throw new ArgumentError.notNull('abstract'); - if (annotations == null) throw new ArgumentError.notNull('annotations'); - if (docs == null) throw new ArgumentError.notNull('docs'); - if (implements == null) throw new ArgumentError.notNull('implements'); - if (mixins == null) throw new ArgumentError.notNull('mixins'); - if (types == null) throw new ArgumentError.notNull('types'); - if (constructors == null) throw new ArgumentError.notNull('constructors'); - if (methods == null) throw new ArgumentError.notNull('methods'); - if (fields == null) throw new ArgumentError.notNull('fields'); - if (name == null) throw new ArgumentError.notNull('name'); + if (abstract == null) + throw new BuiltValueNullFieldError('Class', 'abstract'); + if (annotations == null) + throw new BuiltValueNullFieldError('Class', 'annotations'); + if (docs == null) throw new BuiltValueNullFieldError('Class', 'docs'); + if (implements == null) + throw new BuiltValueNullFieldError('Class', 'implements'); + if (mixins == null) throw new BuiltValueNullFieldError('Class', 'mixins'); + if (types == null) throw new BuiltValueNullFieldError('Class', 'types'); + if (constructors == null) + throw new BuiltValueNullFieldError('Class', 'constructors'); + if (methods == null) throw new BuiltValueNullFieldError('Class', 'methods'); + if (fields == null) throw new BuiltValueNullFieldError('Class', 'fields'); + if (name == null) throw new BuiltValueNullFieldError('Class', 'name'); } @override @@ -300,19 +304,47 @@ class _$ClassBuilder extends ClassBuilder { @override _$Class build() { - final _$result = _$v ?? - new _$Class._( - abstract: abstract, - annotations: annotations?.build(), - docs: docs?.build(), - extend: extend, - implements: implements?.build(), - mixins: mixins?.build(), - types: types?.build(), - constructors: constructors?.build(), - methods: methods?.build(), - fields: fields?.build(), - name: name); + _$Class _$result; + try { + _$result = _$v ?? + new _$Class._( + abstract: abstract, + annotations: annotations.build(), + docs: docs.build(), + extend: extend, + implements: implements.build(), + mixins: mixins.build(), + types: types.build(), + constructors: constructors.build(), + methods: methods.build(), + fields: fields.build(), + name: name); + } catch (_) { + String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + + _$failedField = 'implements'; + implements.build(); + _$failedField = 'mixins'; + mixins.build(); + _$failedField = 'types'; + types.build(); + _$failedField = 'constructors'; + constructors.build(); + _$failedField = 'methods'; + methods.build(); + _$failedField = 'fields'; + fields.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'Class', _$failedField, e.toString()); + } + rethrow; + } replace(_$result); return _$result; } diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart index b012536a3..9952e7013 100644 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -22,7 +22,8 @@ class _$Block extends Block { (new BlockBuilder()..update(updates)).build() as _$Block; _$Block._({this.statements}) : super._() { - if (statements == null) throw new ArgumentError.notNull('statements'); + if (statements == null) + throw new BuiltValueNullFieldError('Block', 'statements'); } @override @@ -89,7 +90,20 @@ class _$BlockBuilder extends BlockBuilder { @override _$Block build() { - final _$result = _$v ?? new _$Block._(statements: statements?.build()); + _$Block _$result; + try { + _$result = _$v ?? new _$Block._(statements: statements.build()); + } catch (_) { + String _$failedField; + try { + _$failedField = 'statements'; + statements.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'Block', _$failedField, e.toString()); + } + rethrow; + } replace(_$result); return _$result; } diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index 9ec7d4413..d83818843 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -57,16 +57,21 @@ class _$Constructor extends Constructor { this.name, this.redirect}) : super._() { - if (annotations == null) throw new ArgumentError.notNull('annotations'); - if (docs == null) throw new ArgumentError.notNull('docs'); + if (annotations == null) + throw new BuiltValueNullFieldError('Constructor', 'annotations'); + if (docs == null) throw new BuiltValueNullFieldError('Constructor', 'docs'); if (optionalParameters == null) - throw new ArgumentError.notNull('optionalParameters'); + throw new BuiltValueNullFieldError('Constructor', 'optionalParameters'); if (requiredParameters == null) - throw new ArgumentError.notNull('requiredParameters'); - if (initializers == null) throw new ArgumentError.notNull('initializers'); - if (external == null) throw new ArgumentError.notNull('external'); - if (constant == null) throw new ArgumentError.notNull('constant'); - if (factory == null) throw new ArgumentError.notNull('factory'); + throw new BuiltValueNullFieldError('Constructor', 'requiredParameters'); + if (initializers == null) + throw new BuiltValueNullFieldError('Constructor', 'initializers'); + if (external == null) + throw new BuiltValueNullFieldError('Constructor', 'external'); + if (constant == null) + throw new BuiltValueNullFieldError('Constructor', 'constant'); + if (factory == null) + throw new BuiltValueNullFieldError('Constructor', 'factory'); } @override @@ -320,20 +325,41 @@ class _$ConstructorBuilder extends ConstructorBuilder { @override _$Constructor build() { - final _$result = _$v ?? - new _$Constructor._( - annotations: annotations?.build(), - docs: docs?.build(), - optionalParameters: optionalParameters?.build(), - requiredParameters: requiredParameters?.build(), - initializers: initializers?.build(), - body: body, - external: external, - constant: constant, - factory: factory, - lambda: lambda, - name: name, - redirect: redirect); + _$Constructor _$result; + try { + _$result = _$v ?? + new _$Constructor._( + annotations: annotations.build(), + docs: docs.build(), + optionalParameters: optionalParameters.build(), + requiredParameters: requiredParameters.build(), + initializers: initializers.build(), + body: body, + external: external, + constant: constant, + factory: factory, + lambda: lambda, + name: name, + redirect: redirect); + } catch (_) { + String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + _$failedField = 'optionalParameters'; + optionalParameters.build(); + _$failedField = 'requiredParameters'; + requiredParameters.build(); + _$failedField = 'initializers'; + initializers.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'Constructor', _$failedField, e.toString()); + } + rethrow; + } replace(_$result); return _$result; } diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart index 2a59c6630..336d5ef9c 100644 --- a/pkgs/code_builder/lib/src/specs/directive.g.dart +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -34,11 +34,12 @@ class _$Directive extends Directive { _$Directive._( {this.as, this.url, this.type, this.show, this.hide, this.deferred}) : super._() { - if (url == null) throw new ArgumentError.notNull('url'); - if (type == null) throw new ArgumentError.notNull('type'); - if (show == null) throw new ArgumentError.notNull('show'); - if (hide == null) throw new ArgumentError.notNull('hide'); - if (deferred == null) throw new ArgumentError.notNull('deferred'); + if (url == null) throw new BuiltValueNullFieldError('Directive', 'url'); + if (type == null) throw new BuiltValueNullFieldError('Directive', 'type'); + if (show == null) throw new BuiltValueNullFieldError('Directive', 'show'); + if (hide == null) throw new BuiltValueNullFieldError('Directive', 'hide'); + if (deferred == null) + throw new BuiltValueNullFieldError('Directive', 'deferred'); } @override diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 75d88be12..d78fcdd46 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -42,11 +42,13 @@ class _$Field extends Field { this.type, this.modifier}) : super._() { - if (annotations == null) throw new ArgumentError.notNull('annotations'); - if (docs == null) throw new ArgumentError.notNull('docs'); - if (static == null) throw new ArgumentError.notNull('static'); - if (name == null) throw new ArgumentError.notNull('name'); - if (modifier == null) throw new ArgumentError.notNull('modifier'); + if (annotations == null) + throw new BuiltValueNullFieldError('Field', 'annotations'); + if (docs == null) throw new BuiltValueNullFieldError('Field', 'docs'); + if (static == null) throw new BuiltValueNullFieldError('Field', 'static'); + if (name == null) throw new BuiltValueNullFieldError('Field', 'name'); + if (modifier == null) + throw new BuiltValueNullFieldError('Field', 'modifier'); } @override @@ -213,15 +215,30 @@ class _$FieldBuilder extends FieldBuilder { @override _$Field build() { - final _$result = _$v ?? - new _$Field._( - annotations: annotations?.build(), - docs: docs?.build(), - assignment: assignment, - static: static, - name: name, - type: type, - modifier: modifier); + _$Field _$result; + try { + _$result = _$v ?? + new _$Field._( + annotations: annotations.build(), + docs: docs.build(), + assignment: assignment, + static: static, + name: name, + type: type, + modifier: modifier); + } catch (_) { + String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'Field', _$failedField, e.toString()); + } + rethrow; + } replace(_$result); return _$result; } diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index 1fe24aa55..9d8eb279b 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -24,8 +24,9 @@ class _$Library extends Library { (new LibraryBuilder()..update(updates)).build() as _$Library; _$Library._({this.directives, this.body}) : super._() { - if (directives == null) throw new ArgumentError.notNull('directives'); - if (body == null) throw new ArgumentError.notNull('body'); + if (directives == null) + throw new BuiltValueNullFieldError('Library', 'directives'); + if (body == null) throw new BuiltValueNullFieldError('Library', 'body'); } @override @@ -107,8 +108,23 @@ class _$LibraryBuilder extends LibraryBuilder { @override _$Library build() { - final _$result = _$v ?? - new _$Library._(directives: directives?.build(), body: body?.build()); + _$Library _$result; + try { + _$result = _$v ?? + new _$Library._(directives: directives.build(), body: body.build()); + } catch (_) { + String _$failedField; + try { + _$failedField = 'directives'; + directives.build(); + _$failedField = 'body'; + body.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'Library', _$failedField, e.toString()); + } + rethrow; + } replace(_$result); return _$result; } diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index 2535c79ed..470b7b2d0 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -60,15 +60,17 @@ class _$Method extends Method { this.modifier, this.returns}) : super._() { - if (annotations == null) throw new ArgumentError.notNull('annotations'); - if (docs == null) throw new ArgumentError.notNull('docs'); - if (types == null) throw new ArgumentError.notNull('types'); + if (annotations == null) + throw new BuiltValueNullFieldError('Method', 'annotations'); + if (docs == null) throw new BuiltValueNullFieldError('Method', 'docs'); + if (types == null) throw new BuiltValueNullFieldError('Method', 'types'); if (optionalParameters == null) - throw new ArgumentError.notNull('optionalParameters'); + throw new BuiltValueNullFieldError('Method', 'optionalParameters'); if (requiredParameters == null) - throw new ArgumentError.notNull('requiredParameters'); - if (external == null) throw new ArgumentError.notNull('external'); - if (static == null) throw new ArgumentError.notNull('static'); + throw new BuiltValueNullFieldError('Method', 'requiredParameters'); + if (external == null) + throw new BuiltValueNullFieldError('Method', 'external'); + if (static == null) throw new BuiltValueNullFieldError('Method', 'static'); } @override @@ -341,21 +343,42 @@ class _$MethodBuilder extends MethodBuilder { @override _$Method build() { - final _$result = _$v ?? - new _$Method._( - annotations: annotations?.build(), - docs: docs?.build(), - types: types?.build(), - optionalParameters: optionalParameters?.build(), - requiredParameters: requiredParameters?.build(), - body: body, - external: external, - lambda: lambda, - static: static, - name: name, - type: type, - modifier: modifier, - returns: returns); + _$Method _$result; + try { + _$result = _$v ?? + new _$Method._( + annotations: annotations.build(), + docs: docs.build(), + types: types.build(), + optionalParameters: optionalParameters.build(), + requiredParameters: requiredParameters.build(), + body: body, + external: external, + lambda: lambda, + static: static, + name: name, + type: type, + modifier: modifier, + returns: returns); + } catch (_) { + String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + _$failedField = 'types'; + types.build(); + _$failedField = 'optionalParameters'; + optionalParameters.build(); + _$failedField = 'requiredParameters'; + requiredParameters.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'Method', _$failedField, e.toString()); + } + rethrow; + } replace(_$result); return _$result; } @@ -392,12 +415,14 @@ class _$Parameter extends Parameter { this.types, this.type}) : super._() { - if (name == null) throw new ArgumentError.notNull('name'); - if (named == null) throw new ArgumentError.notNull('named'); - if (toThis == null) throw new ArgumentError.notNull('toThis'); - if (annotations == null) throw new ArgumentError.notNull('annotations'); - if (docs == null) throw new ArgumentError.notNull('docs'); - if (types == null) throw new ArgumentError.notNull('types'); + if (name == null) throw new BuiltValueNullFieldError('Parameter', 'name'); + if (named == null) throw new BuiltValueNullFieldError('Parameter', 'named'); + if (toThis == null) + throw new BuiltValueNullFieldError('Parameter', 'toThis'); + if (annotations == null) + throw new BuiltValueNullFieldError('Parameter', 'annotations'); + if (docs == null) throw new BuiltValueNullFieldError('Parameter', 'docs'); + if (types == null) throw new BuiltValueNullFieldError('Parameter', 'types'); } @override @@ -581,16 +606,33 @@ class _$ParameterBuilder extends ParameterBuilder { @override _$Parameter build() { - final _$result = _$v ?? - new _$Parameter._( - defaultTo: defaultTo, - name: name, - named: named, - toThis: toThis, - annotations: annotations?.build(), - docs: docs?.build(), - types: types?.build(), - type: type); + _$Parameter _$result; + try { + _$result = _$v ?? + new _$Parameter._( + defaultTo: defaultTo, + name: name, + named: named, + toThis: toThis, + annotations: annotations.build(), + docs: docs.build(), + types: types.build(), + type: type); + } catch (_) { + String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + _$failedField = 'types'; + types.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'Parameter', _$failedField, e.toString()); + } + rethrow; + } replace(_$result); return _$result; } diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart index 2faa2d273..1a64ed134 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -36,13 +36,14 @@ class _$FunctionType extends FunctionType { this.optionalParameters, this.namedParameters}) : super._() { - if (types == null) throw new ArgumentError.notNull('types'); + if (types == null) + throw new BuiltValueNullFieldError('FunctionType', 'types'); if (requiredParameters == null) - throw new ArgumentError.notNull('requiredParameters'); + throw new BuiltValueNullFieldError('FunctionType', 'requiredParameters'); if (optionalParameters == null) - throw new ArgumentError.notNull('optionalParameters'); + throw new BuiltValueNullFieldError('FunctionType', 'optionalParameters'); if (namedParameters == null) - throw new ArgumentError.notNull('namedParameters'); + throw new BuiltValueNullFieldError('FunctionType', 'namedParameters'); } @override @@ -176,13 +177,32 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { @override _$FunctionType build() { - final _$result = _$v ?? - new _$FunctionType._( - returnType: returnType, - types: types?.build(), - requiredParameters: requiredParameters?.build(), - optionalParameters: optionalParameters?.build(), - namedParameters: namedParameters?.build()); + _$FunctionType _$result; + try { + _$result = _$v ?? + new _$FunctionType._( + returnType: returnType, + types: types.build(), + requiredParameters: requiredParameters.build(), + optionalParameters: optionalParameters.build(), + namedParameters: namedParameters.build()); + } catch (_) { + String _$failedField; + try { + _$failedField = 'types'; + types.build(); + _$failedField = 'requiredParameters'; + requiredParameters.build(); + _$failedField = 'optionalParameters'; + optionalParameters.build(); + _$failedField = 'namedParameters'; + namedParameters.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'FunctionType', _$failedField, e.toString()); + } + rethrow; + } replace(_$result); return _$result; } diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index 05d271904..226f9e041 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -29,8 +29,10 @@ class _$TypeReference extends TypeReference { _$TypeReference._({this.symbol, this.url, this.bound, this.types}) : super._() { - if (symbol == null) throw new ArgumentError.notNull('symbol'); - if (types == null) throw new ArgumentError.notNull('types'); + if (symbol == null) + throw new BuiltValueNullFieldError('TypeReference', 'symbol'); + if (types == null) + throw new BuiltValueNullFieldError('TypeReference', 'types'); } @override @@ -146,9 +148,22 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { @override _$TypeReference build() { - final _$result = _$v ?? - new _$TypeReference._( - symbol: symbol, url: url, bound: bound, types: types?.build()); + _$TypeReference _$result; + try { + _$result = _$v ?? + new _$TypeReference._( + symbol: symbol, url: url, bound: bound, types: types.build()); + } catch (_) { + String _$failedField; + try { + _$failedField = 'types'; + types.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'TypeReference', _$failedField, e.toString()); + } + rethrow; + } replace(_$result); return _$result; } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 10c3e3585..bd3c33b25 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.0.1 +version: 3.0.2 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -13,13 +13,13 @@ web: dependencies: built_collection: '>=1.0.0 <4.0.0' - built_value: '>=2.0.0 <5.0.0' + built_value: ^5.1.0 matcher: ^0.12.0 meta: ^1.0.5 dev_dependencies: build_runner: '>=0.4.0 <0.7.0' - built_value_generator: '>=2.0.0 <5.0.0' + built_value_generator: ^5.1.0 dart_style: ^1.0.0 source_gen: '^0.7.0' test: ^0.12.0 From d5b79b4e574988916f689866aa289e2b57075426 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Mon, 29 Jan 2018 19:49:53 -0800 Subject: [PATCH 106/271] Prepare to release 3.0.1 (dart-lang/code_builder#193) --- pkgs/code_builder/CHANGELOG.md | 6 ++---- .../code_builder/lib/src/specs/expression/literal.dart | 3 +++ pkgs/code_builder/pubspec.yaml | 10 +--------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 195e96bfc..d30703293 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,10 +1,8 @@ -## 3.0.2 - -* Upgrade to `built_value` 5.1.0. - ## 3.0.1 +* Upgrade to `built_value` 5.1.0. * Export the `literalNum` function. +* **BUG FIX**: `literal` supports a `Map`. ## 3.0.0 diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index b98825056..b407b5a26 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -20,6 +20,9 @@ Expression literal(Object literal, {Expression onError(Object value)}) { if (literal is List) { return literalList(literal); } + if (literal is Map) { + return literalMap(literal); + } if (literal == null) { return literalNull; } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index bd3c33b25..6514cf6fd 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.0.2 +version: 3.0.1 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -7,10 +7,6 @@ homepage: https://github.com/dart-lang/code_builder environment: sdk: '>=2.0.0-dev <2.0.0' -web: - compiler: - debug: dartdevc - dependencies: built_collection: '>=1.0.0 <4.0.0' built_value: ^5.1.0 @@ -23,7 +19,3 @@ dev_dependencies: dart_style: ^1.0.0 source_gen: '^0.7.0' test: ^0.12.0 - -transformers: - - test/pub_serve: - $include: test/**_test.dart From c8bd929ef6e2fdc998426faab9c1a2f27224634d Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Tue, 6 Feb 2018 22:35:57 -0800 Subject: [PATCH 107/271] Update to the latest build_runner. (dart-lang/code_builder#194) * Update to the latest build_runner. * Remove library directives. --- pkgs/code_builder/README.md | 10 ++++++++++ pkgs/code_builder/build.yaml | 14 ++++++++++++++ pkgs/code_builder/lib/src/specs/class.dart | 2 -- pkgs/code_builder/lib/src/specs/class.g.dart | 2 +- pkgs/code_builder/lib/src/specs/code.dart | 2 -- pkgs/code_builder/lib/src/specs/code.g.dart | 2 +- pkgs/code_builder/lib/src/specs/constructor.dart | 2 -- .../lib/src/specs/constructor.g.dart | 2 +- pkgs/code_builder/lib/src/specs/directive.dart | 2 -- pkgs/code_builder/lib/src/specs/directive.g.dart | 2 +- pkgs/code_builder/lib/src/specs/field.dart | 2 -- pkgs/code_builder/lib/src/specs/field.g.dart | 2 +- pkgs/code_builder/lib/src/specs/library.dart | 2 -- pkgs/code_builder/lib/src/specs/library.g.dart | 2 +- pkgs/code_builder/lib/src/specs/method.dart | 2 -- pkgs/code_builder/lib/src/specs/method.g.dart | 2 +- .../lib/src/specs/type_function.dart | 2 -- .../lib/src/specs/type_function.g.dart | 2 +- .../lib/src/specs/type_reference.dart | 2 -- .../lib/src/specs/type_reference.g.dart | 2 +- pkgs/code_builder/pubspec.yaml | 11 +++++++++-- pkgs/code_builder/tool/build.dart | 13 ------------- .../tool/src/{codegen.dart => builder.dart} | 16 ++++++---------- pkgs/code_builder/tool/watch.dart | 13 ------------- 24 files changed, 48 insertions(+), 65 deletions(-) create mode 100644 pkgs/code_builder/build.yaml delete mode 100644 pkgs/code_builder/tool/build.dart rename pkgs/code_builder/tool/src/{codegen.dart => builder.dart} (51%) delete mode 100644 pkgs/code_builder/tool/watch.dart diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 036be72ac..fc8d9741b 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -91,3 +91,13 @@ will be on a best-effort basis. [wiki]: https://github.com/dart-lang/code_builder/wiki [issue]: https://github.com/dart-lang/code_builder/issues [pull]: https://github.com/dart-lang/code_builder/pulls + +### Updating generated (`.g.dart`) files + +Use [`build_runner`][build_runner]: + +```bash +$ pub run build_runner build --delete-conflicting-outputs +``` + +[build_runner]: https://pub.dartlang.org/packages/build_runner diff --git a/pkgs/code_builder/build.yaml b/pkgs/code_builder/build.yaml new file mode 100644 index 000000000..8654afbcc --- /dev/null +++ b/pkgs/code_builder/build.yaml @@ -0,0 +1,14 @@ +targets: + $default: + builders: + "|_built_value": + +builders: + _built_value: + target: ":code_builder" + import: "../../../tool/src/builder.dart" + builder_factories: + - "builtValueBuilder" + build_extensions: + ".dart": ".g.dart" + build_to: "source" diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart index 5e12ec1f9..4f81f15a4 100644 --- a/pkgs/code_builder/lib/src/specs/class.dart +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.class_; - import 'package:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index 7ab65d15b..f3746f267 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of code_builder.src.specs.class_; +part of 'class.dart'; // ************************************************************************** // Generator: BuiltValueGenerator diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index 4814ebfd0..936f33365 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.code; - import 'package:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart index 9952e7013..5c0f4e6b9 100644 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of code_builder.src.specs.code; +part of 'code.dart'; // ************************************************************************** // Generator: BuiltValueGenerator diff --git a/pkgs/code_builder/lib/src/specs/constructor.dart b/pkgs/code_builder/lib/src/specs/constructor.dart index 3bf9b569b..db7202ef8 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.constructor; - import 'package:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index d83818843..d08f35e8c 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of code_builder.src.specs.constructor; +part of 'constructor.dart'; // ************************************************************************** // Generator: BuiltValueGenerator diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart index bc3a9db79..ff68db525 100644 --- a/pkgs/code_builder/lib/src/specs/directive.dart +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.directive; - import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart index 336d5ef9c..2dfe91a8c 100644 --- a/pkgs/code_builder/lib/src/specs/directive.g.dart +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of code_builder.src.specs.directive; +part of 'directive.dart'; // ************************************************************************** // Generator: BuiltValueGenerator diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index 201ae9c98..314ff7561 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.field; - import 'package:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index d78fcdd46..15898393d 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of code_builder.src.specs.field; +part of 'field.dart'; // ************************************************************************** // Generator: BuiltValueGenerator diff --git a/pkgs/code_builder/lib/src/specs/library.dart b/pkgs/code_builder/lib/src/specs/library.dart index 180bc8978..7f7b4976c 100644 --- a/pkgs/code_builder/lib/src/specs/library.dart +++ b/pkgs/code_builder/lib/src/specs/library.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.library; - import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index 9d8eb279b..15c6a6054 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of code_builder.src.specs.library; +part of 'library.dart'; // ************************************************************************** // Generator: BuiltValueGenerator diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 31180a29a..c8f29c225 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.method; - import 'package:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index 470b7b2d0..d7eb9fc1c 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of code_builder.src.specs.method; +part of 'method.dart'; // ************************************************************************** // Generator: BuiltValueGenerator diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index 44dac42ed..ed02440fe 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.type_function; - import 'package:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart index 1a64ed134..fef17dc64 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of code_builder.src.specs.type_function; +part of 'type_function.dart'; // ************************************************************************** // Generator: BuiltValueGenerator diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index cb1415b85..4eaa81c56 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.type_reference; - import 'package:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index 226f9e041..5d7e23b16 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of code_builder.src.specs.type_reference; +part of 'type_reference.dart'; // ************************************************************************** // Generator: BuiltValueGenerator diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 6514cf6fd..9ff804118 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -14,8 +14,15 @@ dependencies: meta: ^1.0.5 dev_dependencies: - build_runner: '>=0.4.0 <0.7.0' + build_runner: ^0.7.9 built_value_generator: ^5.1.0 dart_style: ^1.0.0 - source_gen: '^0.7.0' + source_gen: ^0.7.0 test: ^0.12.0 + +# Required until built_value_generator supports 0.7.9. +# +# Remove when publishing. +dependency_overrides: + build: ^0.12.0 + build_runner: ^0.7.9 diff --git a/pkgs/code_builder/tool/build.dart b/pkgs/code_builder/tool/build.dart deleted file mode 100644 index 55be42c1b..000000000 --- a/pkgs/code_builder/tool/build.dart +++ /dev/null @@ -1,13 +0,0 @@ -// 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 'dart:async'; - -import 'package:build_runner/build_runner.dart'; - -import 'src/codegen.dart'; - -Future main() async { - await build([buildAction()], deleteFilesByDefault: true); -} diff --git a/pkgs/code_builder/tool/src/codegen.dart b/pkgs/code_builder/tool/src/builder.dart similarity index 51% rename from pkgs/code_builder/tool/src/codegen.dart rename to pkgs/code_builder/tool/src/builder.dart index 8d8bbd2f1..9e8393db1 100644 --- a/pkgs/code_builder/tool/src/codegen.dart +++ b/pkgs/code_builder/tool/src/builder.dart @@ -2,17 +2,13 @@ // 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:build_runner/build_runner.dart'; +import 'package:build/build.dart'; import 'package:built_value_generator/built_value_generator.dart'; import 'package:source_gen/source_gen.dart'; -/// Returns the [BuildAction] for both `build.dart` and `watch.dart`. -BuildAction buildAction() { - return new BuildAction( - new PartBuilder([ - const BuiltValueGenerator(), - ]), - 'code_builder', - inputs: const ['lib/src/specs/**.dart'], - ); +/// Returns a [Builder] to generate `.g.dart` files for `built_value`. +Builder builtValueBuilder(BuilderOptions _) { + return new PartBuilder([ + const BuiltValueGenerator(), + ], requireLibraryDirective: false); } diff --git a/pkgs/code_builder/tool/watch.dart b/pkgs/code_builder/tool/watch.dart deleted file mode 100644 index eb3e9fcad..000000000 --- a/pkgs/code_builder/tool/watch.dart +++ /dev/null @@ -1,13 +0,0 @@ -// 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 'dart:async'; - -import 'package:build_runner/build_runner.dart'; - -import 'src/codegen.dart'; - -Future main() async { - await watch([buildAction()], deleteFilesByDefault: true); -} From 3e2169a6c8221431d2e5d24d02ae39ae34c12997 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 9 Feb 2018 17:13:55 -0800 Subject: [PATCH 108/271] Bump for source_gen. (dart-lang/code_builder#196) --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/pubspec.yaml | 4 ++-- pkgs/code_builder/tool/src/builder.dart | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index d30703293..d44df5740 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.2 + +* Require `source_gen: ^0.7.5`. + ## 3.0.1 * Upgrade to `built_value` 5.1.0. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 9ff804118..ffa34c3f4 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.0.1 +version: 3.0.2 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -17,7 +17,7 @@ dev_dependencies: build_runner: ^0.7.9 built_value_generator: ^5.1.0 dart_style: ^1.0.0 - source_gen: ^0.7.0 + source_gen: ^0.7.5 test: ^0.12.0 # Required until built_value_generator supports 0.7.9. diff --git a/pkgs/code_builder/tool/src/builder.dart b/pkgs/code_builder/tool/src/builder.dart index 9e8393db1..4b0803cb9 100644 --- a/pkgs/code_builder/tool/src/builder.dart +++ b/pkgs/code_builder/tool/src/builder.dart @@ -10,5 +10,5 @@ import 'package:source_gen/source_gen.dart'; Builder builtValueBuilder(BuilderOptions _) { return new PartBuilder([ const BuiltValueGenerator(), - ], requireLibraryDirective: false); + ]); } From 946f3c6977b7d3169c3f0904ac1faad3769b502a Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Sat, 10 Feb 2018 10:55:53 -0800 Subject: [PATCH 109/271] Fix build_runner crashes. (dart-lang/code_builder#198) --- pkgs/code_builder/CHANGELOG.md | 6 ++++++ pkgs/code_builder/README.md | 6 ++++++ pkgs/code_builder/{build.yaml => build.disabled.yaml} | 0 pkgs/code_builder/pubspec.yaml | 3 ++- 4 files changed, 14 insertions(+), 1 deletion(-) rename pkgs/code_builder/{build.yaml => build.disabled.yaml} (100%) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index d44df5740..0da90b6cf 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,9 @@ +## 3.0.3 + +* Fix a bug that caused all downstream users of `code_builder` to crash due to + `build_runner` trying to import our private builder (in `tool/`). Sorry for + the inconvenience. + ## 3.0.2 * Require `source_gen: ^0.7.5`. diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index fc8d9741b..d36b9eed8 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -94,10 +94,16 @@ will be on a best-effort basis. ### Updating generated (`.g.dart`) files +> **NOTE**: There is currently a limitation in `build_runner` that requires +> a workaround for developing this package. We expect this to be unnecessary +> in the future. + Use [`build_runner`][build_runner]: ```bash +$ mv build.disabled.yaml build.yaml $ pub run build_runner build --delete-conflicting-outputs +$ mv build.yaml build.disabled.yaml ``` [build_runner]: https://pub.dartlang.org/packages/build_runner diff --git a/pkgs/code_builder/build.yaml b/pkgs/code_builder/build.disabled.yaml similarity index 100% rename from pkgs/code_builder/build.yaml rename to pkgs/code_builder/build.disabled.yaml diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index ffa34c3f4..3995e7f6f 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.0.2 +version: 3.0.3 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -14,6 +14,7 @@ dependencies: meta: ^1.0.5 dev_dependencies: + build: ^0.12.0 build_runner: ^0.7.9 built_value_generator: ^5.1.0 dart_style: ^1.0.0 From 1cfe7207810afc60675d8f3fd1481d8c3b791175 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 23 Feb 2018 09:31:42 -0800 Subject: [PATCH 110/271] Run latest dartfmt. (dart-lang/code_builder#201) --- pkgs/code_builder/lib/src/specs/expression/invoke.dart | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index 84148beea..037a2e7e0 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -23,8 +23,7 @@ class InvokeExpression extends Expression { this.namedArguments = const {}, this.typeArguments, this.name, - ]) - : type = null; + ]) : type = null; @visibleForTesting const InvokeExpression.newOf( @@ -33,8 +32,7 @@ class InvokeExpression extends Expression { this.namedArguments = const {}, this.typeArguments, this.name, - ]) - : type = InvokeExpressionType.newInstance; + ]) : type = InvokeExpressionType.newInstance; @visibleForTesting const InvokeExpression.constOf( @@ -43,8 +41,7 @@ class InvokeExpression extends Expression { this.namedArguments = const {}, this.typeArguments, this.name, - ]) - : type = InvokeExpressionType.constInstance; + ]) : type = InvokeExpressionType.constInstance; @override R accept(ExpressionVisitor visitor, [R context]) { From b21553cae9ef4e094b760ae1845a219b8daeea58 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 26 Feb 2018 11:18:57 -0800 Subject: [PATCH 111/271] Remove visibleForTesting annotation for 4 functions (dart-lang/code_builder#202) --- pkgs/code_builder/lib/src/emitter.dart | 3 --- pkgs/code_builder/lib/src/specs/expression/closure.dart | 1 - pkgs/code_builder/lib/src/specs/expression/invoke.dart | 2 -- 3 files changed, 6 deletions(-) diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 82284a42d..7f2c6936e 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -2,8 +2,6 @@ // 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:meta/meta.dart'; - import 'allocator.dart'; import 'base.dart'; import 'specs/class.dart'; @@ -24,7 +22,6 @@ import 'visitors.dart'; /// For every `Spec` in [elements], executing [visit]. /// /// If [elements] is at least 2 elements, inserts [separator] delimiting them. -@visibleForTesting StringSink visitAll( Iterable elements, StringSink output, diff --git a/pkgs/code_builder/lib/src/specs/expression/closure.dart b/pkgs/code_builder/lib/src/specs/expression/closure.dart index e8600dcec..99377c005 100644 --- a/pkgs/code_builder/lib/src/specs/expression/closure.dart +++ b/pkgs/code_builder/lib/src/specs/expression/closure.dart @@ -4,7 +4,6 @@ part of code_builder.src.specs.expression; -@visibleForTesting Expression toClosure(Method method) { final withoutTypes = method.rebuild((b) { b.returns = null; diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index 037a2e7e0..3ac586fe3 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -25,7 +25,6 @@ class InvokeExpression extends Expression { this.name, ]) : type = null; - @visibleForTesting const InvokeExpression.newOf( this.target, this.positionalArguments, [ @@ -34,7 +33,6 @@ class InvokeExpression extends Expression { this.name, ]) : type = InvokeExpressionType.newInstance; - @visibleForTesting const InvokeExpression.constOf( this.target, this.positionalArguments, [ From 926b40fc2d13a368e4eae82699d3fe5b00722daf Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 7 Mar 2018 07:15:51 -0800 Subject: [PATCH 112/271] Update gitter badge (dart-lang/code_builder#204) Fixes https://github.com/dart-lang/code_builder/issues/203 --- pkgs/code_builder/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index d36b9eed8..decbfe563 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -3,7 +3,7 @@ [![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) [![Latest docs](https://img.shields.io/badge/dartdocs-latest-blue.svg)](https://www.dartdocs.org/documentation/code_builder/latest) -[![Gitter chat](https://badges.gitter.im/dart-lang/source_gen.svg)](https://gitter.im/dart-lang/source_gen) +[![Gitter chat](https://badges.gitter.im/dart-lang/build.svg)](https://gitter.im/dart-lang/build) `code_builder` is a fluent Dart API for generating valid Dart source code. From d8241b05aa0bbd2243dc1382e6f7b57ad18e7680 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 5 Apr 2018 14:04:51 -0700 Subject: [PATCH 113/271] Fix travis by using SDK dartfmt (dart-lang/code_builder#205) --- pkgs/code_builder/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index d206571e5..3d9c7f5f0 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -18,4 +18,4 @@ branches: dart_task: - test: --platform vm - dartanalyzer - - dartfmt + - dartfmt: sdk From 584bf5784e748a823877e894ee15787ec6a2202a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 18 Mar 2018 11:25:18 -0700 Subject: [PATCH 114/271] Update dev dependencies to get latest source_gen and build_runner --- pkgs/code_builder/pubspec.yaml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 3995e7f6f..ccb9729e1 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.0.3 +version: 3.0.4-dev description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder @@ -15,15 +15,8 @@ dependencies: dev_dependencies: build: ^0.12.0 - build_runner: ^0.7.9 + build_runner: '>=0.7.9 <0.9.0' built_value_generator: ^5.1.0 dart_style: ^1.0.0 - source_gen: ^0.7.5 + source_gen: '>=0.7.5 <0.9.0' test: ^0.12.0 - -# Required until built_value_generator supports 0.7.9. -# -# Remove when publishing. -dependency_overrides: - build: ^0.12.0 - build_runner: ^0.7.9 From 9a547be15d335959af2c0466185b79fdde5bea37 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 18 Mar 2018 11:25:58 -0700 Subject: [PATCH 115/271] .gitignore: ignore .dart_tool and other cleanup --- pkgs/code_builder/.gitignore | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/pkgs/code_builder/.gitignore b/pkgs/code_builder/.gitignore index ae6cc48c5..feb089dd9 100644 --- a/pkgs/code_builder/.gitignore +++ b/pkgs/code_builder/.gitignore @@ -1,14 +1,5 @@ # Files and directories created by pub -.buildlog +.dart_tool .packages -.project .pub -**/build -**/packages - -# Directory created by dartdoc -doc/api/ - -# Don't commit pubspec lock file -# (Library packages only! Remove pattern if developing an application package) pubspec.lock From ae06c633caa810a4e24d2d49fc15ede69e05e145 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 6 May 2018 18:39:38 -0700 Subject: [PATCH 116/271] remove gratuitous export (dart-lang/code_builder#207) --- pkgs/code_builder/lib/code_builder.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 79685a7c8..7ee6102f7 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -6,7 +6,6 @@ export 'src/allocator.dart' show Allocator; export 'src/base.dart' show lazySpec, Spec; export 'src/emitter.dart' show DartEmitter; export 'src/matchers.dart' show equalsDart, EqualsDart; -export 'src/matchers.dart' show equalsDart; export 'src/specs/class.dart' show Class, ClassBuilder; export 'src/specs/code.dart' show lazyCode, Block, BlockBuilder, Code, StaticCode, ScopedCode; From 04edfdd16ab430df6e92d596319154a8fe9c3fc4 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 1 Jun 2018 11:25:38 -0700 Subject: [PATCH 117/271] add Expression.asA (dart-lang/code_builder#210) --- pkgs/code_builder/CHANGELOG.md | 21 ++++++++++++++++--- .../lib/src/specs/expression.dart | 9 ++++++++ pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 7 +++++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 0da90b6cf..e7b249186 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,18 @@ +## 3.0.4 + +* Added `Expression.asA` for creating explicit casts: + +```dart +void main() { + test('should emit an explicit cast', () { + expect( + refer('foo').asA(refer('String')), + equalsDart('foo as String'), + ); + }); +} +``` + ## 3.0.3 * Fix a bug that caused all downstream users of `code_builder` to crash due to @@ -314,7 +329,7 @@ are welcome! * `const Code.scope((allocate) => '')` * Removed `SimpleSpecVisitor` (it was unused). -* Removed `implements Reference` from `Method` and `Field`; not a lot of value. +* Removed `implements Reference` from `Method` and `Field`; not a lot of value. * `SpecVisitor`'s methods all have an optional `[T context]` parameter now. * This makes it much easier to avoid allocating extra `StringBuffer`s. @@ -353,7 +368,7 @@ final animal = new Class((b) => b ```dart expect( - reference('foo').isInstanceOf(_barType), + reference('foo').isInstanceOf(_barType), equalsSource('foo is Bar'), ); ``` @@ -403,7 +418,7 @@ that the entire Dart language is buildable with our API, though. - Added `ConstructorBuilder.redirectTo` for a redirecting factory constructor. - Added a `name` getter to `ReferenceBuilder`. - Supplying an empty constructor name (`''`) is equivalent to `null` (default). -- Automatically encodes string literals with multiple lines as `'''`. +- Automatically encodes string literals with multiple lines as `'''`. - Added `asThrow` to `ExpressionBuilder`. - Fixed a bug that prevented `FieldBuilder` from being used at the top-level. diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 50600a49f..a0632f56f 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -44,6 +44,15 @@ abstract class Expression implements Spec { return new BinaryExpression._(expression, other, '&&'); } + /// Returns the result of `this` `as` [other]. + Expression asA(Expression other) { + return new BinaryExpression._( + expression, + other, + 'as', + ); + } + /// Returns accessing the index operator (`[]`) on `this`. Expression index(Expression index) { return new BinaryExpression._( diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index ccb9729e1..2b667fa33 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.0.4-dev +version: 3.0.4 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index d64cb6454..e54c883c4 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -343,6 +343,13 @@ void main() { ); }); + test('should emit an explicit cast', () { + expect( + refer('foo').asA(refer('String')), + equalsDart('foo as String'), + ); + }); + test('should emit an is check', () { expect( refer('foo').isA(refer('String')), From 8bf0599bd81c720f71bb64028b15a0ac14252fbd Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 1 Jun 2018 12:01:39 -0700 Subject: [PATCH 118/271] change version to 3.1.0 (dart-lang/code_builder#211) Bump version to 3.1.0 --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index e7b249186..fd1c6b350 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.0.4 +## 3.1.0 * Added `Expression.asA` for creating explicit casts: diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 2b667fa33..61ea758f6 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.0.4 +version: 3.1.0 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From a9fe70a25ec83e9d99ca11ef5881bf3d0c9786a3 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 6 Jun 2018 14:06:26 -0700 Subject: [PATCH 119/271] Enable prefer_equal_for_default_values lint (dart-lang/code_builder#212) --- pkgs/code_builder/analysis_options.yaml | 1 + pkgs/code_builder/lib/src/emitter.dart | 4 ++-- pkgs/code_builder/lib/src/specs/directive.dart | 12 ++++++------ .../lib/src/specs/expression/literal.dart | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml index cf2c8917f..b4b37b47b 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/analysis_options.yaml @@ -41,6 +41,7 @@ linter: - prefer_collection_literals - prefer_const_constructors - prefer_contains + - prefer_equal_for_default_values - prefer_final_fields - prefer_final_locals - prefer_initializing_formals diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 7f2c6936e..b19c40584 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -427,8 +427,8 @@ class DartEmitter extends Object void _visitParameter( Parameter spec, StringSink output, { - bool optional: false, - bool named: false, + bool optional = false, + bool named = false, }) { spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart index ff68db525..b804ce6ec 100644 --- a/pkgs/code_builder/lib/src/specs/directive.dart +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -17,8 +17,8 @@ abstract class Directive implements Built, Spec { factory Directive.import( String url, { String as, - List show: const [], - List hide: const [], + List show = const [], + List hide = const [], }) => new Directive((builder) => builder ..as = as @@ -30,8 +30,8 @@ abstract class Directive implements Built, Spec { factory Directive.importDeferredAs( String url, String as, { - List show: const [], - List hide: const [], + List show = const [], + List hide = const [], }) => new Directive((builder) => builder ..as = as @@ -43,8 +43,8 @@ abstract class Directive implements Built, Spec { factory Directive.export( String url, { - List show: const [], - List hide: const [], + List show = const [], + List hide = const [], }) => new Directive((builder) => builder ..type = DirectiveType.export diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index b407b5a26..720ea37ba 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -54,7 +54,7 @@ Expression literalNum(num value) => new LiteralExpression._('$value'); /// If [raw] is `true`, creates a raw String formatted `r''` and the /// value may not contain a single quote. /// If [raw] is `false` escapes single quotes in the value. -Expression literalString(String value, {bool raw: false}) { +Expression literalString(String value, {bool raw = false}) { if (raw && value.contains('\'')) { throw new ArgumentError('Cannot include a single quote in a raw string'); } From 38af8aa8309c789a6f51bb94ef17a8bd6ac82486 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 26 Jun 2018 13:49:49 -0700 Subject: [PATCH 120/271] Wrap `as` expressions with parens (dart-lang/code_builder#214) Closes dart-lang/code_builder#213 --- pkgs/code_builder/CHANGELOG.md | 6 ++++++ pkgs/code_builder/lib/src/specs/expression.dart | 14 +++++++++----- pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index fd1c6b350..ee720dd9d 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,9 @@ +## 3.1.1 + +* `Expression.asA` is now wrapped with parenthesis so that further calls may be + made on it as an expression. + + ## 3.1.0 * Added `Expression.asA` for creating explicit casts: diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index a0632f56f..00f5e33b8 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -46,11 +46,15 @@ abstract class Expression implements Spec { /// Returns the result of `this` `as` [other]. Expression asA(Expression other) { - return new BinaryExpression._( - expression, - other, - 'as', - ); + return new CodeExpression(new Block.of([ + const Code('('), + new BinaryExpression._( + expression, + other, + 'as', + ).code, + const Code(')') + ])); } /// Returns accessing the index operator (`[]`) on `this`. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 61ea758f6..b14ae07b9 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.1.0 +version: 3.1.1 description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index e54c883c4..df1888da3 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -345,8 +345,8 @@ void main() { test('should emit an explicit cast', () { expect( - refer('foo').asA(refer('String')), - equalsDart('foo as String'), + refer('foo').asA(refer('String')).property('length'), + equalsDart('( foo as String ).length'), ); }); From 63944f8d1ad097a96af9f129a4a4cd838856e03e Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Thu, 19 Jul 2018 16:51:24 -0400 Subject: [PATCH 121/271] chore: set max SDK version to <3.0.0 (dart-lang/code_builder#215) --- pkgs/code_builder/.travis.yml | 2 +- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/pubspec.yaml | 11 ++++++----- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index 3d9c7f5f0..d206571e5 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -18,4 +18,4 @@ branches: dart_task: - test: --platform vm - dartanalyzer - - dartfmt: sdk + - dartfmt diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index ee720dd9d..c2d9fe1f1 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.1.2 + +* Set max SDK version to `<3.0.0`. + ## 3.1.1 * `Expression.asA` is now wrapped with parenthesis so that further calls may be diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index b14ae07b9..65a10f4eb 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,11 +1,12 @@ name: code_builder -version: 3.1.1 +version: 3.1.2 + description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=2.0.0-dev <2.0.0' + sdk: '>=2.0.0-dev <3.0.0' dependencies: built_collection: '>=1.0.0 <4.0.0' @@ -15,8 +16,8 @@ dependencies: dev_dependencies: build: ^0.12.0 - build_runner: '>=0.7.9 <0.9.0' + build_runner: ^0.9.2 built_value_generator: ^5.1.0 dart_style: ^1.0.0 - source_gen: '>=0.7.5 <0.9.0' - test: ^0.12.0 + source_gen: ^0.8.3 + test: ^1.3.0 From 0d4f049277243093d2c546b85f7faadc29eb656c Mon Sep 17 00:00:00 2001 From: Eric Schneller Date: Wed, 1 Aug 2018 00:40:37 +0200 Subject: [PATCH 122/271] Add Expression.operators (add/substract/divide/multiply/euclidean modulo) (dart-lang/code_builder#218) Closes dart-lang/code_builder#216 --- .../lib/src/specs/expression.dart | 45 +++++++++++++++++++ .../test/specs/code/expression_test.dart | 24 ++++++++++ 2 files changed, 69 insertions(+) diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 00f5e33b8..e05f91bde 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -142,6 +142,51 @@ abstract class Expression implements Spec { ); } + /// Returns the result of `this` `+` [other]. + Expression operatorAdd(Expression other) { + return new BinaryExpression._( + expression, + other, + '+', + ); + } + + /// Returns the result of `this` `-` [other]. + Expression operatorSubstract(Expression other) { + return new BinaryExpression._( + expression, + other, + '-', + ); + } + + /// Returns the result of `this` `/` [other]. + Expression operatorDivide(Expression other) { + return new BinaryExpression._( + expression, + other, + '/', + ); + } + + /// Returns the result of `this` `*` [other]. + Expression operatorMultiply(Expression other) { + return new BinaryExpression._( + expression, + other, + '*', + ); + } + + /// Returns the result of `this` `%` [other]. + Expression operatorEuclideanModulo(Expression other) { + return new BinaryExpression._( + expression, + other, + '%', + ); + } + Expression conditional(Expression whenTrue, Expression whenFalse) { return new BinaryExpression._( expression, diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index df1888da3..e6f2e6539 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -412,4 +412,28 @@ void main() { equalsDart('foo ? 1 : 2'), ); }); + + test('should emit an operator add call', () { + expect(refer('foo').operatorAdd(refer('foo2')), equalsDart('foo + foo2')); + }); + + test('should emit an operator substract call', () { + expect(refer('foo').operatorSubstract(refer('foo2')), + equalsDart('foo - foo2')); + }); + + test('should emit an operator divide call', () { + expect( + refer('foo').operatorDivide(refer('foo2')), equalsDart('foo / foo2')); + }); + + test('should emit an operator multiply call', () { + expect( + refer('foo').operatorMultiply(refer('foo2')), equalsDart('foo * foo2')); + }); + + test('should emit an euclidean modulo operator call', () { + expect(refer('foo').operatorEuclideanModulo(refer('foo2')), + equalsDart('foo % foo2')); + }); } From b556e3820fca6c0f9315cb2aac456a50e3dcb5ba Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 9 Aug 2018 17:28:19 -0700 Subject: [PATCH 123/271] Update to latest built_value (dart-lang/code_builder#222) Also update build_runner and source_gen. Manually hold back some changes in the generated files - some fields were missing from `TypeReference`. --- pkgs/code_builder/build.disabled.yaml | 2 +- pkgs/code_builder/lib/src/specs/class.g.dart | 4 +++- pkgs/code_builder/lib/src/specs/code.g.dart | 4 +++- pkgs/code_builder/lib/src/specs/constructor.g.dart | 4 +++- pkgs/code_builder/lib/src/specs/directive.g.dart | 4 +++- pkgs/code_builder/lib/src/specs/field.g.dart | 4 +++- pkgs/code_builder/lib/src/specs/library.g.dart | 4 +++- pkgs/code_builder/lib/src/specs/method.g.dart | 4 +++- pkgs/code_builder/lib/src/specs/type_function.g.dart | 4 +++- pkgs/code_builder/lib/src/specs/type_reference.g.dart | 4 +++- pkgs/code_builder/pubspec.yaml | 8 ++++---- pkgs/code_builder/tool/src/builder.dart | 2 +- 12 files changed, 33 insertions(+), 15 deletions(-) diff --git a/pkgs/code_builder/build.disabled.yaml b/pkgs/code_builder/build.disabled.yaml index 8654afbcc..2eed50399 100644 --- a/pkgs/code_builder/build.disabled.yaml +++ b/pkgs/code_builder/build.disabled.yaml @@ -10,5 +10,5 @@ builders: builder_factories: - "builtValueBuilder" build_extensions: - ".dart": ".g.dart" + ".dart": [".g.dart"] build_to: "source" diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index f3746f267..68cff19b4 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -3,13 +3,15 @@ part of 'class.dart'; // ************************************************************************** -// Generator: BuiltValueGenerator +// BuiltValueGenerator // ************************************************************************** // ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides // ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_catches_without_on_clauses // ignore_for_file: avoid_returning_this +// ignore_for_file: lines_longer_than_80_chars // ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart index 5c0f4e6b9..5243ec82f 100644 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -3,13 +3,15 @@ part of 'code.dart'; // ************************************************************************** -// Generator: BuiltValueGenerator +// BuiltValueGenerator // ************************************************************************** // ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides // ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_catches_without_on_clauses // ignore_for_file: avoid_returning_this +// ignore_for_file: lines_longer_than_80_chars // ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index d08f35e8c..efc08f267 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -3,13 +3,15 @@ part of 'constructor.dart'; // ************************************************************************** -// Generator: BuiltValueGenerator +// BuiltValueGenerator // ************************************************************************** // ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides // ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_catches_without_on_clauses // ignore_for_file: avoid_returning_this +// ignore_for_file: lines_longer_than_80_chars // ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart index 2dfe91a8c..a1717b2d5 100644 --- a/pkgs/code_builder/lib/src/specs/directive.g.dart +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -3,13 +3,15 @@ part of 'directive.dart'; // ************************************************************************** -// Generator: BuiltValueGenerator +// BuiltValueGenerator // ************************************************************************** // ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides // ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_catches_without_on_clauses // ignore_for_file: avoid_returning_this +// ignore_for_file: lines_longer_than_80_chars // ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 15898393d..3bef453fa 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -3,13 +3,15 @@ part of 'field.dart'; // ************************************************************************** -// Generator: BuiltValueGenerator +// BuiltValueGenerator // ************************************************************************** // ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides // ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_catches_without_on_clauses // ignore_for_file: avoid_returning_this +// ignore_for_file: lines_longer_than_80_chars // ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index 15c6a6054..9935040d0 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -3,13 +3,15 @@ part of 'library.dart'; // ************************************************************************** -// Generator: BuiltValueGenerator +// BuiltValueGenerator // ************************************************************************** // ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides // ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_catches_without_on_clauses // ignore_for_file: avoid_returning_this +// ignore_for_file: lines_longer_than_80_chars // ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index d7eb9fc1c..b6b862ada 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -3,13 +3,15 @@ part of 'method.dart'; // ************************************************************************** -// Generator: BuiltValueGenerator +// BuiltValueGenerator // ************************************************************************** // ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides // ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_catches_without_on_clauses // ignore_for_file: avoid_returning_this +// ignore_for_file: lines_longer_than_80_chars // ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart index fef17dc64..b89237f58 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -3,13 +3,15 @@ part of 'type_function.dart'; // ************************************************************************** -// Generator: BuiltValueGenerator +// BuiltValueGenerator // ************************************************************************** // ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides // ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_catches_without_on_clauses // ignore_for_file: avoid_returning_this +// ignore_for_file: lines_longer_than_80_chars // ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index 5d7e23b16..bcd362f1f 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -3,13 +3,15 @@ part of 'type_reference.dart'; // ************************************************************************** -// Generator: BuiltValueGenerator +// BuiltValueGenerator // ************************************************************************** // ignore_for_file: always_put_control_body_on_new_line // ignore_for_file: annotate_overrides // ignore_for_file: avoid_annotating_with_dynamic +// ignore_for_file: avoid_catches_without_on_clauses // ignore_for_file: avoid_returning_this +// ignore_for_file: lines_longer_than_80_chars // ignore_for_file: omit_local_variable_types // ignore_for_file: prefer_expression_function_bodies // ignore_for_file: sort_constructors_first diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 65a10f4eb..51097de30 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -10,14 +10,14 @@ environment: dependencies: built_collection: '>=1.0.0 <4.0.0' - built_value: ^5.1.0 + built_value: ^6.0.0 matcher: ^0.12.0 meta: ^1.0.5 dev_dependencies: build: ^0.12.0 - build_runner: ^0.9.2 - built_value_generator: ^5.1.0 + build_runner: ^0.10.0 + built_value_generator: ^6.0.0 dart_style: ^1.0.0 - source_gen: ^0.8.3 + source_gen: ^0.9.0 test: ^1.3.0 diff --git a/pkgs/code_builder/tool/src/builder.dart b/pkgs/code_builder/tool/src/builder.dart index 4b0803cb9..6b0b0989b 100644 --- a/pkgs/code_builder/tool/src/builder.dart +++ b/pkgs/code_builder/tool/src/builder.dart @@ -10,5 +10,5 @@ import 'package:source_gen/source_gen.dart'; Builder builtValueBuilder(BuilderOptions _) { return new PartBuilder([ const BuiltValueGenerator(), - ]); + ], '.g.dart'); } From aaccaf11e2cbcb11847a064f50483d1fd2649116 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 15 Aug 2018 13:36:35 -0700 Subject: [PATCH 124/271] Run dartfmt --fix to drop optional new (dart-lang/code_builder#224) - Update the SDK constraint to >=2.0.0 - Update README to drop `new` keyword. - Hold back lib/**/*.g.dart files since they are generated. --- pkgs/code_builder/README.md | 18 +-- pkgs/code_builder/example/example.dart | 16 +-- pkgs/code_builder/lib/src/allocator.dart | 10 +- pkgs/code_builder/lib/src/base.dart | 2 +- pkgs/code_builder/lib/src/emitter.dart | 26 ++--- pkgs/code_builder/lib/src/matchers.dart | 2 +- pkgs/code_builder/lib/src/specs/class.dart | 16 +-- pkgs/code_builder/lib/src/specs/code.dart | 12 +- .../lib/src/specs/constructor.dart | 10 +- .../code_builder/lib/src/specs/directive.dart | 6 +- .../lib/src/specs/expression.dart | 98 ++++++++-------- .../lib/src/specs/expression/closure.dart | 2 +- .../lib/src/specs/expression/literal.dart | 22 ++-- pkgs/code_builder/lib/src/specs/field.dart | 4 +- pkgs/code_builder/lib/src/specs/library.dart | 4 +- pkgs/code_builder/lib/src/specs/method.dart | 18 +-- .../code_builder/lib/src/specs/reference.dart | 14 +-- .../lib/src/specs/type_function.dart | 16 +-- .../lib/src/specs/type_reference.dart | 12 +- pkgs/code_builder/pubspec.yaml | 4 +- pkgs/code_builder/test/allocator_test.dart | 6 +- pkgs/code_builder/test/common.dart | 2 +- .../code_builder/test/e2e/injection_test.dart | 12 +- pkgs/code_builder/test/specs/class_test.dart | 96 ++++++++-------- .../test/specs/code/expression_test.dart | 16 +-- .../test/specs/code/statement_test.dart | 8 +- pkgs/code_builder/test/specs/field_test.dart | 10 +- .../code_builder/test/specs/library_test.dart | 38 +++--- pkgs/code_builder/test/specs/method_test.dart | 108 +++++++++--------- pkgs/code_builder/tool/src/builder.dart | 2 +- 30 files changed, 304 insertions(+), 306 deletions(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index decbfe563..d4bd2b022 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -20,14 +20,14 @@ import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; void main() { - final animal = new Class((b) => b + final animal = Class((b) => b ..name = 'Animal' ..extend = refer('Organism') - ..methods.add(new Method.returnsVoid((b) => b + ..methods.add(Method.returnsVoid((b) => b ..name = 'eat' ..body = const Code('print(\'Yum\')')))); - final emitter = new DartEmitter(); - print(new DartFormatter().format('${animal.accept(emitter)}')); + final emitter = DartEmitter(); + print(DartFormatter().format('${animal.accept(emitter)}')); } ``` @@ -47,18 +47,18 @@ import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; void main() { - final library = new Library((b) => b.body.addAll([ - new Method((b) => b + final library = Library((b) => b.body.addAll([ + Method((b) => b ..body = const Code('') ..name = 'doThing' ..returns = refer('Thing', 'package:a/a.dart')), - new Method((b) => b + Method((b) => b ..body = const Code('') ..name = 'doOther' ..returns = refer('Other', 'package:b/b.dart')), ])); - final emitter = new DartEmitter(new Allocator.simplePrefixing()); - print(new DartFormatter().format('${library.accept(emitter)}')); + final emitter = DartEmitter(Allocator.simplePrefixing()); + print(DartFormatter().format('${library.accept(emitter)}')); } ``` diff --git a/pkgs/code_builder/example/example.dart b/pkgs/code_builder/example/example.dart index ccb77dfc3..577752bbb 100644 --- a/pkgs/code_builder/example/example.dart +++ b/pkgs/code_builder/example/example.dart @@ -5,7 +5,7 @@ import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; -final _dartfmt = new DartFormatter(); +final _dartfmt = DartFormatter(); void main() { print('animalClass():\n${'=' * 40}\n${animalClass()}'); @@ -20,13 +20,13 @@ void main() { /// } /// ``` String animalClass() { - final animal = new Class((b) => b + final animal = Class((b) => b ..name = 'Animal' ..extend = refer('Organism') - ..methods.add(new Method.returnsVoid((b) => b + ..methods.add(Method.returnsVoid((b) => b ..name = 'eat' ..body = refer('print').call([literalString('Yum!')]).code))); - return _dartfmt.format('${animal.accept(new DartEmitter())}'); + return _dartfmt.format('${animal.accept(DartEmitter())}'); } /// Outputs: @@ -40,15 +40,15 @@ String animalClass() { /// ``` String scopedLibrary() { final methods = [ - new Method((b) => b + Method((b) => b ..body = const Code('') ..name = 'doThing' ..returns = refer('Thing', 'package:a/a.dart')), - new Method((b) => b + Method((b) => b ..body = const Code('') ..name = 'doOther' ..returns = refer('Other', 'package:b/b.dart')), ]; - final library = new Library((b) => b.body.addAll(methods)); - return _dartfmt.format('${library.accept(new DartEmitter.scoped())}'); + final library = Library((b) => b.body.addAll(methods)); + return _dartfmt.format('${library.accept(DartEmitter.scoped())}'); } diff --git a/pkgs/code_builder/lib/src/allocator.dart b/pkgs/code_builder/lib/src/allocator.dart index f6289daa4..87315d5ab 100644 --- a/pkgs/code_builder/lib/src/allocator.dart +++ b/pkgs/code_builder/lib/src/allocator.dart @@ -12,7 +12,7 @@ import 'specs/reference.dart'; /// to resolve all symbols in your generated code. abstract class Allocator { /// An allocator that does not prefix symbols nor collects imports. - static const Allocator none = const _NullAllocator(); + static const Allocator none = _NullAllocator(); /// Creates a new default allocator that applies no prefixing. factory Allocator() = _Allocator; @@ -46,7 +46,7 @@ abstract class Allocator { } class _Allocator implements Allocator { - final _imports = new Set(); + final _imports = Set(); @override String allocate(Reference reference) { @@ -58,7 +58,7 @@ class _Allocator implements Allocator { @override Iterable get imports { - return _imports.map((u) => new Directive.import(u)); + return _imports.map((u) => Directive.import(u)); } } @@ -73,7 +73,7 @@ class _NullAllocator implements Allocator { } class _PrefixedAllocator implements Allocator { - static const _doNotPrefix = const ['dart:core']; + static const _doNotPrefix = ['dart:core']; final _imports = {}; var _keys = 1; @@ -92,7 +92,7 @@ class _PrefixedAllocator implements Allocator { @override Iterable get imports { return _imports.keys.map( - (u) => new Directive.import(u, as: '_i${_imports[u]}'), + (u) => Directive.import(u, as: '_i${_imports[u]}'), ); } } diff --git a/pkgs/code_builder/lib/src/base.dart b/pkgs/code_builder/lib/src/base.dart index c11d5491b..529dd5be9 100644 --- a/pkgs/code_builder/lib/src/base.dart +++ b/pkgs/code_builder/lib/src/base.dart @@ -9,7 +9,7 @@ abstract class Spec { } /// Returns a generic [Spec] that is lazily generated when visited. -Spec lazySpec(Spec Function() generate) => new _LazySpec(generate); +Spec lazySpec(Spec Function() generate) => _LazySpec(generate); class _LazySpec implements Spec { final Spec Function() generate; diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index b19c40584..e039d3ecb 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -57,7 +57,7 @@ class DartEmitter extends Object /// Creates a new instance of [DartEmitter] with simple automatic imports. factory DartEmitter.scoped() { - return new DartEmitter(new Allocator.simplePrefixing()); + return DartEmitter(Allocator.simplePrefixing()); } static bool _isLambdaBody(Code code) => @@ -74,7 +74,7 @@ class DartEmitter extends Object @override visitAnnotation(Expression spec, [StringSink output]) { - (output ??= new StringBuffer()).write('@'); + (output ??= StringBuffer()).write('@'); spec.accept(this, output); output.write(' '); return output; @@ -82,7 +82,7 @@ class DartEmitter extends Object @override visitClass(Class spec, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); if (spec.abstract) { @@ -128,7 +128,7 @@ class DartEmitter extends Object @override visitConstructor(Constructor spec, String clazz, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); if (spec.external) { @@ -212,7 +212,7 @@ class DartEmitter extends Object @override visitDirective(Directive spec, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); if (spec.type == DirectiveType.import) { output.write('import '); } else { @@ -240,7 +240,7 @@ class DartEmitter extends Object @override visitField(Field spec, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); if (spec.static) { @@ -274,9 +274,9 @@ class DartEmitter extends Object @override visitLibrary(Library spec, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); // Process the body first in order to prime the allocators. - final body = new StringBuffer(); + final body = StringBuffer(); for (final spec in spec.body) { spec.accept(this, body); if (spec is Method && _isLambdaMethod(spec)) { @@ -296,7 +296,7 @@ class DartEmitter extends Object @override visitFunctionType(FunctionType spec, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); if (spec.returnType != null) { spec.returnType.accept(this, output); output.write(' '); @@ -336,7 +336,7 @@ class DartEmitter extends Object @override visitMethod(Method spec, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); if (spec.external) { @@ -452,7 +452,7 @@ class DartEmitter extends Object @override visitReference(Reference spec, [StringSink output]) { - return (output ??= new StringBuffer())..write(allocator.allocate(spec)); + return (output ??= StringBuffer())..write(allocator.allocate(spec)); } @override @@ -460,7 +460,7 @@ class DartEmitter extends Object @override visitType(TypeReference spec, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); // Intentionally not .accept to avoid stack overflow. visitReference(spec, output); if (spec.bound != null) { @@ -473,7 +473,7 @@ class DartEmitter extends Object @override visitTypeParameters(Iterable specs, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); if (specs.isNotEmpty) { output ..write('<') diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index 92b654706..dda8ac8ec 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -16,7 +16,7 @@ Matcher equalsDart( String source, [ DartEmitter emitter, ]) => - new EqualsDart._(EqualsDart._format(source), emitter ?? new DartEmitter()); + EqualsDart._(EqualsDart._format(source), emitter ?? DartEmitter()); /// Implementation detail of using the [equalsDart] matcher. /// diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart index 4f81f15a4..3e596a605 100644 --- a/pkgs/code_builder/lib/src/specs/class.dart +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -72,22 +72,22 @@ abstract class ClassBuilder extends Object bool abstract = false; @override - ListBuilder annotations = new ListBuilder(); + ListBuilder annotations = ListBuilder(); @override - ListBuilder docs = new ListBuilder(); + ListBuilder docs = ListBuilder(); Reference extend; - ListBuilder implements = new ListBuilder(); - ListBuilder mixins = new ListBuilder(); + ListBuilder implements = ListBuilder(); + ListBuilder mixins = ListBuilder(); @override - ListBuilder types = new ListBuilder(); + ListBuilder types = ListBuilder(); - ListBuilder constructors = new ListBuilder(); - ListBuilder methods = new ListBuilder(); - ListBuilder fields = new ListBuilder(); + ListBuilder constructors = ListBuilder(); + ListBuilder methods = ListBuilder(); + ListBuilder fields = ListBuilder(); /// Name of the class. String name; diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index 936f33365..6ff923c37 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -50,7 +50,7 @@ abstract class Block implements Built, Code, Spec { factory Block([void updates(BlockBuilder b)]) = _$Block; factory Block.of(Iterable statements) { - return new Block((b) => b..statements.addAll(statements)); + return Block((b) => b..statements.addAll(statements)); } Block._(); @@ -75,7 +75,7 @@ abstract class BlockBuilder implements Builder { statements.add(expression.statement); } - ListBuilder statements = new ListBuilder(); + ListBuilder statements = ListBuilder(); } /// Knowledge of different types of blocks of code in Dart. @@ -94,7 +94,7 @@ abstract class CodeEmitter implements CodeVisitor { @override visitBlock(Block block, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); return visitAll(block.statements, output, (statement) { statement.accept(this, output); }, '\n'); @@ -102,13 +102,13 @@ abstract class CodeEmitter implements CodeVisitor { @override visitStaticCode(StaticCode code, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); return output..write(code.code); } @override visitScopedCode(ScopedCode code, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); return output..write(code.code(allocator.allocate)); } } @@ -126,7 +126,7 @@ class LazyCode implements Code { } /// Returns a generic [Code] that is lazily generated when visited. -Code lazyCode(Code Function() generate) => new _LazyCode(generate); +Code lazyCode(Code Function() generate) => _LazyCode(generate); class _LazyCode implements Code { final Code Function() generate; diff --git a/pkgs/code_builder/lib/src/specs/constructor.dart b/pkgs/code_builder/lib/src/specs/constructor.dart index db7202ef8..04fcc709f 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.dart @@ -72,19 +72,19 @@ abstract class ConstructorBuilder extends Object ConstructorBuilder._(); @override - ListBuilder annotations = new ListBuilder(); + ListBuilder annotations = ListBuilder(); @override - ListBuilder docs = new ListBuilder(); + ListBuilder docs = ListBuilder(); /// Optional parameters. - ListBuilder optionalParameters = new ListBuilder(); + ListBuilder optionalParameters = ListBuilder(); /// Required parameters. - ListBuilder requiredParameters = new ListBuilder(); + ListBuilder requiredParameters = ListBuilder(); /// Constructor initializer statements. - ListBuilder initializers = new ListBuilder(); + ListBuilder initializers = ListBuilder(); /// Body of the constructor. Code body; diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart index b804ce6ec..cb6b3a20a 100644 --- a/pkgs/code_builder/lib/src/specs/directive.dart +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -20,7 +20,7 @@ abstract class Directive implements Built, Spec { List show = const [], List hide = const [], }) => - new Directive((builder) => builder + Directive((builder) => builder ..as = as ..type = DirectiveType.import ..url = url @@ -33,7 +33,7 @@ abstract class Directive implements Built, Spec { List show = const [], List hide = const [], }) => - new Directive((builder) => builder + Directive((builder) => builder ..as = as ..type = DirectiveType.import ..url = url @@ -46,7 +46,7 @@ abstract class Directive implements Built, Spec { List show = const [], List hide = const [], }) => - new Directive((builder) => builder + Directive((builder) => builder ..type = DirectiveType.export ..url = url ..show.addAll(show) diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index e05f91bde..4c2571e70 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -34,21 +34,21 @@ abstract class Expression implements Spec { /// The expression as a valid [Code] block. /// /// Also see [statement]. - Code get code => new ToCodeExpression(this, false); + Code get code => ToCodeExpression(this, false); /// The expression as a valid [Code] block with a trailing `;`. - Code get statement => new ToCodeExpression(this, true); + Code get statement => ToCodeExpression(this, true); /// Returns the result of `this` `&&` [other]. Expression and(Expression other) { - return new BinaryExpression._(expression, other, '&&'); + return BinaryExpression._(expression, other, '&&'); } /// Returns the result of `this` `as` [other]. Expression asA(Expression other) { - return new CodeExpression(new Block.of([ + return CodeExpression(Block.of([ const Code('('), - new BinaryExpression._( + BinaryExpression._( expression, other, 'as', @@ -59,9 +59,9 @@ abstract class Expression implements Spec { /// Returns accessing the index operator (`[]`) on `this`. Expression index(Expression index) { - return new BinaryExpression._( + return BinaryExpression._( expression, - new CodeExpression(new Block.of([ + CodeExpression(Block.of([ const Code('['), index.code, const Code(']'), @@ -72,7 +72,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `is` [other]. Expression isA(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, 'is', @@ -81,7 +81,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `is!` [other]. Expression isNotA(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, 'is!', @@ -90,7 +90,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `==` [other]. Expression equalTo(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '==', @@ -99,7 +99,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `!=` [other]. Expression notEqualTo(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '!=', @@ -108,7 +108,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `>` [other]. Expression greaterThan(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '>', @@ -117,7 +117,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `<` [other]. Expression lessThan(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '<', @@ -126,7 +126,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `>=` [other]. Expression greaterOrEqualTo(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '>=', @@ -135,7 +135,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `<=` [other]. Expression lessOrEqualTo(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '<=', @@ -144,7 +144,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `+` [other]. Expression operatorAdd(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '+', @@ -153,7 +153,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `-` [other]. Expression operatorSubstract(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '-', @@ -162,7 +162,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `/` [other]. Expression operatorDivide(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '/', @@ -171,7 +171,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `*` [other]. Expression operatorMultiply(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '*', @@ -180,7 +180,7 @@ abstract class Expression implements Spec { /// Returns the result of `this` `%` [other]. Expression operatorEuclideanModulo(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( expression, other, '%', @@ -188,16 +188,16 @@ abstract class Expression implements Spec { } Expression conditional(Expression whenTrue, Expression whenFalse) { - return new BinaryExpression._( + return BinaryExpression._( expression, - new BinaryExpression._(whenTrue, whenFalse, ':'), + BinaryExpression._(whenTrue, whenFalse, ':'), '?', ); } /// This expression preceded by `await`. Expression get awaited { - return new BinaryExpression._( + return BinaryExpression._( const LiteralExpression._('await'), this, '', @@ -206,7 +206,7 @@ abstract class Expression implements Spec { /// Return `{other} = {this}`. Expression assign(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( this, other, '=', @@ -215,7 +215,7 @@ abstract class Expression implements Spec { /// Return `{other} ??= {this}`. Expression assignNullAware(Expression other) { - return new BinaryExpression._( + return BinaryExpression._( this, other, '??=', @@ -224,12 +224,12 @@ abstract class Expression implements Spec { /// Return `var {name} = {this}`. Expression assignVar(String name, [Reference type]) { - return new BinaryExpression._( + return BinaryExpression._( type == null - ? new LiteralExpression._('var $name') - : new BinaryExpression._( + ? LiteralExpression._('var $name') + : BinaryExpression._( type.expression, - new LiteralExpression._(name), + LiteralExpression._(name), '', ), this, @@ -239,10 +239,10 @@ abstract class Expression implements Spec { /// Return `final {name} = {this}`. Expression assignFinal(String name, [Reference type]) { - return new BinaryExpression._( + return BinaryExpression._( type == null ? const LiteralExpression._('final') - : new BinaryExpression._( + : BinaryExpression._( const LiteralExpression._('final'), type.expression, '', @@ -254,10 +254,10 @@ abstract class Expression implements Spec { /// Return `const {name} = {this}`. Expression assignConst(String name, [Reference type]) { - return new BinaryExpression._( + return BinaryExpression._( type == null ? const LiteralExpression._('const') - : new BinaryExpression._( + : BinaryExpression._( const LiteralExpression._('const'), type.expression, '', @@ -273,7 +273,7 @@ abstract class Expression implements Spec { Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression._( + return InvokeExpression._( this, positionalArguments.toList(), namedArguments, @@ -283,9 +283,9 @@ abstract class Expression implements Spec { /// Returns an expression accessing `.` on this expression. Expression property(String name) { - return new BinaryExpression._( + return BinaryExpression._( this, - new LiteralExpression._(name), + LiteralExpression._(name), '.', false, ); @@ -293,9 +293,9 @@ abstract class Expression implements Spec { /// Returns an expression accessing `?.` on this expression. Expression nullSafeProperty(String name) { - return new BinaryExpression._( + return BinaryExpression._( this, - new LiteralExpression._(name), + LiteralExpression._(name), '?.', false, ); @@ -303,7 +303,7 @@ abstract class Expression implements Spec { /// This expression preceded by `return`. Expression get returned { - return new BinaryExpression._( + return BinaryExpression._( const LiteralExpression._('return'), this, '', @@ -316,8 +316,8 @@ abstract class Expression implements Spec { } /// Creates `typedef {name} =`. -Code createTypeDef(String name, FunctionType type) => new BinaryExpression._( - new LiteralExpression._('typedef $name'), type.expression, '=') +Code createTypeDef(String name, FunctionType type) => BinaryExpression._( + LiteralExpression._('typedef $name'), type.expression, '=') .statement; class ToCodeExpression implements Code { @@ -359,7 +359,7 @@ abstract class ExpressionVisitor implements SpecVisitor { abstract class ExpressionEmitter implements ExpressionVisitor { @override visitToCodeExpression(ToCodeExpression expression, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); expression.code.accept(this, output); if (expression.isStatement) { output.write(';'); @@ -369,7 +369,7 @@ abstract class ExpressionEmitter implements ExpressionVisitor { @override visitBinaryExpression(BinaryExpression expression, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); expression.left.accept(this, output); if (expression.addSpace) { output.write(' '); @@ -384,20 +384,20 @@ abstract class ExpressionEmitter implements ExpressionVisitor { @override visitClosureExpression(ClosureExpression expression, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); return expression.method.accept(this, output); } @override visitCodeExpression(CodeExpression expression, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); final visitor = this as CodeVisitor; return expression.code.accept(visitor, output); } @override visitInvokeExpression(InvokeExpression expression, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); switch (expression.type) { case InvokeExpressionType.newInstance: output.write('new '); @@ -434,7 +434,7 @@ abstract class ExpressionEmitter implements ExpressionVisitor { @override visitLiteralExpression(LiteralExpression expression, [StringSink output]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); return output..write(expression.literal); } @@ -451,7 +451,7 @@ abstract class ExpressionEmitter implements ExpressionVisitor { LiteralListExpression expression, [ StringSink output, ]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); if (expression.isConst) { output.write('const '); } @@ -472,7 +472,7 @@ abstract class ExpressionEmitter implements ExpressionVisitor { LiteralMapExpression expression, [ StringSink output, ]) { - output ??= new StringBuffer(); + output ??= StringBuffer(); if (expression.isConst) { output.write('const '); } diff --git a/pkgs/code_builder/lib/src/specs/expression/closure.dart b/pkgs/code_builder/lib/src/specs/expression/closure.dart index 99377c005..1af27609a 100644 --- a/pkgs/code_builder/lib/src/specs/expression/closure.dart +++ b/pkgs/code_builder/lib/src/specs/expression/closure.dart @@ -9,7 +9,7 @@ Expression toClosure(Method method) { b.returns = null; b.types.clear(); }); - return new ClosureExpression._(withoutTypes); + return ClosureExpression._(withoutTypes); } class ClosureExpression extends Expression { diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 720ea37ba..5953f9de0 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -29,23 +29,23 @@ Expression literal(Object literal, {Expression onError(Object value)}) { if (onError != null) { return onError(literal); } - throw new UnsupportedError('Not a supported literal type: $literal.'); + throw UnsupportedError('Not a supported literal type: $literal.'); } /// Represents the literal value `true`. -const Expression literalTrue = const LiteralExpression._('true'); +const Expression literalTrue = LiteralExpression._('true'); /// Represents the literal value `false`. -const Expression literalFalse = const LiteralExpression._('false'); +const Expression literalFalse = LiteralExpression._('false'); /// Create a literal expression from a boolean [value]. Expression literalBool(bool value) => value ? literalTrue : literalFalse; /// Represents the literal value `null`. -const Expression literalNull = const LiteralExpression._('null'); +const Expression literalNull = LiteralExpression._('null'); /// Create a literal expression from a number [value]. -Expression literalNum(num value) => new LiteralExpression._('$value'); +Expression literalNum(num value) => LiteralExpression._('$value'); /// Create a literal expression from a string [value]. /// @@ -56,20 +56,20 @@ Expression literalNum(num value) => new LiteralExpression._('$value'); /// If [raw] is `false` escapes single quotes in the value. Expression literalString(String value, {bool raw = false}) { if (raw && value.contains('\'')) { - throw new ArgumentError('Cannot include a single quote in a raw string'); + throw ArgumentError('Cannot include a single quote in a raw string'); } final escaped = value.replaceAll('\'', '\\\''); - return new LiteralExpression._("${raw ? 'r' : ''}'$escaped'"); + return LiteralExpression._("${raw ? 'r' : ''}'$escaped'"); } /// Creates a literal list expression from [values]. LiteralListExpression literalList(Iterable values, [Reference type]) { - return new LiteralListExpression._(false, values.toList(), type); + return LiteralListExpression._(false, values.toList(), type); } /// Creates a literal `const` list expression from [values]. LiteralListExpression literalConstList(List values, [Reference type]) { - return new LiteralListExpression._(true, values, type); + return LiteralListExpression._(true, values, type); } /// Create a literal map expression from [values]. @@ -78,7 +78,7 @@ LiteralMapExpression literalMap( Reference keyType, Reference valueType, ]) { - return new LiteralMapExpression._(false, values, keyType, valueType); + return LiteralMapExpression._(false, values, keyType, valueType); } /// Create a literal `const` map expression from [values]. @@ -87,7 +87,7 @@ LiteralMapExpression literalConstMap( Reference keyType, Reference valueType, ]) { - return new LiteralMapExpression._(true, values, keyType, valueType); + return LiteralMapExpression._(true, values, keyType, valueType); } /// Represents a literal value in Dart source code. diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index 314ff7561..a04feb550 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -69,10 +69,10 @@ abstract class FieldBuilder extends Object FieldBuilder._(); @override - ListBuilder annotations = new ListBuilder(); + ListBuilder annotations = ListBuilder(); @override - ListBuilder docs = new ListBuilder(); + ListBuilder docs = ListBuilder(); /// Field assignment, if any. Code assignment; diff --git a/pkgs/code_builder/lib/src/specs/library.dart b/pkgs/code_builder/lib/src/specs/library.dart index 7f7b4976c..f47682809 100644 --- a/pkgs/code_builder/lib/src/specs/library.dart +++ b/pkgs/code_builder/lib/src/specs/library.dart @@ -32,6 +32,6 @@ abstract class LibraryBuilder implements Builder { factory LibraryBuilder() = _$LibraryBuilder; LibraryBuilder._(); - ListBuilder body = new ListBuilder(); - ListBuilder directives = new ListBuilder(); + ListBuilder body = ListBuilder(); + ListBuilder directives = ListBuilder(); } diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index c8f29c225..5fecfe3d1 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -26,7 +26,7 @@ abstract class Method extends Object factory Method([void updates(MethodBuilder b)]) = _$Method; factory Method.returnsVoid([void updates(MethodBuilder b)]) { - return new Method((b) { + return Method((b) { if (updates != null) { updates(b); } @@ -105,19 +105,19 @@ abstract class MethodBuilder extends Object MethodBuilder._(); @override - ListBuilder annotations = new ListBuilder(); + ListBuilder annotations = ListBuilder(); @override - ListBuilder docs = new ListBuilder(); + ListBuilder docs = ListBuilder(); @override - ListBuilder types = new ListBuilder(); + ListBuilder types = ListBuilder(); /// Optional parameters. - ListBuilder optionalParameters = new ListBuilder(); + ListBuilder optionalParameters = ListBuilder(); /// Required parameters. - ListBuilder requiredParameters = new ListBuilder(); + ListBuilder requiredParameters = ListBuilder(); /// Body of the method. Code body; @@ -216,13 +216,13 @@ abstract class ParameterBuilder extends Object bool toThis = false; @override - ListBuilder annotations = new ListBuilder(); + ListBuilder annotations = ListBuilder(); @override - ListBuilder docs = new ListBuilder(); + ListBuilder docs = ListBuilder(); @override - ListBuilder types = new ListBuilder(); + ListBuilder types = ListBuilder(); /// Type of the parameter; Reference type; diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 3a71f819c..1c0f79395 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -15,7 +15,7 @@ import 'type_reference.dart'; /// Short-hand for `new Reference(symbol, url)`. Reference refer(String symbol, [String url]) { - return new Reference(symbol, url); + return Reference(symbol, url); } /// A reference to [symbol], such as a class, or top-level method or field. @@ -55,7 +55,7 @@ class Reference extends Expression implements Spec { Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression.newOf( + return InvokeExpression.newOf( this, positionalArguments.toList(), namedArguments, @@ -71,7 +71,7 @@ class Reference extends Expression implements Spec { Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression.newOf( + return InvokeExpression.newOf( this, positionalArguments.toList(), namedArguments, @@ -86,7 +86,7 @@ class Reference extends Expression implements Spec { Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression.constOf( + return InvokeExpression.constOf( this, positionalArguments.toList(), namedArguments, @@ -102,7 +102,7 @@ class Reference extends Expression implements Spec { Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression.constOf( + return InvokeExpression.constOf( this, positionalArguments.toList(), namedArguments, @@ -113,7 +113,7 @@ class Reference extends Expression implements Spec { @override Expression get expression { - return new CodeExpression(new Code.scope((a) => a(this))); + return CodeExpression(Code.scope((a) => a(this))); } @override @@ -123,7 +123,7 @@ class Reference extends Expression implements Spec { .toString(); /// Returns as a [TypeReference], which allows adding generic type parameters. - Reference get type => new TypeReference((b) => b + Reference get type => TypeReference((b) => b ..url = url ..symbol = symbol); } diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index ed02440fe..2f1fb6f90 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -63,7 +63,7 @@ abstract class FunctionType extends Expression Map namedArguments = const {}, List typeArguments = const [], ]) => - throw new UnsupportedError('Cannot "new" a function type.'); + throw UnsupportedError('Cannot "new" a function type.'); @override Expression newInstanceNamed( @@ -72,7 +72,7 @@ abstract class FunctionType extends Expression Map namedArguments = const {}, List typeArguments = const [], ]) => - throw new UnsupportedError('Cannot "new" a function type.'); + throw UnsupportedError('Cannot "new" a function type.'); @override Expression constInstance( @@ -80,7 +80,7 @@ abstract class FunctionType extends Expression Map namedArguments = const {}, List typeArguments = const [], ]) => - throw new UnsupportedError('Cannot "const" a function type.'); + throw UnsupportedError('Cannot "const" a function type.'); @override Expression constInstanceNamed( @@ -89,7 +89,7 @@ abstract class FunctionType extends Expression Map namedArguments = const {}, List typeArguments = const [], ]) => - throw new UnsupportedError('Cannot "const" a function type.'); + throw UnsupportedError('Cannot "const" a function type.'); /// A typedef assignment to this type. Code toTypeDef(String name) => createTypeDef(name, this); @@ -105,12 +105,12 @@ abstract class FunctionTypeBuilder extends Object Reference returnType; @override - ListBuilder types = new ListBuilder(); + ListBuilder types = ListBuilder(); - ListBuilder requiredParameters = new ListBuilder(); + ListBuilder requiredParameters = ListBuilder(); - ListBuilder optionalParameters = new ListBuilder(); + ListBuilder optionalParameters = ListBuilder(); MapBuilder namedParameters = - new MapBuilder(); + MapBuilder(); } diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index 4eaa81c56..1f864f9c6 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -48,7 +48,7 @@ abstract class TypeReference extends Expression @override Expression get expression { - return new CodeExpression(new Code.scope((a) => a(this))); + return CodeExpression(Code.scope((a) => a(this))); } @override @@ -60,7 +60,7 @@ abstract class TypeReference extends Expression Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression.newOf( + return InvokeExpression.newOf( this, positionalArguments.toList(), namedArguments, @@ -76,7 +76,7 @@ abstract class TypeReference extends Expression Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression.newOf( + return InvokeExpression.newOf( this, positionalArguments.toList(), namedArguments, @@ -91,7 +91,7 @@ abstract class TypeReference extends Expression Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression.constOf( + return InvokeExpression.constOf( this, positionalArguments.toList(), namedArguments, @@ -107,7 +107,7 @@ abstract class TypeReference extends Expression Map namedArguments = const {}, List typeArguments = const [], ]) { - return new InvokeExpression.constOf( + return InvokeExpression.constOf( this, positionalArguments.toList(), namedArguments, @@ -132,5 +132,5 @@ abstract class TypeReferenceBuilder extends Object Reference bound; @override - ListBuilder types = new ListBuilder(); + ListBuilder types = ListBuilder(); } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 51097de30..a623814e1 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,12 +1,12 @@ name: code_builder -version: 3.1.2 +version: 3.1.3-dev description: A fluent API for generating Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=2.0.0-dev <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: built_collection: '>=1.0.0 <4.0.0' diff --git a/pkgs/code_builder/test/allocator_test.dart b/pkgs/code_builder/test/allocator_test.dart index 25ca1f401..09f135c56 100644 --- a/pkgs/code_builder/test/allocator_test.dart +++ b/pkgs/code_builder/test/allocator_test.dart @@ -14,12 +14,12 @@ void main() { Allocator allocator; test('should return the exact (non-prefixed) symbol', () { - allocator = new Allocator(); + allocator = Allocator(); expect(allocator.allocate(refer('Foo', 'package:foo')), 'Foo'); }); test('should collect import URLs', () { - allocator = new Allocator() + allocator = Allocator() ..allocate(refer('List', 'dart:core')) ..allocate(refer('LinkedHashMap', 'dart:collection')) ..allocate(refer('someSymbol')); @@ -36,7 +36,7 @@ void main() { }); test('.simplePrefixing should add import prefixes', () { - allocator = new Allocator.simplePrefixing(); + allocator = Allocator.simplePrefixing(); expect( allocator.allocate(refer('List', 'dart:core')), 'List', diff --git a/pkgs/code_builder/test/common.dart b/pkgs/code_builder/test/common.dart index de8dde16b..70a4a6600 100644 --- a/pkgs/code_builder/test/common.dart +++ b/pkgs/code_builder/test/common.dart @@ -5,7 +5,7 @@ import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; -final DartFormatter _dartfmt = new DartFormatter(); +final DartFormatter _dartfmt = DartFormatter(); String _format(String source) { try { return _dartfmt.format(source); diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index 9b45bbf61..16eb94276 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -16,18 +16,18 @@ void main() { final $Module = refer('Module', 'package:app/module.dart'); final $Thing = refer('Thing', 'package:app/thing.dart'); - final clazz = new ClassBuilder() + final clazz = ClassBuilder() ..name = 'Injector' ..implements.add($App) - ..fields.add(new Field((b) => b + ..fields.add(Field((b) => b ..modifier = FieldModifier.final$ ..name = '_module' ..type = $Module.type)) - ..constructors.add(new Constructor((b) => b - ..requiredParameters.add(new Parameter((b) => b + ..constructors.add(Constructor((b) => b + ..requiredParameters.add(Parameter((b) => b ..name = '_module' ..toThis = true)))) - ..methods.add(new Method((b) => b + ..methods.add(Method((b) => b ..name = 'getThing' ..body = $Thing.newInstance([ refer('_module').property('get1').call([]), @@ -61,7 +61,7 @@ void main() { @override _i3.Thing getThing() => new _i3.Thing(_module.get1(), _module.get2()); } - ''', new DartEmitter(new Allocator.simplePrefixing())), + ''', DartEmitter(Allocator.simplePrefixing())), ); }); } diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 872a5b931..28dbaf91f 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -12,7 +12,7 @@ void main() { test('should create a class', () { expect( - new Class((b) => b..name = 'Foo'), + Class((b) => b..name = 'Foo'), equalsDart(r''' class Foo {} '''), @@ -21,7 +21,7 @@ void main() { test('should create an abstract class', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' ..abstract = true), equalsDart(r''' @@ -32,7 +32,7 @@ void main() { test('should create a class with documentations', () { expect( - new Class( + Class( (b) => b ..name = 'Foo' ..docs.addAll( @@ -50,7 +50,7 @@ void main() { test('should create a class with annotations', () { expect( - new Class( + Class( (b) => b ..name = 'Foo' ..annotations.addAll([ @@ -68,7 +68,7 @@ void main() { test('should create a class with a generic type', () { expect( - new Class((b) => b + Class((b) => b ..name = 'List' ..types.add(refer('T'))), equalsDart(r''' @@ -79,7 +79,7 @@ void main() { test('should create a class with multiple generic types', () { expect( - new Class( + Class( (b) => b ..name = 'Map' ..types.addAll([ @@ -95,11 +95,11 @@ void main() { test('should create a class with a bound generic type', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Comparable' - ..types.add(new TypeReference((b) => b + ..types.add(TypeReference((b) => b ..symbol = 'T' - ..bound = new TypeReference((b) => b + ..bound = TypeReference((b) => b ..symbol = 'Comparable' ..types.add(refer('T').type))))), equalsDart(r''' @@ -110,9 +110,9 @@ void main() { test('should create a class extending another class', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..extend = new TypeReference((b) => b.symbol = 'Bar')), + ..extend = TypeReference((b) => b.symbol = 'Bar')), equalsDart(r''' class Foo extends Bar {} '''), @@ -121,10 +121,10 @@ void main() { test('should create a class mixing in another class', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..extend = new TypeReference((b) => b.symbol = 'Bar') - ..mixins.add(new TypeReference((b) => b.symbol = 'Foo'))), + ..extend = TypeReference((b) => b.symbol = 'Bar') + ..mixins.add(TypeReference((b) => b.symbol = 'Foo'))), equalsDart(r''' class Foo extends Bar with Foo {} '''), @@ -133,10 +133,10 @@ void main() { test('should create a class implementing another class', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..extend = new TypeReference((b) => b.symbol = 'Bar') - ..implements.add(new TypeReference((b) => b.symbol = 'Foo'))), + ..extend = TypeReference((b) => b.symbol = 'Bar') + ..implements.add(TypeReference((b) => b.symbol = 'Foo'))), equalsDart(r''' class Foo extends Bar implements Foo {} '''), @@ -145,9 +145,9 @@ void main() { test('should create a class with a constructor', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add(new Constructor())), + ..constructors.add(Constructor())), equalsDart(r''' class Foo { Foo(); @@ -158,11 +158,11 @@ void main() { test('should create a class with a constructor with initializers', () { expect( - new Class( + Class( (b) => b ..name = 'Foo' ..constructors.add( - new Constructor( + Constructor( (b) => b ..initializers.addAll([ const Code('a = 5'), @@ -181,10 +181,10 @@ void main() { test('should create a class with a annotated constructor', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add( - new Constructor((b) => b..annotations.add(refer('deprecated'))))), + ..constructors + .add(Constructor((b) => b..annotations.add(refer('deprecated'))))), equalsDart(r''' class Foo { @deprecated @@ -196,9 +196,9 @@ void main() { test('should create a class with a named constructor', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add(new Constructor((b) => b..name = 'named'))), + ..constructors.add(Constructor((b) => b..name = 'named'))), equalsDart(r''' class Foo { Foo.named(); @@ -209,9 +209,9 @@ void main() { test('should create a class with a const constructor', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add(new Constructor((b) => b..constant = true))), + ..constructors.add(Constructor((b) => b..constant = true))), equalsDart(r''' class Foo { const Foo(); @@ -222,9 +222,9 @@ void main() { test('should create a class with an external constructor', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add(new Constructor((b) => b..external = true))), + ..constructors.add(Constructor((b) => b..external = true))), equalsDart(r''' class Foo { external Foo(); @@ -235,9 +235,9 @@ void main() { test('should create a class with a factory constructor', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add(new Constructor((b) => b + ..constructors.add(Constructor((b) => b ..factory = true ..redirect = refer('_Foo')))), equalsDart(r''' @@ -250,9 +250,9 @@ void main() { test('should create a class with a factory lambda constructor', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add(new Constructor((b) => b + ..constructors.add(Constructor((b) => b ..factory = true ..lambda = true ..body = const Code('new _Foo()')))), @@ -266,9 +266,9 @@ void main() { test('should create a class with an implicit factory lambda constructor', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add(new Constructor((b) => b + ..constructors.add(Constructor((b) => b ..factory = true ..body = refer('_Foo').newInstance([]).code))), equalsDart(r''' @@ -281,9 +281,9 @@ void main() { test('should create a class with a constructor with a body', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add(new Constructor((b) => b + ..constructors.add(Constructor((b) => b ..factory = true ..body = const Code('return new _Foo();')))), equalsDart(r''' @@ -298,15 +298,15 @@ void main() { test('should create a class with method parameters', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add(new Constructor((b) => b + ..constructors.add(Constructor((b) => b ..requiredParameters.addAll([ - new Parameter((b) => b..name = 'a'), - new Parameter((b) => b..name = 'b'), + Parameter((b) => b..name = 'a'), + Parameter((b) => b..name = 'b'), ]) ..optionalParameters.addAll([ - new Parameter((b) => b + Parameter((b) => b ..name = 'c' ..named = true), ])))), @@ -320,19 +320,19 @@ void main() { test('should create a class with a constructor+field-formal parameters', () { expect( - new Class((b) => b + Class((b) => b ..name = 'Foo' - ..constructors.add(new Constructor((b) => b + ..constructors.add(Constructor((b) => b ..requiredParameters.addAll([ - new Parameter((b) => b + Parameter((b) => b ..name = 'a' ..toThis = true), - new Parameter((b) => b + Parameter((b) => b ..name = 'b' ..toThis = true), ]) ..optionalParameters.addAll([ - new Parameter((b) => b + Parameter((b) => b ..name = 'c' ..named = true ..toThis = true), diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index e6f2e6539..07adc3ae3 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -87,7 +87,7 @@ void main() { test('should emit a scoped type as an expression', () { expect( refer('Foo', 'package:foo/foo.dart'), - equalsDart('_i1.Foo', new DartEmitter(new Allocator.simplePrefixing())), + equalsDart('_i1.Foo', DartEmitter(Allocator.simplePrefixing())), ); }); @@ -200,21 +200,21 @@ void main() { test('should emit a function type', () { expect( - new FunctionType((b) => b.returnType = refer('void')), + FunctionType((b) => b.returnType = refer('void')), equalsDart('void Function()'), ); }); test('should emit a typedef statement', () { expect( - new FunctionType((b) => b.returnType = refer('void')).toTypeDef('Void0'), + FunctionType((b) => b.returnType = refer('void')).toTypeDef('Void0'), equalsDart('typedef Void0 = void Function();'), ); }); test('should emit a function type with type parameters', () { expect( - new FunctionType((b) => b + FunctionType((b) => b ..returnType = refer('T') ..types.add(refer('T'))), equalsDart('T Function()'), @@ -223,14 +223,14 @@ void main() { test('should emit a function type a single parameter', () { expect( - new FunctionType((b) => b..requiredParameters.add(refer('String'))), + FunctionType((b) => b..requiredParameters.add(refer('String'))), equalsDart('Function(String)'), ); }); test('should emit a function type with parameters', () { expect( - new FunctionType((b) => b + FunctionType((b) => b ..requiredParameters.add(refer('String')) ..optionalParameters.add(refer('int'))), equalsDart('Function(String, [int])'), @@ -239,7 +239,7 @@ void main() { test('should emit a function type with named parameters', () { expect( - new FunctionType((b) => b + FunctionType((b) => b ..namedParameters.addAll({ 'x': refer('int'), 'y': refer('int'), @@ -252,7 +252,7 @@ void main() { expect( refer('map').property('putIfAbsent').call([ literalString('foo'), - new Method((b) => b..body = literalTrue.code).closure, + Method((b) => b..body = literalTrue.code).closure, ]), equalsDart("map.putIfAbsent('foo', () => true)"), ); diff --git a/pkgs/code_builder/test/specs/code/statement_test.dart b/pkgs/code_builder/test/specs/code/statement_test.dart index a31d5565c..72ed6fe1a 100644 --- a/pkgs/code_builder/test/specs/code/statement_test.dart +++ b/pkgs/code_builder/test/specs/code/statement_test.dart @@ -12,7 +12,7 @@ void main() { test('should emit a block of code', () { expect( - new Block.of([ + Block.of([ const Code('if (foo) {'), const Code(' print(true);'), const Code('}'), @@ -27,7 +27,7 @@ void main() { test('should emit a block of code including expressions', () { expect( - new Block.of([ + Block.of([ const Code('if (foo) {'), refer('print')([literalTrue]).statement, const Code('}'), @@ -42,9 +42,9 @@ void main() { test('should emit a block of code with lazyily invoked generators', () { expect( - new Method((b) => b + Method((b) => b ..name = 'main' - ..body = new Block.of([ + ..body = Block.of([ const Code('if ('), lazyCode(() => refer('foo').code), const Code(') {'), diff --git a/pkgs/code_builder/test/specs/field_test.dart b/pkgs/code_builder/test/specs/field_test.dart index afda0b2f7..3a89d685c 100644 --- a/pkgs/code_builder/test/specs/field_test.dart +++ b/pkgs/code_builder/test/specs/field_test.dart @@ -12,7 +12,7 @@ void main() { test('should create a field', () { expect( - new Field((b) => b..name = 'foo'), + Field((b) => b..name = 'foo'), equalsDart(r''' var foo; '''), @@ -21,7 +21,7 @@ void main() { test('should create a typed field', () { expect( - new Field((b) => b + Field((b) => b ..name = 'foo' ..type = refer('String')), equalsDart(r''' @@ -32,7 +32,7 @@ void main() { test('should create a final field', () { expect( - new Field((b) => b + Field((b) => b ..name = 'foo' ..modifier = FieldModifier.final$), equalsDart(r''' @@ -43,7 +43,7 @@ void main() { test('should create a constant field', () { expect( - new Field((b) => b + Field((b) => b ..name = 'foo' ..modifier = FieldModifier.constant), equalsDart(r''' @@ -54,7 +54,7 @@ void main() { test('should create a field with an assignment', () { expect( - new Field((b) => b + Field((b) => b ..name = 'foo' ..assignment = const Code('1')), equalsDart(r''' diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index 29ef147ca..1e806a0fc 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -15,9 +15,9 @@ void main() { test('should emit a source file with manual imports', () { expect( - new Library((b) => b - ..directives.add(new Directive.import('dart:collection')) - ..body.add(new Field((b) => b + Library((b) => b + ..directives.add(Directive.import('dart:collection')) + ..body.add(Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ ..assignment = $LinkedHashMap.newInstance([]).code))), @@ -25,16 +25,16 @@ void main() { import 'dart:collection'; final test = new LinkedHashMap(); - ''', new DartEmitter()), + ''', DartEmitter()), ); }); test('should emit a source file with a deferred import', () { expect( - new Library( + Library( (b) => b ..directives.add( - new Directive.importDeferredAs( + Directive.importDeferredAs( 'package:foo/foo.dart', 'foo', ), @@ -48,10 +48,10 @@ void main() { test('should emit a source file with a "show" combinator', () { expect( - new Library( + Library( (b) => b ..directives.add( - new Directive.import( + Directive.import( 'package:foo/foo.dart', show: ['Foo', 'Bar'], ), @@ -65,10 +65,10 @@ void main() { test('should emit a source file with a "hide" combinator', () { expect( - new Library( + Library( (b) => b ..directives.add( - new Directive.import( + Directive.import( 'package:foo/foo.dart', hide: ['Foo', 'Bar'], ), @@ -82,33 +82,31 @@ void main() { test('should emit a source file with allocation', () { expect( - new Library((b) => b - ..body.add(new Field((b) => b + Library((b) => b + ..body.add(Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ - ..assignment = - new Code.scope((a) => 'new ${a($LinkedHashMap)}()')))), + ..assignment = Code.scope((a) => 'new ${a($LinkedHashMap)}()')))), equalsDart(r''' import 'dart:collection'; final test = new LinkedHashMap(); - ''', new DartEmitter(new Allocator())), + ''', DartEmitter(Allocator())), ); }); test('should emit a source file with allocation + prefixing', () { expect( - new Library((b) => b - ..body.add(new Field((b) => b + Library((b) => b + ..body.add(Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ - ..assignment = - new Code.scope((a) => 'new ${a($LinkedHashMap)}()')))), + ..assignment = Code.scope((a) => 'new ${a($LinkedHashMap)}()')))), equalsDart(r''' import 'dart:collection' as _i1; final test = new _i1.LinkedHashMap(); - ''', new DartEmitter(new Allocator.simplePrefixing())), + ''', DartEmitter(Allocator.simplePrefixing())), ); }); }); diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 9e87018c0..076356ea6 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -12,7 +12,7 @@ void main() { test('should create a method', () { expect( - new Method((b) => b..name = 'foo'), + Method((b) => b..name = 'foo'), equalsDart(r''' foo(); '''), @@ -21,7 +21,7 @@ void main() { test('should create an async method', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' ..modifier = MethodModifier.async ..body = literalNull.code), @@ -33,7 +33,7 @@ void main() { test('should create an async* method', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' ..modifier = MethodModifier.asyncStar ..body = literalNull.code), @@ -45,7 +45,7 @@ void main() { test('should create an sync* method', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' ..modifier = MethodModifier.syncStar ..body = literalNull.code), @@ -57,7 +57,7 @@ void main() { test('should create a lambda method implicitly', () { expect( - new Method((b) => b + Method((b) => b ..name = 'returnsTrue' ..returns = refer('bool') ..body = literalTrue.code), @@ -69,7 +69,7 @@ void main() { test('should create a normal method implicitly', () { expect( - new Method.returnsVoid((b) => b + Method.returnsVoid((b) => b ..name = 'assignTrue' ..body = refer('topLevelFoo').assign(literalTrue).statement), equalsDart(r''' @@ -82,7 +82,7 @@ void main() { test('should create a getter', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' ..external = true ..type = MethodType.getter), @@ -94,10 +94,10 @@ void main() { test('should create a setter', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' ..external = true - ..requiredParameters.add((new Parameter((b) => b..name = 'foo'))) + ..requiredParameters.add((Parameter((b) => b..name = 'foo'))) ..type = MethodType.setter), equalsDart(r''' external set foo(foo); @@ -107,7 +107,7 @@ void main() { test('should create a method with a return type', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' ..returns = refer('String')), equalsDart(r''' @@ -118,7 +118,7 @@ void main() { test('should create a method with a void return type', () { expect( - new Method.returnsVoid((b) => b..name = 'foo'), + Method.returnsVoid((b) => b..name = 'foo'), equalsDart(r''' void foo(); '''), @@ -127,9 +127,9 @@ void main() { test('should create a method with a function type return type', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' - ..returns = new FunctionType((b) => b + ..returns = FunctionType((b) => b ..returnType = refer('String') ..requiredParameters.addAll([ refer('int'), @@ -142,10 +142,10 @@ void main() { test('should create a method with a nested function type return type', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' - ..returns = new FunctionType((b) => b - ..returnType = new FunctionType((b) => b + ..returns = FunctionType((b) => b + ..returnType = FunctionType((b) => b ..returnType = refer('String') ..requiredParameters.add(refer('String'))) ..requiredParameters.addAll([ @@ -159,10 +159,10 @@ void main() { test('should create a method with a function type argument', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' - ..requiredParameters.add(new Parameter((b) => b - ..type = new FunctionType((b) => b + ..requiredParameters.add(Parameter((b) => b + ..type = FunctionType((b) => b ..returnType = refer('String') ..requiredParameters.add(refer('int'))) ..name = 'argument'))), @@ -173,11 +173,11 @@ void main() { test('should create a method with a nested function type argument', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' - ..requiredParameters.add(new Parameter((b) => b - ..type = new FunctionType((b) => b - ..returnType = new FunctionType((b) => b + ..requiredParameters.add(Parameter((b) => b + ..type = FunctionType((b) => b + ..returnType = FunctionType((b) => b ..returnType = refer('String') ..requiredParameters.add(refer('String'))) ..requiredParameters.add(refer('int'))) @@ -189,7 +189,7 @@ void main() { test('should create a method with generic types', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' ..types.add(refer('T'))), equalsDart(r''' @@ -200,7 +200,7 @@ void main() { test('should create an external method', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' ..external = true), equalsDart(r''' @@ -211,7 +211,7 @@ void main() { test('should create a method with a body', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' ..body = const Code('return 1+ 2;')), equalsDart(r''' @@ -224,7 +224,7 @@ void main() { test('should create a lambda method (explicitly)', () { expect( - new Method((b) => b + Method((b) => b ..name = 'foo' ..lambda = true ..body = const Code('1 + 2')), @@ -237,9 +237,9 @@ void main() { test('should create a method with a body with references', () { final $LinkedHashMap = refer('LinkedHashMap', 'dart:collection'); expect( - new Method((b) => b + Method((b) => b ..name = 'foo' - ..body = new Code.scope( + ..body = Code.scope( (a) => 'return new ${a($LinkedHashMap)}();', )), equalsDart(r''' @@ -252,11 +252,11 @@ void main() { test('should create a method with a paremter', () { expect( - new Method( + Method( (b) => b ..name = 'fib' ..requiredParameters.add( - new Parameter((b) => b.name = 'i'), + Parameter((b) => b.name = 'i'), ), ), equalsDart(r''' @@ -267,11 +267,11 @@ void main() { test('should create a method with an annotated parameter', () { expect( - new Method( + Method( (b) => b ..name = 'fib' ..requiredParameters.add( - new Parameter((b) => b + Parameter((b) => b ..name = 'i' ..annotations.add(refer('deprecated'))), ), @@ -284,11 +284,11 @@ void main() { test('should create a method with a parameter with a type', () { expect( - new Method( + Method( (b) => b ..name = 'fib' ..requiredParameters.add( - new Parameter( + Parameter( (b) => b ..name = 'i' ..type = refer('int').type, @@ -303,21 +303,21 @@ void main() { test('should create a method with a parameter with a generic type', () { expect( - new Method( + Method( (b) => b ..name = 'foo' - ..types.add(new TypeReference((b) => b + ..types.add(TypeReference((b) => b ..symbol = 'T' ..bound = refer('Iterable'))) ..requiredParameters.addAll([ - new Parameter( + Parameter( (b) => b ..name = 't' ..type = refer('T'), ), - new Parameter((b) => b + Parameter((b) => b ..name = 'x' - ..type = new TypeReference((b) => b + ..type = TypeReference((b) => b ..symbol = 'X' ..types.add(refer('T')))), ]), @@ -330,11 +330,11 @@ void main() { test('should create a method with an optional parameter', () { expect( - new Method( + Method( (b) => b ..name = 'fib' ..optionalParameters.add( - new Parameter((b) => b.name = 'i'), + Parameter((b) => b.name = 'i'), ), ), equalsDart(r''' @@ -345,12 +345,12 @@ void main() { test('should create a method with multiple optional parameters', () { expect( - new Method( + Method( (b) => b ..name = 'foo' ..optionalParameters.addAll([ - new Parameter((b) => b.name = 'a'), - new Parameter((b) => b.name = 'b'), + Parameter((b) => b.name = 'a'), + Parameter((b) => b.name = 'b'), ]), ), equalsDart(r''' @@ -361,11 +361,11 @@ void main() { test('should create a method with an optional parameter with a value', () { expect( - new Method( + Method( (b) => b ..name = 'fib' ..optionalParameters.add( - new Parameter((b) => b + Parameter((b) => b ..name = 'i' ..defaultTo = const Code('0')), ), @@ -378,11 +378,11 @@ void main() { test('should create a method with a named optional parameter', () { expect( - new Method( + Method( (b) => b ..name = 'fib' ..optionalParameters.add( - new Parameter((b) => b + Parameter((b) => b ..named = true ..name = 'i'), ), @@ -395,11 +395,11 @@ void main() { test('should create a method with a named optional parameter with value', () { expect( - new Method( + Method( (b) => b ..name = 'fib' ..optionalParameters.add( - new Parameter((b) => b + Parameter((b) => b ..named = true ..name = 'i' ..defaultTo = const Code('0')), @@ -413,14 +413,14 @@ void main() { test('should create a method with a mix of parameters', () { expect( - new Method( + Method( (b) => b ..name = 'foo' ..requiredParameters.add( - new Parameter((b) => b..name = 'a'), + Parameter((b) => b..name = 'a'), ) ..optionalParameters.add( - new Parameter((b) => b + Parameter((b) => b ..named = true ..name = 'b'), ), diff --git a/pkgs/code_builder/tool/src/builder.dart b/pkgs/code_builder/tool/src/builder.dart index 6b0b0989b..ff9581495 100644 --- a/pkgs/code_builder/tool/src/builder.dart +++ b/pkgs/code_builder/tool/src/builder.dart @@ -8,7 +8,7 @@ import 'package:source_gen/source_gen.dart'; /// Returns a [Builder] to generate `.g.dart` files for `built_value`. Builder builtValueBuilder(BuilderOptions _) { - return new PartBuilder([ + return PartBuilder([ const BuiltValueGenerator(), ], '.g.dart'); } From 722637da9a0a22cc6d3d2ee1228bd1501cbfbada Mon Sep 17 00:00:00 2001 From: Nicholas Shahan Date: Fri, 24 Aug 2018 17:42:10 -0700 Subject: [PATCH 125/271] Bump the dependency range for built_collection. (dart-lang/code_builder#228) Updated the lower bound based on running `pub downgrade`. --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index c2d9fe1f1..ef8464ab0 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.1.3-dev + +* Bump dependency on built_collection to include v4.0.0. + ## 3.1.2 * Set max SDK version to `<3.0.0`. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index a623814e1..97468c647 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -9,7 +9,7 @@ environment: sdk: '>=2.0.0 <3.0.0' dependencies: - built_collection: '>=1.0.0 <4.0.0' + built_collection: '>=3.0.0 <5.0.0' built_value: ^6.0.0 matcher: ^0.12.0 meta: ^1.0.5 From c7aa6457d5a141a8fa0d94ecba28794c982763d3 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 30 Aug 2018 14:48:57 -0700 Subject: [PATCH 126/271] Prepare to release 3.1.3. (dart-lang/code_builder#229) * Prepare to release 3.1.3. * Remove old file. --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index ef8464ab0..b0c247345 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.1.3-dev +## 3.1.3 * Bump dependency on built_collection to include v4.0.0. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 97468c647..8277ed040 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.1.3-dev +version: 3.1.3 description: A fluent API for generating Dart code author: Dart Team From 710e096a2faff23392c8771d5b8796c4d9b0657f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 11 Oct 2018 15:33:23 -0700 Subject: [PATCH 127/271] Small tweak to readme (dart-lang/code_builder#230) Add missing semicolon, use double-quote instead of character esacping --- pkgs/code_builder/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index d4bd2b022..87739bf85 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -25,7 +25,7 @@ void main() { ..extend = refer('Organism') ..methods.add(Method.returnsVoid((b) => b ..name = 'eat' - ..body = const Code('print(\'Yum\')')))); + ..body = const Code("print('Yum');")))); final emitter = DartEmitter(); print(DartFormatter().format('${animal.accept(emitter)}')); } From 29b0283fed6790af65630f680d7ff8683e508215 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 10 Dec 2018 11:06:42 -0800 Subject: [PATCH 128/271] Use `=` instead of `:` for default values (dart-lang/code_builder#233) Fixes dart-lang/code_builder#232 This follows the recommendations in Effective Dart. --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/lib/src/emitter.dart | 6 +----- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/method_test.dart | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index b0c247345..222ec9e0b 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.2.0 + +* Emit `=` instead of `:` for named parameter default values. + ## 3.1.3 * Bump dependency on built_collection to include v4.0.0. diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index e039d3ecb..9573067bc 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -441,11 +441,7 @@ class DartEmitter extends Object } output.write(spec.name); if (optional && spec.defaultTo != null) { - if (spec.named) { - output.write(': '); - } else { - output.write(' = '); - } + output.write(' = '); spec.defaultTo.accept(this, output); } } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 8277ed040..56b81b184 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.1.3 +version: 3.2.0 description: A fluent API for generating Dart code author: Dart Team diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 076356ea6..682d6704f 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -406,7 +406,7 @@ void main() { ), ), equalsDart(r''' - fib({i: 0}); + fib({i = 0}); '''), ); }); From 5347f14f1219aa568c1011ee3fff551bcc85d696 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 10 Dec 2018 12:20:11 -0800 Subject: [PATCH 129/271] Don't emit `new` keyword in generated code (dart-lang/code_builder#227) * Don't emit keyword in generated code Closes dart-lang/code_builder#220 * -dev.1 version --- pkgs/code_builder/CHANGELOG.md | 3 ++- pkgs/code_builder/lib/src/specs/expression.dart | 1 - pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/e2e/injection_test.dart | 4 ++-- pkgs/code_builder/test/specs/class_test.dart | 10 +++++----- .../test/specs/code/expression_test.dart | 12 ++++++------ pkgs/code_builder/test/specs/library_test.dart | 10 +++++----- pkgs/code_builder/test/specs/method_test.dart | 4 ++-- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 222ec9e0b..291f20464 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ -## 3.2.0 +## 3.2.0-alpha * Emit `=` instead of `:` for named parameter default values. +* The `new` keyword will not be used in generated code. ## 3.1.3 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 4c2571e70..bfac9a948 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -400,7 +400,6 @@ abstract class ExpressionEmitter implements ExpressionVisitor { output ??= StringBuffer(); switch (expression.type) { case InvokeExpressionType.newInstance: - output.write('new '); break; case InvokeExpressionType.constInstance: output.write('const '); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 56b81b184..ae47fb77e 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.2.0 +version: 3.2.0-alpha description: A fluent API for generating Dart code author: Dart Team diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index 16eb94276..741a69761 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -45,7 +45,7 @@ void main() { final Module _module; @override - Thing getThing() => new Thing(_module.get1(), _module.get2()); + Thing getThing() => Thing(_module.get1(), _module.get2()); } '''), ); @@ -59,7 +59,7 @@ void main() { final _i2.Module _module; @override - _i3.Thing getThing() => new _i3.Thing(_module.get1(), _module.get2()); + _i3.Thing getThing() => _i3.Thing(_module.get1(), _module.get2()); } ''', DartEmitter(Allocator.simplePrefixing())), ); diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 28dbaf91f..2b0698cfe 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -255,10 +255,10 @@ void main() { ..constructors.add(Constructor((b) => b ..factory = true ..lambda = true - ..body = const Code('new _Foo()')))), + ..body = const Code('_Foo()')))), equalsDart(r''' class Foo { - factory Foo() => new _Foo(); + factory Foo() => _Foo(); } '''), ); @@ -273,7 +273,7 @@ void main() { ..body = refer('_Foo').newInstance([]).code))), equalsDart(r''' class Foo { - factory Foo() => new _Foo(); + factory Foo() => _Foo(); } '''), ); @@ -285,11 +285,11 @@ void main() { ..name = 'Foo' ..constructors.add(Constructor((b) => b ..factory = true - ..body = const Code('return new _Foo();')))), + ..body = const Code('return _Foo();')))), equalsDart(r''' class Foo { factory Foo() { - return new _Foo(); + return _Foo(); } } '''), diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 07adc3ae3..89cd82ae0 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -69,14 +69,14 @@ void main() { refer('three'): 3, refer('Map').newInstance([]): null, }), - equalsDart(r"{1: 'one', 2: two, three: 3, new Map(): null}"), + equalsDart(r"{1: 'one', 2: two, three: 3, Map(): null}"), ); }); test('should emit a list of other literals and expressions', () { expect( literalList([[], true, null, refer('Map').newInstance([])]), - equalsDart('[[], true, null, new Map()]'), + equalsDart('[[], true, null, Map()]'), ); }); @@ -91,17 +91,17 @@ void main() { ); }); - test('should emit invoking new Type()', () { + test('should emit invoking Type()', () { expect( refer('Map').newInstance([]), - equalsDart('new Map()'), + equalsDart('Map()'), ); }); - test('should emit invoking new named constructor', () { + test('should emit invoking named constructor', () { expect( refer('Foo').newInstanceNamed('bar', []), - equalsDart('new Foo.bar()'), + equalsDart('Foo.bar()'), ); }); diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index 1e806a0fc..4000fdf19 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -24,7 +24,7 @@ void main() { equalsDart(r''' import 'dart:collection'; - final test = new LinkedHashMap(); + final test = LinkedHashMap(); ''', DartEmitter()), ); }); @@ -86,11 +86,11 @@ void main() { ..body.add(Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ - ..assignment = Code.scope((a) => 'new ${a($LinkedHashMap)}()')))), + ..assignment = Code.scope((a) => '${a($LinkedHashMap)}()')))), equalsDart(r''' import 'dart:collection'; - final test = new LinkedHashMap(); + final test = LinkedHashMap(); ''', DartEmitter(Allocator())), ); }); @@ -101,11 +101,11 @@ void main() { ..body.add(Field((b) => b ..name = 'test' ..modifier = FieldModifier.final$ - ..assignment = Code.scope((a) => 'new ${a($LinkedHashMap)}()')))), + ..assignment = Code.scope((a) => '${a($LinkedHashMap)}()')))), equalsDart(r''' import 'dart:collection' as _i1; - final test = new _i1.LinkedHashMap(); + final test = _i1.LinkedHashMap(); ''', DartEmitter(Allocator.simplePrefixing())), ); }); diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 682d6704f..cc6de2b5b 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -240,11 +240,11 @@ void main() { Method((b) => b ..name = 'foo' ..body = Code.scope( - (a) => 'return new ${a($LinkedHashMap)}();', + (a) => 'return ${a($LinkedHashMap)}();', )), equalsDart(r''' foo() { - return new LinkedHashMap(); + return LinkedHashMap(); } '''), ); From 98b7b3b51b62e473d21715afb541bd920e751e1c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 10 Dec 2018 13:32:36 -0800 Subject: [PATCH 130/271] Remove `new` from text references (dart-lang/code_builder#226) Update code in Doc comments and text references for Dart 2 style code. --- pkgs/code_builder/lib/src/specs/code.dart | 6 +++--- pkgs/code_builder/lib/src/specs/expression/literal.dart | 2 +- pkgs/code_builder/lib/src/specs/reference.dart | 2 +- pkgs/code_builder/lib/src/specs/type_function.dart | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index 6ff923c37..e14c1020c 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -31,10 +31,10 @@ abstract class Code implements Spec { /// Create a code based that may use a provided [Allocator] for scoping: /// /// ```dart - /// // Emits `new _i123.FooType()`, where `_i123` is the import prefix. + /// // Emits `_i123.FooType()`, where `_i123` is the import prefix. /// - /// new Code.scope((a) { - /// return 'new ${a.allocate(fooType)}()' + /// Code.scope((a) { + /// return '${a.allocate(fooType)}()' /// }); /// ``` const factory Code.scope( diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 5953f9de0..cb0522c75 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -92,7 +92,7 @@ LiteralMapExpression literalConstMap( /// Represents a literal value in Dart source code. /// -/// For example, `new LiteralExpression('null')` should emit `null`. +/// For example, `LiteralExpression('null')` should emit `null`. /// /// Some common literals and helpers are available as methods/fields: /// * [literal] diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 1c0f79395..102d33040 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -13,7 +13,7 @@ import 'code.dart'; import 'expression.dart'; import 'type_reference.dart'; -/// Short-hand for `new Reference(symbol, url)`. +/// Short-hand for `Reference(symbol, url)`. Reference refer(String symbol, [String url]) { return Reference(symbol, url); } diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index 2f1fb6f90..b7b9014bd 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -63,7 +63,7 @@ abstract class FunctionType extends Expression Map namedArguments = const {}, List typeArguments = const [], ]) => - throw UnsupportedError('Cannot "new" a function type.'); + throw UnsupportedError('Cannot instantiate a function type.'); @override Expression newInstanceNamed( @@ -72,7 +72,7 @@ abstract class FunctionType extends Expression Map namedArguments = const {}, List typeArguments = const [], ]) => - throw UnsupportedError('Cannot "new" a function type.'); + throw UnsupportedError('Cannot instantiate a function type.'); @override Expression constInstance( From 1f39c10d76a496b3df2a5602f6ed7e520f5caea7 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 14 Jan 2019 07:20:59 -0800 Subject: [PATCH 131/271] Update dev deps on build and build_runner (dart-lang/code_builder#235) --- pkgs/code_builder/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index ae47fb77e..ae8675daf 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -15,8 +15,8 @@ dependencies: meta: ^1.0.5 dev_dependencies: - build: ^0.12.0 - build_runner: ^0.10.0 + build: ^1.0.0 + build_runner: ^1.1.0 built_value_generator: ^6.0.0 dart_style: ^1.0.0 source_gen: ^0.9.0 From 0c96007514e99917319eccaa8c36126b20567bb3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 29 Jan 2019 12:55:00 -0800 Subject: [PATCH 132/271] Add an option in `DartEmitter` to order directives (dart-lang/code_builder#237) Fixes https://github.com/dart-lang/code_builder/issues/236 --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/emitter.dart | 61 +++++++++++++-- .../code_builder/lib/src/specs/directive.dart | 50 ++++++++++++- pkgs/code_builder/pubspec.yaml | 1 + pkgs/code_builder/test/direcive_test.dart | 75 +++++++++++++++++++ 5 files changed, 180 insertions(+), 8 deletions(-) create mode 100644 pkgs/code_builder/test/direcive_test.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 291f20464..dffe1dd59 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -2,6 +2,7 @@ * Emit `=` instead of `:` for named parameter default values. * The `new` keyword will not be used in generated code. +* Add an option in `DartEmitter` to order directives. ## 3.1.3 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 9573067bc..9e28270e3 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -50,14 +50,24 @@ class DartEmitter extends Object @override final Allocator allocator; + /// If directives should be ordered while emitting. + /// + /// Ordering rules follow the guidance in + /// [Effective Dart](https://www.dartlang.org/guides/language/effective-dart/style#ordering) + /// and the + /// [directives_ordering](http://dart-lang.github.io/linter/lints/directives_ordering.html) + /// lint. + final bool orderDirectives; + /// Creates a new instance of [DartEmitter]. /// /// May specify an [Allocator] to use for symbols, otherwise uses a no-op. - DartEmitter([this.allocator = Allocator.none]); + DartEmitter([this.allocator = Allocator.none, bool orderDirectives = false]) + : orderDirectives = orderDirectives ?? false; /// Creates a new instance of [DartEmitter] with simple automatic imports. - factory DartEmitter.scoped() { - return DartEmitter(Allocator.simplePrefixing()); + factory DartEmitter.scoped({bool orderDirectives = false}) { + return DartEmitter(Allocator.simplePrefixing(), orderDirectives); } static bool _isLambdaBody(Code code) => @@ -283,12 +293,25 @@ class DartEmitter extends Object body.write(';'); } } - // TODO: Allow some sort of logical ordering. - for (final directive in spec.directives) { - directive.accept(this, output); + + final directives = [] + ..addAll(spec.directives) + ..addAll(allocator.imports); + + if (orderDirectives) { + directives.sort(); } - for (final directive in allocator.imports) { + + Directive previous; + for (final directive in directives) { + if (_newLineBetween(orderDirectives, previous, directive)) { + // Note: dartfmt handles creating new lines between directives. + // 2 lines are written here. The first one comes after the previous + // directive `;`, the second is the empty line. + output..writeln()..writeln(); + } directive.accept(this, output); + previous = directive; } output.write(body); return output; @@ -479,3 +502,27 @@ class DartEmitter extends Object return output; } } + +/// Returns `true` if: +/// +/// * [ordered] is `true` +/// * [a] is non-`null` +/// * If there should be an empty line before [b] if it's emitted after [a]. +bool _newLineBetween(bool ordered, Directive a, Directive b) { + if (!ordered) return false; + if (a == null) return false; + + assert(b != null); + + // Put a line between imports and exports + if (a.type != b.type) return true; + + // Within exports, don't put in extra blank lines + if (a.type == DirectiveType.export) { + assert(b.type == DirectiveType.export); + return false; + } + + // Return `true` if the schemes for [a] and [b] are different + return !Uri.parse(a.url).isScheme(Uri.parse(b.url).scheme); +} diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart index cb6b3a20a..69e93ff94 100644 --- a/pkgs/code_builder/lib/src/specs/directive.dart +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:built_value/built_value.dart'; +import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; import '../base.dart'; @@ -11,7 +12,8 @@ import '../visitors.dart'; part 'directive.g.dart'; @immutable -abstract class Directive implements Built, Spec { +abstract class Directive + implements Built, Spec, Comparable { factory Directive([void updates(DirectiveBuilder b)]) = _$Directive; factory Directive.import( @@ -73,6 +75,9 @@ abstract class Directive implements Built, Spec { R context, ]) => visitor.visitDirective(this, context); + + @override + int compareTo(Directive other) => _compareDirectives(this, other); } abstract class DirectiveBuilder @@ -98,3 +103,46 @@ enum DirectiveType { import, export, } + +/// Sort import URIs represented by [a] and [b] to honor the +/// "Effective Dart" ordering rules which are enforced by the +/// `directives_ordering` lint. +/// +/// 1. `import`s before `export`s +/// 2. `dart:` +/// 3. `package:` +/// 4. relative +int _compareDirectives(Directive a, Directive b) { + // NOTE: using the fact that `import` is before `export` in the + // `DirectiveType` enum – which allows us to compare using `indexOf`. + var value = DirectiveType.values + .indexOf(a.type) + .compareTo(DirectiveType.values.indexOf(b.type)); + + if (value == 0) { + final uriA = Uri.parse(a.url); + final uriB = Uri.parse(b.url); + + if (uriA.hasScheme) { + if (uriB.hasScheme) { + // If both import URIs have schemes, compare them based on scheme + // `dart` will sort before `package` which is what we want + // schemes are case-insensitive, so compare accordingly + value = compareAsciiLowerCase(uriA.scheme, uriB.scheme); + } else { + value = -1; + } + } else if (uriB.hasScheme) { + value = 1; + } + + // If both schemes are the same, compare based on path + if (value == 0) { + value = compareAsciiLowerCase(uriA.path, uriB.path); + } + + assert((value == 0) == (a.url == b.url)); + } + + return value; +} diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index ae8675daf..6f4d08616 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -11,6 +11,7 @@ environment: dependencies: built_collection: '>=3.0.0 <5.0.0' built_value: ^6.0.0 + collection: ^1.14.0 matcher: ^0.12.0 meta: ^1.0.5 diff --git a/pkgs/code_builder/test/direcive_test.dart b/pkgs/code_builder/test/direcive_test.dart new file mode 100644 index 000000000..f5fcaa32c --- /dev/null +++ b/pkgs/code_builder/test/direcive_test.dart @@ -0,0 +1,75 @@ +// 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:test/test.dart'; + +import 'common.dart'; + +void main() { + useDartfmt(); + + final $LinkedHashMap = refer('LinkedHashMap', 'dart:collection'); + + final library = Library((b) => b + ..directives.add((Directive.export('../relative.dart'))) + ..directives.add((Directive.export('package:foo/foo.dart'))) + ..body.add(Field((b) => b + ..name = 'relativeRef' + ..modifier = FieldModifier.final$ + ..assignment = + refer('Relative', '../relative.dart').newInstance([]).code)) + ..body.add(Field((b) => b + ..name = 'pkgRefFoo' + ..modifier = FieldModifier.final$ + ..assignment = refer('Foo', 'package:foo/foo.dart').newInstance([]).code)) + ..body.add(Field((b) => b + ..name = 'pkgRefBar' + ..modifier = FieldModifier.final$ + ..assignment = refer('Bar', 'package:foo/bar.dart').newInstance([]).code)) + ..body.add(Field((b) => b + ..name = 'collectionRef' + ..modifier = FieldModifier.final$ + ..assignment = $LinkedHashMap.newInstance([]).code))); + + test('should emit a source file with imports in defined order', () { + expect( + library, + equalsDart(r''' + export '../relative.dart'; + export 'package:foo/foo.dart'; + import '../relative.dart' as _i1; + import 'package:foo/foo.dart' as _i2; + import 'package:foo/bar.dart' as _i3; + import 'dart:collection' as _i4; + + final relativeRef = _i1.Relative(); + final pkgRefFoo = _i2.Foo(); + final pkgRefBar = _i3.Bar(); + final collectionRef = _i4.LinkedHashMap();''', DartEmitter.scoped()), + ); + }); + + test('should emit a source file with ordered', () { + expect( + library, + equalsDart(r''' + import 'dart:collection' as _i4; + + import 'package:foo/bar.dart' as _i3; + import 'package:foo/foo.dart' as _i2; + + import '../relative.dart' as _i1; + + export 'package:foo/foo.dart'; + export '../relative.dart'; + + final relativeRef = _i1.Relative(); + final pkgRefFoo = _i2.Foo(); + final pkgRefBar = _i3.Bar(); + final collectionRef = _i4.LinkedHashMap();''', + DartEmitter.scoped(orderDirectives: true)), + ); + }); +} From cd48ebc1f6fb36301ae3dab35a487aa1f244ee14 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 30 Jan 2019 13:14:28 -0800 Subject: [PATCH 133/271] Omit extra const (dart-lang/code_builder#238) Fixes https://github.com/dart-lang/code_builder/issues/221 --- pkgs/code_builder/CHANGELOG.md | 4 + pkgs/code_builder/lib/src/emitter.dart | 4 +- .../lib/src/specs/expression.dart | 166 +++++++++++------- .../lib/src/specs/expression/binary.dart | 6 +- pkgs/code_builder/lib/src/specs/field.dart | 2 +- pkgs/code_builder/test/const_test.dart | 51 ++++++ 6 files changed, 166 insertions(+), 67 deletions(-) create mode 100644 pkgs/code_builder/test/const_test.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index dffe1dd59..37c8f3f63 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -2,7 +2,11 @@ * Emit `=` instead of `:` for named parameter default values. * The `new` keyword will not be used in generated code. +* The `const` keyword will be omitted when it can be inferred. * Add an option in `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.1.3 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 9e28270e3..95e13106c 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -276,7 +276,9 @@ class DartEmitter extends Object output.write(spec.name); if (spec.assignment != null) { output.write(' = '); - spec.assignment.accept(this, output); + startConstCode(spec.modifier == FieldModifier.constant, () { + spec.assignment.accept(this, output); + }); } output.writeln(';'); return output; diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index bfac9a948..793274893 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -264,6 +264,7 @@ abstract class Expression implements Spec { ), this, '$name =', + isConst: true, ); } @@ -287,7 +288,7 @@ abstract class Expression implements Spec { this, LiteralExpression._(name), '.', - false, + addSpace: false, ); } @@ -297,7 +298,7 @@ abstract class Expression implements Spec { this, LiteralExpression._(name), '?.', - false, + addSpace: false, ); } @@ -378,7 +379,9 @@ abstract class ExpressionEmitter implements ExpressionVisitor { if (expression.addSpace) { output.write(' '); } - expression.right.accept(this, output); + startConstCode(expression.isConst, () { + expression.right.accept(this, output); + }); return output; } @@ -398,37 +401,33 @@ abstract class ExpressionEmitter implements ExpressionVisitor { @override visitInvokeExpression(InvokeExpression expression, [StringSink output]) { output ??= StringBuffer(); - switch (expression.type) { - case InvokeExpressionType.newInstance: - break; - case InvokeExpressionType.constInstance: - output.write('const '); - break; - } - expression.target.accept(this, output); - if (expression.name != null) { - output..write('.')..write(expression.name); - } - if (expression.typeArguments.isNotEmpty) { - output.write('<'); - visitAll(expression.typeArguments, output, (type) { - type.accept(this, output); + return _writeConstExpression( + output, expression.type == InvokeExpressionType.constInstance, () { + expression.target.accept(this, output); + if (expression.name != null) { + output..write('.')..write(expression.name); + } + if (expression.typeArguments.isNotEmpty) { + output.write('<'); + visitAll(expression.typeArguments, output, (type) { + type.accept(this, output); + }); + output.write('>'); + } + output.write('('); + visitAll(expression.positionalArguments, output, (spec) { + spec.accept(this, output); }); - output.write('>'); - } - output.write('('); - visitAll(expression.positionalArguments, output, (spec) { - spec.accept(this, output); - }); - if (expression.positionalArguments.isNotEmpty && - expression.namedArguments.isNotEmpty) { - output.write(', '); - } - visitAll(expression.namedArguments.keys, output, (name) { - output..write(name)..write(': '); - expression.namedArguments[name].accept(this, output); + if (expression.positionalArguments.isNotEmpty && + expression.namedArguments.isNotEmpty) { + output.write(', '); + } + visitAll(expression.namedArguments.keys, output, (name) { + output..write(name)..write(': '); + expression.namedArguments[name].accept(this, output); + }); + return output..write(')'); }); - return output..write(')'); } @override @@ -445,25 +444,27 @@ abstract class ExpressionEmitter implements ExpressionVisitor { literal(literalOrSpec).accept(this, output); } + bool _withInConstExpression = false; + @override visitLiteralListExpression( LiteralListExpression expression, [ StringSink output, ]) { output ??= StringBuffer(); - if (expression.isConst) { - output.write('const '); - } - if (expression.type != null) { - output.write('<'); - expression.type.accept(this, output); - output.write('>'); - } - output.write('['); - visitAll(expression.values, output, (value) { - _acceptLiteral(value, output); + + return _writeConstExpression(output, expression.isConst, () { + if (expression.type != null) { + output.write('<'); + expression.type.accept(this, output); + output.write('>'); + } + output.write('['); + visitAll(expression.values, output, (value) { + _acceptLiteral(value, output); + }); + return output..write(']'); }); - return output..write(']'); } @override @@ -472,27 +473,66 @@ abstract class ExpressionEmitter implements ExpressionVisitor { StringSink output, ]) { output ??= StringBuffer(); - if (expression.isConst) { - output.write('const '); + return _writeConstExpression(output, expression.isConst, () { + if (expression.keyType != null) { + output.write('<'); + expression.keyType.accept(this, output); + output.write(', '); + if (expression.valueType == null) { + const Reference('dynamic', 'dart:core').accept(this, output); + } else { + expression.valueType.accept(this, output); + } + output.write('>'); + } + output.write('{'); + visitAll(expression.values.keys, output, (key) { + final value = expression.values[key]; + _acceptLiteral(key, output); + output.write(': '); + _acceptLiteral(value, output); + }); + return output..write('}'); + }); + } + + /// Executes [visit] within a context which may alter the output if [isConst] + /// is `true`. + /// + /// This allows constant expressions to omit the `const` keyword if they + /// are already within a constant expression. + void startConstCode( + bool isConst, + Null Function() visit, + ) { + final previousConstContext = _withInConstExpression; + if (isConst) { + _withInConstExpression = true; } - if (expression.keyType != null) { - output.write('<'); - expression.keyType.accept(this, output); - output.write(', '); - if (expression.valueType == null) { - const Reference('dynamic', 'dart:core').accept(this, output); - } else { - expression.valueType.accept(this, output); + + visit(); + _withInConstExpression = previousConstContext; + } + + /// Similar to [startConstCode], but handles writing `"const "` if [isConst] + /// is `true` and the invocation is not nested under other invocations where + /// [isConst] is true. + StringSink _writeConstExpression( + StringSink sink, + bool isConst, + StringSink Function() visitExpression, + ) { + final previousConstContext = _withInConstExpression; + if (isConst) { + if (!_withInConstExpression) { + sink.write('const '); } - output.write('>'); + _withInConstExpression = true; } - output.write('{'); - visitAll(expression.values.keys, output, (key) { - final value = expression.values[key]; - _acceptLiteral(key, output); - output.write(': '); - _acceptLiteral(value, output); - }); - return output..write('}'); + + final returnedSink = visitExpression(); + assert(identical(returnedSink, sink)); + _withInConstExpression = previousConstContext; + return sink; } } diff --git a/pkgs/code_builder/lib/src/specs/expression/binary.dart b/pkgs/code_builder/lib/src/specs/expression/binary.dart index aefd86dde..1f7e76e4d 100644 --- a/pkgs/code_builder/lib/src/specs/expression/binary.dart +++ b/pkgs/code_builder/lib/src/specs/expression/binary.dart @@ -10,13 +10,15 @@ class BinaryExpression extends Expression { final Expression right; final String operator; final bool addSpace; + final bool isConst; const BinaryExpression._( this.left, this.right, - this.operator, [ + this.operator, { this.addSpace = true, - ]); + this.isConst = false, + }); @override R accept(ExpressionVisitor visitor, [R context]) { diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index a04feb550..81c564003 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -2,8 +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:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; import '../base.dart'; diff --git a/pkgs/code_builder/test/const_test.dart b/pkgs/code_builder/test/const_test.dart new file mode 100644 index 000000000..b10cea0ef --- /dev/null +++ b/pkgs/code_builder/test/const_test.dart @@ -0,0 +1,51 @@ +// 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:test/test.dart'; + +import 'common.dart'; + +void main() { + useDartfmt(); + + final constMap = literalConstMap({ + 'list': literalConstList([]), + 'duration': refer('Duration').constInstance([]), + }); + + test('expression', () { + expect(constMap, equalsDart(r''' + const {'list': [], 'duration': Duration()}''')); + }); + + test('assignConst', () { + expect( + constMap.assignConst('constField'), + equalsDart(r''' + const constField = {'list': [], 'duration': Duration()}''', + DartEmitter.scoped()), + ); + }); + + final library = Library((b) => b + ..body.add(Field((b) => b + ..name = 'val1' + ..modifier = FieldModifier.constant + ..assignment = refer('ConstClass').constInstance([]).code)) + ..body.add(Field((b) => b + ..name = 'val2' + ..modifier = FieldModifier.constant + ..assignment = + refer('ConstClass').constInstanceNamed('other', []).code))); + + test('should emit a source file with imports in defined order', () { + expect( + library, + equalsDart(r''' + const val1 = ConstClass(); + const val2 = ConstClass.other();'''), + ); + }); +} From 32f4ae40cbb9302b2422f53ec8b7dbcb7d559422 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 30 Jan 2019 20:44:12 -0800 Subject: [PATCH 134/271] Add more to package description, prepare for v3.2.0 (dart-lang/code_builder#239) --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/README.md | 4 +--- pkgs/code_builder/pubspec.yaml | 5 +++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 37c8f3f63..a46204b26 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.2.0-alpha +## 3.2.0 * Emit `=` instead of `:` for named parameter default values. * The `new` keyword will not be used in generated code. diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 87739bf85..9d9f394a2 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -1,11 +1,9 @@ -# 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) [![Latest docs](https://img.shields.io/badge/dartdocs-latest-blue.svg)](https://www.dartdocs.org/documentation/code_builder/latest) [![Gitter chat](https://badges.gitter.im/dart-lang/build.svg)](https://gitter.im/dart-lang/build) -`code_builder` is a fluent Dart API for generating valid Dart source code. +A fluent, builder-based library for generating valid Dart code. ## Usage diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 6f4d08616..2cd03bd83 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,7 +1,8 @@ name: code_builder -version: 3.2.0-alpha +version: 3.2.0 -description: A fluent API for generating Dart code +description: >- + A fluent, builder-based library for generating valid Dart code author: Dart Team homepage: https://github.com/dart-lang/code_builder From 9911ba723d27c6ef0d09966593c967c1cb3f70a1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 12 Mar 2019 20:59:04 -0700 Subject: [PATCH 135/271] Test oldest support SDK on travis (dart-lang/code_builder#240) --- pkgs/code_builder/.travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index d206571e5..b0d393b8d 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -1,6 +1,8 @@ language: dart dart: - dev + - 2.0.0 + cache: directories: - $HOME/.pub-cache From 2cb55c6d145398d0a963da5310e6fe26d975c268 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 18 Jun 2019 10:37:57 -0700 Subject: [PATCH 136/271] Escape newlines in String literals (dart-lang/code_builder#242) Fixes dart-lang/code_builder#241 It is never sensible to write a single quoted string with a newline character, they should be written as `\n`. --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/lib/src/specs/expression/literal.dart | 4 ++-- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/code/expression_test.dart | 4 ++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index a46204b26..bcc5e1526 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.2.1 + +* Escape newlines in String literals. + ## 3.2.0 * Emit `=` instead of `:` for named parameter default values. diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index cb0522c75..1502a3282 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -53,12 +53,12 @@ Expression literalNum(num value) => LiteralExpression._('$value'); /// /// If [raw] is `true`, creates a raw String formatted `r''` and the /// value may not contain a single quote. -/// If [raw] is `false` escapes single quotes in the value. +/// Escapes single quotes and newlines in the value. Expression literalString(String value, {bool raw = false}) { if (raw && value.contains('\'')) { throw ArgumentError('Cannot include a single quote in a raw string'); } - final escaped = value.replaceAll('\'', '\\\''); + final escaped = value.replaceAll('\'', '\\\'').replaceAll('\n', '\\n'); return LiteralExpression._("${raw ? 'r' : ''}'$escaped'"); } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 2cd03bd83..7d27a7b4b 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.2.0 +version: 3.2.1 description: >- A fluent, builder-based library for generating valid Dart code diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 89cd82ae0..e788bdc88 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -30,6 +30,10 @@ void main() { expect(() => literalString(r"don't", raw: true), throwsArgumentError); }); + test('should escape a newline in a string', () { + expect(literalString('some\nthing'), equalsDart(r"'some\nthing'")); + }); + test('should emit a && expression', () { expect(literalTrue.and(literalFalse), equalsDart('true && false')); }); From 97c8010df263ba5d803b52b0c03c4a622f3d24a6 Mon Sep 17 00:00:00 2001 From: Rob Halff Date: Fri, 9 Aug 2019 01:16:11 +0200 Subject: [PATCH 137/271] Add support for literal sets (dart-lang/code_builder#244) --- pkgs/code_builder/lib/code_builder.dart | 2 + .../lib/src/specs/expression.dart | 22 ++++++++++ .../lib/src/specs/expression/literal.dart | 30 ++++++++++++++ .../test/specs/code/expression_test.dart | 41 ++++++++++++++++++- 4 files changed, 93 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 7ee6102f7..2be4733f2 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -30,6 +30,8 @@ export 'src/specs/expression.dart' literalBool, literalList, literalConstList, + literalSet, + literalConstSet, literalMap, literalConstMap, literalString, diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 793274893..fd2cbe25c 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -351,6 +351,7 @@ abstract class ExpressionVisitor implements SpecVisitor { T visitInvokeExpression(InvokeExpression expression, [T context]); T visitLiteralExpression(LiteralExpression expression, [T context]); T visitLiteralListExpression(LiteralListExpression expression, [T context]); + T visitLiteralSetExpression(LiteralSetExpression expression, [T context]); T visitLiteralMapExpression(LiteralMapExpression expression, [T context]); } @@ -467,6 +468,27 @@ abstract class ExpressionEmitter implements ExpressionVisitor { }); } + @override + visitLiteralSetExpression( + LiteralSetExpression expression, [ + StringSink output, + ]) { + output ??= StringBuffer(); + + return _writeConstExpression(output, expression.isConst, () { + if (expression.type != null) { + output.write('<'); + expression.type.accept(this, output); + output.write('>'); + } + output.write('{'); + visitAll(expression.values, output, (value) { + _acceptLiteral(value, output); + }); + return output..write('}'); + }); + } + @override visitLiteralMapExpression( LiteralMapExpression expression, [ diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 1502a3282..3021fa18c 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -20,6 +20,9 @@ Expression literal(Object literal, {Expression onError(Object value)}) { if (literal is List) { return literalList(literal); } + if (literal is Set) { + return literalSet(literal); + } if (literal is Map) { return literalMap(literal); } @@ -72,6 +75,16 @@ LiteralListExpression literalConstList(List values, [Reference type]) { return LiteralListExpression._(true, values, type); } +/// Creates a literal set expression from [values]. +LiteralSetExpression literalSet(Iterable values, [Reference type]) { + return LiteralSetExpression._(false, values.toSet(), type); +} + +/// Creates a literal `const` set expression from [values]. +LiteralSetExpression literalConstSet(Set values, [Reference type]) { + return LiteralSetExpression._(true, values, type); +} + /// Create a literal map expression from [values]. LiteralMapExpression literalMap( Map values, [ @@ -99,6 +112,7 @@ LiteralMapExpression literalConstMap( /// * [literalBool] and [literalTrue], [literalFalse] /// * [literalNull] /// * [literalList] and [literalConstList] +/// * [literalSet] and [literalConstSet] class LiteralExpression extends Expression { final String literal; @@ -129,6 +143,22 @@ class LiteralListExpression extends Expression { String toString() => '[${values.map(literal).join(', ')}]'; } +class LiteralSetExpression extends Expression { + final bool isConst; + final Set values; + final Reference type; + + const LiteralSetExpression._(this.isConst, this.values, this.type); + + @override + R accept(ExpressionVisitor visitor, [R context]) { + return visitor.visitLiteralSetExpression(this, context); + } + + @override + String toString() => '{${values.map(literal).join(', ')}}'; +} + class LiteralMapExpression extends Expression { final bool isConst; final Map values; diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index e788bdc88..e7efd4324 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -50,6 +50,21 @@ void main() { expect(literalList([], refer('int')), equalsDart('[]')); }); + test('should emit a set', () { + // ignore: prefer_collection_literals + expect(literalSet(Set()), equalsDart('{}')); + }); + + test('should emit a const set', () { + // ignore: prefer_collection_literals + expect(literalConstSet(Set()), equalsDart('const {}')); + }); + + test('should emit an explicitly typed set', () { + // ignore: prefer_collection_literals + expect(literalSet(Set(), refer('int')), equalsDart('{}')); + }); + test('should emit a map', () { expect(literalMap({}), equalsDart('{}')); }); @@ -79,8 +94,30 @@ void main() { test('should emit a list of other literals and expressions', () { expect( - literalList([[], true, null, refer('Map').newInstance([])]), - equalsDart('[[], true, null, Map()]'), + literalList([ + [], + // ignore: prefer_collection_literals + Set(), + true, + null, + refer('Map').newInstance([]) + ]), + equalsDart('[[], {}, true, null, Map()]'), + ); + }); + + test('should emit a set of other literals and expressions', () { + expect( + // ignore: prefer_collection_literals + literalSet([ + [], + // ignore: prefer_collection_literals + Set(), + true, + null, + refer('Map').newInstance([]) + ]), + equalsDart('{[], {}, true, null, Map()}'), ); }); From 03e8ad1f5ff7ff05dd9869c6915395a02d49f696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Z=C3=B6chbauer?= Date: Fri, 9 Aug 2019 01:16:33 +0200 Subject: [PATCH 138/271] fix redundant `,` in Function type (dart-lang/code_builder#231) optional positional or named parameters. --- pkgs/code_builder/lib/src/emitter.dart | 5 +- pkgs/code_builder/test/specs/method_test.dart | 60 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 95e13106c..d7a688f23 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -338,8 +338,9 @@ class DartEmitter extends Object visitAll(spec.requiredParameters, output, (spec) { spec.accept(this, output); }); - if (spec.optionalParameters.isNotEmpty || - spec.namedParameters.isNotEmpty && spec.requiredParameters.isNotEmpty) { + if (spec.requiredParameters.isNotEmpty && + (spec.optionalParameters.isNotEmpty || + spec.namedParameters.isNotEmpty)) { output.write(', '); } if (spec.optionalParameters.isNotEmpty) { diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index cc6de2b5b..4d2f87690 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -140,6 +140,66 @@ void main() { ); }); + test('should create a function type with an optional positional parameter', + () { + expect( + FunctionType((b) => b + ..returnType = refer('String') + ..optionalParameters.add(refer('int'))), + equalsDart(r''' + String Function([int]) + '''), + ); + }); + + test( + 'should create a function type with a required ' + 'and an optional positional parameter', () { + expect( + FunctionType((b) => b + ..returnType = refer('String') + ..requiredParameters.add(refer('int')) + ..optionalParameters.add(refer('int'))), + equalsDart(r''' + String Function(int, [int]) + '''), + ); + }); + + test('should create a function type without parameters', () { + expect( + FunctionType((b) => b..returnType = refer('String')), + equalsDart(r''' + String Function() + '''), + ); + }); + + test('should create a function type with an optional named parameter', () { + expect( + FunctionType((b) => b + ..returnType = refer('String') + ..namedParameters['named'] = refer('int')), + equalsDart(r''' + String Function({int named}) + '''), + ); + }); + + test( + 'should create a function type with a required ' + 'and an optional named parameter', () { + expect( + FunctionType((b) => b + ..returnType = refer('String') + ..requiredParameters.add(refer('int')) + ..namedParameters['named'] = refer('int')), + equalsDart(r''' + String Function(int, {int named}) + '''), + ); + }); + test('should create a method with a nested function type return type', () { expect( Method((b) => b From abebda3e01953c66382543feb6f824cbfb5274d0 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Thu, 8 Aug 2019 16:17:35 -0700 Subject: [PATCH 139/271] Update CHANGELOG.md --- pkgs/code_builder/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index bcc5e1526..f133b3423 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,6 @@ +* No longer emits redundant `,`s in `FunctionType`s. +* Added support for `literalSet` and `literalConstSet`. + ## 3.2.1 * Escape newlines in String literals. From e32d8711adfdd42e97af684e56c13ae77b8f9eef Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 24 Sep 2019 21:42:48 -0700 Subject: [PATCH 140/271] =?UTF-8?q?Remove=20visibleForTesting=20from=20con?= =?UTF-8?q?structor=20used=20in=20lib/src/specs/=E2=80=A6=20(dart-lang/cod?= =?UTF-8?q?e=5Fbuilder#246)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkgs/code_builder/lib/src/specs/expression/code.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/code_builder/lib/src/specs/expression/code.dart b/pkgs/code_builder/lib/src/specs/expression/code.dart index 026b859a4..7465448e7 100644 --- a/pkgs/code_builder/lib/src/specs/expression/code.dart +++ b/pkgs/code_builder/lib/src/specs/expression/code.dart @@ -10,7 +10,6 @@ class CodeExpression extends Expression { final Code code; /// **INTERNAL ONLY**: Used to wrap [Code] as an [Expression]. - @visibleForTesting const CodeExpression(this.code); @override From d5bb7490fbbeaad45dc31e298870cf02f8788f48 Mon Sep 17 00:00:00 2001 From: Dmytro Dashenkov Date: Thu, 7 Nov 2019 21:33:39 +0200 Subject: [PATCH 141/271] `OR` and `NOT` expressions (dart-lang/code_builder#249) * Introduce `Expression.or` and `Expression.negate` * Remove spaces from `negate` expressions * Add tests for `or` and `negate` expressions * Use `_empty` expression for `await` instead of a literal `await` as an expression * Bump version to 3.2.2 --- pkgs/code_builder/lib/src/specs/expression.dart | 17 +++++++++++++++-- pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 8 ++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index fd2cbe25c..cbbf6d4c1 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -28,6 +28,9 @@ part 'expression/literal.dart'; abstract class Expression implements Spec { const Expression(); + /// An empty expression. + static const _empty = CodeExpression(Code('')); + @override R accept(covariant ExpressionVisitor visitor, [R context]); @@ -44,6 +47,16 @@ abstract class Expression implements Spec { return BinaryExpression._(expression, other, '&&'); } + /// Returns the result of `this` `||` [other]. + Expression or(Expression other) { + return BinaryExpression._(expression, other, '||'); + } + + /// Returns the result of `!this`. + Expression negate() { + return BinaryExpression._(_empty, expression, '!', addSpace: false); + } + /// Returns the result of `this` `as` [other]. Expression asA(Expression other) { return CodeExpression(Block.of([ @@ -198,9 +211,9 @@ abstract class Expression implements Spec { /// This expression preceded by `await`. Expression get awaited { return BinaryExpression._( - const LiteralExpression._('await'), + _empty, this, - '', + 'await', ); } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 7d27a7b4b..e9d90d3a9 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.2.1 +version: 3.2.2 description: >- A fluent, builder-based library for generating valid Dart code diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index e7efd4324..79b04ccfd 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -38,6 +38,14 @@ void main() { expect(literalTrue.and(literalFalse), equalsDart('true && false')); }); + test('should emit a || expression', () { + expect(literalTrue.or(literalFalse), equalsDart('true || false')); + }); + + test('should emit a ! expression', () { + expect(literalTrue.negate(), equalsDart('!true')); + }); + test('should emit a list', () { expect(literalList([]), equalsDart('[]')); }); From 6e1a5439f49ac7e1bdfd739b6d3a9498d0eb27a4 Mon Sep 17 00:00:00 2001 From: Dmytro Dashenkov Date: Mon, 11 Nov 2019 20:46:33 +0200 Subject: [PATCH 142/271] Add CHANGELOG entry for 3.2.2 (dart-lang/code_builder#250) --- pkgs/code_builder/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index f133b3423..9f0b42eba 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,11 @@ * No longer emits redundant `,`s in `FunctionType`s. * Added support for `literalSet` and `literalConstSet`. +## 3.2.2 + +* Introduce `Expression.or` for boolean OR. +* Introduce `Expression.negate` for boolean NOT. + ## 3.2.1 * Escape newlines in String literals. From b6a581c30f7104c794ec879a7bd289b1a8bb07d5 Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Thu, 14 Nov 2019 12:12:53 -0800 Subject: [PATCH 143/271] Depend on latest built_value (dart-lang/code_builder#252) * Depend on latest built_value * update minimum sdk --- pkgs/code_builder/.travis.yml | 2 +- pkgs/code_builder/CHANGELOG.md | 3 +++ pkgs/code_builder/pubspec.yaml | 11 +++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index b0d393b8d..e415dd4aa 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: - dev - - 2.0.0 + - 2.1.0 cache: directories: diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 9f0b42eba..3f5fd9257 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,8 @@ +# 3.2.3 + * No longer emits redundant `,`s in `FunctionType`s. * Added support for `literalSet` and `literalConstSet`. +* Depend on the latest `package:built_value`. ## 3.2.2 diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index e9d90d3a9..4ec32e7b3 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.2.2 +version: 3.2.3 description: >- A fluent, builder-based library for generating valid Dart code @@ -7,11 +7,11 @@ author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.1.0 <3.0.0' dependencies: built_collection: '>=3.0.0 <5.0.0' - built_value: ^6.0.0 + built_value: ^7.0.0 collection: ^1.14.0 matcher: ^0.12.0 meta: ^1.0.5 @@ -19,7 +19,10 @@ dependencies: dev_dependencies: build: ^1.0.0 build_runner: ^1.1.0 - built_value_generator: ^6.0.0 + built_value_generator: ^7.0.0 dart_style: ^1.0.0 source_gen: ^0.9.0 test: ^1.3.0 + +dependency_overrides: + built_value: ^7.0.0 From c98e3154f1a5cc62b8a745e297a01265f4a3cbc9 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 14 Nov 2019 12:25:35 -0800 Subject: [PATCH 144/271] Go back to version 3.2.1 (dart-lang/code_builder#253) The latest published is 3.2.0 --- pkgs/code_builder/CHANGELOG.md | 14 ++++---------- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 3f5fd9257..6f2abf0a3 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,18 +1,12 @@ -# 3.2.3 +## 3.2.1 +* Escape newlines in String literals. +* Introduce `Expression.or` for boolean OR. +* Introduce `Expression.negate` for boolean NOT. * No longer emits redundant `,`s in `FunctionType`s. * Added support for `literalSet` and `literalConstSet`. * Depend on the latest `package:built_value`. -## 3.2.2 - -* Introduce `Expression.or` for boolean OR. -* Introduce `Expression.negate` for boolean NOT. - -## 3.2.1 - -* Escape newlines in String literals. - ## 3.2.0 * Emit `=` instead of `:` for named parameter default values. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 4ec32e7b3..3072a81f6 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.2.3 +version: 3.2.1 description: >- A fluent, builder-based library for generating valid Dart code From a237438c29a0e20fe158e8ea5f178529d0f5db9d Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 6 Dec 2019 16:09:46 -0800 Subject: [PATCH 145/271] Fix newly enforced package:pedantic lints (dart-lang/code_builder#255) - prefer_collection_literals Upgrade min SDK to 2.2.0 to allow Set literals. --- pkgs/code_builder/.travis.yml | 2 +- pkgs/code_builder/lib/src/allocator.dart | 2 +- pkgs/code_builder/pubspec.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index e415dd4aa..34073cd49 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: - dev - - 2.1.0 + - 2.2.0 cache: directories: diff --git a/pkgs/code_builder/lib/src/allocator.dart b/pkgs/code_builder/lib/src/allocator.dart index 87315d5ab..dad9d7786 100644 --- a/pkgs/code_builder/lib/src/allocator.dart +++ b/pkgs/code_builder/lib/src/allocator.dart @@ -46,7 +46,7 @@ abstract class Allocator { } class _Allocator implements Allocator { - final _imports = Set(); + final _imports = {}; @override String allocate(Reference reference) { diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 3072a81f6..a99653c44 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.2.1 +version: 3.2.2-dev description: >- A fluent, builder-based library for generating valid Dart code @@ -7,7 +7,7 @@ author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=2.1.0 <3.0.0' + sdk: '>=2.2.0 <3.0.0' dependencies: built_collection: '>=3.0.0 <5.0.0' From 783982a0729d07971493313302978a4636de363a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 18 Feb 2020 09:52:05 -0800 Subject: [PATCH 146/271] Enable and fix pedantic lints (dart-lang/code_builder#267) * Enable and fix pedantic lints Re-ran code generation Bumped min SDK to allow new collection literal features Cleaned up .travis.yml file * bump SDK 2.6 --- pkgs/code_builder/.travis.yml | 24 ++--- pkgs/code_builder/CHANGELOG.md | 4 + pkgs/code_builder/analysis_options.yaml | 25 +----- pkgs/code_builder/lib/src/emitter.dart | 33 +++---- pkgs/code_builder/lib/src/specs/class.dart | 2 +- pkgs/code_builder/lib/src/specs/class.g.dart | 64 +++++++------ pkgs/code_builder/lib/src/specs/code.dart | 17 ++-- pkgs/code_builder/lib/src/specs/code.g.dart | 30 +++---- .../lib/src/specs/constructor.dart | 3 +- .../lib/src/specs/constructor.g.dart | 53 +++++------ .../code_builder/lib/src/specs/directive.dart | 2 +- .../lib/src/specs/directive.g.dart | 47 +++++----- .../lib/src/specs/expression.dart | 24 +++-- .../lib/src/specs/expression/literal.dart | 2 +- pkgs/code_builder/lib/src/specs/field.dart | 2 +- pkgs/code_builder/lib/src/specs/field.g.dart | 46 +++++----- pkgs/code_builder/lib/src/specs/library.dart | 2 +- .../code_builder/lib/src/specs/library.g.dart | 36 ++++---- pkgs/code_builder/lib/src/specs/method.dart | 6 +- pkgs/code_builder/lib/src/specs/method.g.dart | 90 +++++++++++-------- .../lib/src/specs/type_function.dart | 2 +- .../lib/src/specs/type_function.g.dart | 40 ++++----- .../lib/src/specs/type_reference.dart | 2 +- .../lib/src/specs/type_reference.g.dart | 34 ++++--- pkgs/code_builder/pubspec.yaml | 6 +- 25 files changed, 300 insertions(+), 296 deletions(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index 34073cd49..342584ece 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -1,23 +1,17 @@ language: dart + dart: - dev - - 2.2.0 + - 2.6.0 -cache: - directories: - - $HOME/.pub-cache - -dist: trusty -addons: - chrome: stable +dart_task: +- test +- dartanalyzer: --fatal-infos --fatal-warnings . +- dartfmt branches: only: [master] -# TODO: Give up the dream of running with dartdevc until... -# https://github.com/dart-lang/sdk/issues/31280 - -dart_task: - - test: --platform vm - - dartanalyzer - - dartfmt +cache: + directories: + - $HOME/.pub-cache diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 6f2abf0a3..b53f90733 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.2.2 + +* Require minimum Dart SDK of `2.6.0`. + ## 3.2.1 * Escape newlines in String literals. diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml index b4b37b47b..7b57d5c9a 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/analysis_options.yaml @@ -1,3 +1,5 @@ +include: package:pedantic/analysis_options.yaml + analyzer: strong-mode: implicit-casts: false @@ -6,7 +8,6 @@ analyzer: linter: rules: # Error Rules - - avoid_empty_else - comment_references - control_flow_in_finally - empty_statements @@ -15,41 +16,19 @@ linter: - iterable_contains_unrelated_type - list_remove_unrelated_type - no_adjacent_strings_in_list - - no_duplicate_case_values - test_types_in_equals - throw_in_finally - - unrelated_type_equality_checks - - valid_regexps # Style Rules - - annotate_overrides - - avoid_init_to_null - - avoid_return_types_on_setters - camel_case_types - cascade_invocations - constant_identifier_names - directives_ordering - - empty_catches - - empty_constructor_bodies - implementation_imports - - library_names - - library_prefixes - non_constant_identifier_names - - omit_local_variable_types - only_throw_errors - - prefer_adjacent_string_concatenation - - prefer_collection_literals - prefer_const_constructors - - prefer_contains - - prefer_equal_for_default_values - - prefer_final_fields - prefer_final_locals - prefer_initializing_formals - prefer_interpolation_to_compose_strings - - prefer_is_empty - - prefer_is_not_empty - - recursive_getters - - slash_for_doc_comments - - type_init_formals - unnecessary_brace_in_string_interps - - unnecessary_this diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index d7a688f23..f5ae995c6 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -25,7 +25,7 @@ import 'visitors.dart'; StringSink visitAll( Iterable elements, StringSink output, - void visit(T element), [ + void Function(T) visit, [ String separator = ', ', ]) { // Basically, this whole method is an improvement on @@ -83,7 +83,7 @@ class DartEmitter extends Object constructor.factory && _isLambdaBody(constructor.body); @override - visitAnnotation(Expression spec, [StringSink output]) { + StringSink visitAnnotation(Expression spec, [StringSink output]) { (output ??= StringBuffer()).write('@'); spec.accept(this, output); output.write(' '); @@ -91,7 +91,7 @@ class DartEmitter extends Object } @override - visitClass(Class spec, [StringSink output]) { + StringSink visitClass(Class spec, [StringSink output]) { output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); @@ -137,7 +137,8 @@ class DartEmitter extends Object } @override - visitConstructor(Constructor spec, String clazz, [StringSink output]) { + StringSink visitConstructor(Constructor spec, String clazz, + [StringSink output]) { output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); @@ -221,7 +222,7 @@ class DartEmitter extends Object } @override - visitDirective(Directive spec, [StringSink output]) { + StringSink visitDirective(Directive spec, [StringSink output]) { output ??= StringBuffer(); if (spec.type == DirectiveType.import) { output.write('import '); @@ -249,7 +250,7 @@ class DartEmitter extends Object } @override - visitField(Field spec, [StringSink output]) { + StringSink visitField(Field spec, [StringSink output]) { output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); @@ -285,7 +286,7 @@ class DartEmitter extends Object } @override - visitLibrary(Library spec, [StringSink output]) { + StringSink visitLibrary(Library spec, [StringSink output]) { output ??= StringBuffer(); // Process the body first in order to prime the allocators. final body = StringBuffer(); @@ -296,9 +297,7 @@ class DartEmitter extends Object } } - final directives = [] - ..addAll(spec.directives) - ..addAll(allocator.imports); + final directives = [...spec.directives, ...allocator.imports]; if (orderDirectives) { directives.sort(); @@ -320,7 +319,7 @@ class DartEmitter extends Object } @override - visitFunctionType(FunctionType spec, [StringSink output]) { + StringSink visitFunctionType(FunctionType spec, [StringSink output]) { output ??= StringBuffer(); if (spec.returnType != null) { spec.returnType.accept(this, output); @@ -361,7 +360,7 @@ class DartEmitter extends Object } @override - visitMethod(Method spec, [StringSink output]) { + StringSink visitMethod(Method spec, [StringSink output]) { output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); @@ -473,15 +472,16 @@ class DartEmitter extends Object } @override - visitReference(Reference spec, [StringSink output]) { + StringSink visitReference(Reference spec, [StringSink output]) { return (output ??= StringBuffer())..write(allocator.allocate(spec)); } @override - visitSpec(Spec spec, [StringSink output]) => spec.accept(this, output); + StringSink visitSpec(Spec spec, [StringSink output]) => + spec.accept(this, output); @override - visitType(TypeReference spec, [StringSink output]) { + StringSink visitType(TypeReference spec, [StringSink output]) { output ??= StringBuffer(); // Intentionally not .accept to avoid stack overflow. visitReference(spec, output); @@ -494,7 +494,8 @@ class DartEmitter extends Object } @override - visitTypeParameters(Iterable specs, [StringSink output]) { + StringSink visitTypeParameters(Iterable specs, + [StringSink output]) { output ??= StringBuffer(); if (specs.isNotEmpty) { output diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart index 3e596a605..77175f23a 100644 --- a/pkgs/code_builder/lib/src/specs/class.dart +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -23,7 +23,7 @@ part 'class.g.dart'; abstract class Class extends Object with HasAnnotations, HasDartDocs, HasGenerics implements Built, Spec { - factory Class([void updates(ClassBuilder b)]) = _$Class; + factory Class([void Function(ClassBuilder) updates]) = _$Class; Class._(); diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index 68cff19b4..916b96bc5 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -6,16 +6,6 @@ part of 'class.dart'; // BuiltValueGenerator // ************************************************************************** -// ignore_for_file: always_put_control_body_on_new_line -// ignore_for_file: annotate_overrides -// ignore_for_file: avoid_annotating_with_dynamic -// ignore_for_file: avoid_catches_without_on_clauses -// ignore_for_file: avoid_returning_this -// ignore_for_file: lines_longer_than_80_chars -// ignore_for_file: omit_local_variable_types -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - class _$Class extends Class { @override final bool abstract; @@ -40,7 +30,7 @@ class _$Class extends Class { @override final String name; - factory _$Class([void updates(ClassBuilder b)]) => + factory _$Class([void Function(ClassBuilder) updates]) => (new ClassBuilder()..update(updates)).build() as _$Class; _$Class._( @@ -56,34 +46,50 @@ class _$Class extends Class { this.fields, this.name}) : super._() { - if (abstract == null) + if (abstract == null) { throw new BuiltValueNullFieldError('Class', 'abstract'); - if (annotations == null) + } + if (annotations == null) { throw new BuiltValueNullFieldError('Class', 'annotations'); - if (docs == null) throw new BuiltValueNullFieldError('Class', 'docs'); - if (implements == null) + } + if (docs == null) { + throw new BuiltValueNullFieldError('Class', 'docs'); + } + if (implements == null) { throw new BuiltValueNullFieldError('Class', 'implements'); - if (mixins == null) throw new BuiltValueNullFieldError('Class', 'mixins'); - if (types == null) throw new BuiltValueNullFieldError('Class', 'types'); - if (constructors == null) + } + if (mixins == null) { + throw new BuiltValueNullFieldError('Class', 'mixins'); + } + if (types == null) { + throw new BuiltValueNullFieldError('Class', 'types'); + } + if (constructors == null) { throw new BuiltValueNullFieldError('Class', 'constructors'); - if (methods == null) throw new BuiltValueNullFieldError('Class', 'methods'); - if (fields == null) throw new BuiltValueNullFieldError('Class', 'fields'); - if (name == null) throw new BuiltValueNullFieldError('Class', 'name'); + } + if (methods == null) { + throw new BuiltValueNullFieldError('Class', 'methods'); + } + if (fields == null) { + throw new BuiltValueNullFieldError('Class', 'fields'); + } + if (name == null) { + throw new BuiltValueNullFieldError('Class', 'name'); + } } @override - Class rebuild(void updates(ClassBuilder b)) => + Class rebuild(void Function(ClassBuilder) updates) => (toBuilder()..update(updates)).build(); @override _$ClassBuilder toBuilder() => new _$ClassBuilder()..replace(this); @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (identical(other, this)) return true; - if (other is! Class) return false; - return abstract == other.abstract && + return other is Class && + abstract == other.abstract && annotations == other.annotations && docs == other.docs && extend == other.extend && @@ -295,12 +301,14 @@ class _$ClassBuilder extends ClassBuilder { @override void replace(Class other) { - if (other == null) throw new ArgumentError.notNull('other'); + if (other == null) { + throw new ArgumentError.notNull('other'); + } _$v = other as _$Class; } @override - void update(void updates(ClassBuilder b)) { + void update(void Function(ClassBuilder) updates) { if (updates != null) updates(this); } @@ -351,3 +359,5 @@ class _$ClassBuilder extends ClassBuilder { return _$result; } } + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index e14c1020c..4ebabd104 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -2,15 +2,14 @@ // 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:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; import '../allocator.dart'; import '../base.dart'; import '../emitter.dart'; import '../visitors.dart'; - import 'expression.dart'; import 'reference.dart'; @@ -19,7 +18,7 @@ part 'code.g.dart'; /// Returns a scoped symbol to [Reference], with an import prefix if needed. /// /// This is short-hand for [Allocator.allocate] in most implementations. -typedef String Allocate(Reference reference); +typedef Allocate = String Function(Reference); /// Represents arbitrary Dart code (either expressions or statements). /// @@ -38,7 +37,7 @@ abstract class Code implements Spec { /// }); /// ``` const factory Code.scope( - String Function(Allocate allocate) scope, + String Function(Allocate) scope, ) = ScopedCode._; @override @@ -47,7 +46,7 @@ abstract class Code implements Spec { /// Represents blocks of statements of Dart code. abstract class Block implements Built, Code, Spec { - factory Block([void updates(BlockBuilder b)]) = _$Block; + factory Block([void Function(BlockBuilder) updates]) = _$Block; factory Block.of(Iterable statements) { return Block((b) => b..statements.addAll(statements)); @@ -83,7 +82,9 @@ abstract class BlockBuilder implements Builder { /// **INTERNAL ONLY**. abstract class CodeVisitor implements SpecVisitor { T visitBlock(Block code, [T context]); + T visitStaticCode(StaticCode code, [T context]); + T visitScopedCode(ScopedCode code, [T context]); } @@ -93,7 +94,7 @@ abstract class CodeEmitter implements CodeVisitor { Allocator get allocator; @override - visitBlock(Block block, [StringSink output]) { + StringSink visitBlock(Block block, [StringSink output]) { output ??= StringBuffer(); return visitAll(block.statements, output, (statement) { statement.accept(this, output); @@ -101,13 +102,13 @@ abstract class CodeEmitter implements CodeVisitor { } @override - visitStaticCode(StaticCode code, [StringSink output]) { + StringSink visitStaticCode(StaticCode code, [StringSink output]) { output ??= StringBuffer(); return output..write(code.code); } @override - visitScopedCode(ScopedCode code, [StringSink output]) { + StringSink visitScopedCode(ScopedCode code, [StringSink output]) { output ??= StringBuffer(); return output..write(code.code(allocator.allocate)); } diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart index 5243ec82f..63a6eab18 100644 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -6,40 +6,30 @@ part of 'code.dart'; // BuiltValueGenerator // ************************************************************************** -// ignore_for_file: always_put_control_body_on_new_line -// ignore_for_file: annotate_overrides -// ignore_for_file: avoid_annotating_with_dynamic -// ignore_for_file: avoid_catches_without_on_clauses -// ignore_for_file: avoid_returning_this -// ignore_for_file: lines_longer_than_80_chars -// ignore_for_file: omit_local_variable_types -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - class _$Block extends Block { @override final BuiltList statements; - factory _$Block([void updates(BlockBuilder b)]) => + factory _$Block([void Function(BlockBuilder) updates]) => (new BlockBuilder()..update(updates)).build() as _$Block; _$Block._({this.statements}) : super._() { - if (statements == null) + if (statements == null) { throw new BuiltValueNullFieldError('Block', 'statements'); + } } @override - Block rebuild(void updates(BlockBuilder b)) => + Block rebuild(void Function(BlockBuilder) updates) => (toBuilder()..update(updates)).build(); @override _$BlockBuilder toBuilder() => new _$BlockBuilder()..replace(this); @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (identical(other, this)) return true; - if (other is! Block) return false; - return statements == other.statements; + return other is Block && statements == other.statements; } @override @@ -81,12 +71,14 @@ class _$BlockBuilder extends BlockBuilder { @override void replace(Block other) { - if (other == null) throw new ArgumentError.notNull('other'); + if (other == null) { + throw new ArgumentError.notNull('other'); + } _$v = other as _$Block; } @override - void update(void updates(BlockBuilder b)) { + void update(void Function(BlockBuilder) updates) { if (updates != null) updates(this); } @@ -110,3 +102,5 @@ class _$BlockBuilder extends BlockBuilder { return _$result; } } + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/constructor.dart b/pkgs/code_builder/lib/src/specs/constructor.dart index 04fcc709f..fb9f68932 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.dart @@ -19,7 +19,8 @@ part 'constructor.g.dart'; abstract class Constructor extends Object with HasAnnotations, HasDartDocs implements Built { - factory Constructor([void updates(ConstructorBuilder b)]) = _$Constructor; + factory Constructor([void Function(ConstructorBuilder) updates]) = + _$Constructor; Constructor._(); diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index efc08f267..0f803d9f3 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -6,16 +6,6 @@ part of 'constructor.dart'; // BuiltValueGenerator // ************************************************************************** -// ignore_for_file: always_put_control_body_on_new_line -// ignore_for_file: annotate_overrides -// ignore_for_file: avoid_annotating_with_dynamic -// ignore_for_file: avoid_catches_without_on_clauses -// ignore_for_file: avoid_returning_this -// ignore_for_file: lines_longer_than_80_chars -// ignore_for_file: omit_local_variable_types -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - class _$Constructor extends Constructor { @override final BuiltList annotations; @@ -42,7 +32,7 @@ class _$Constructor extends Constructor { @override final Reference redirect; - factory _$Constructor([void updates(ConstructorBuilder b)]) => + factory _$Constructor([void Function(ConstructorBuilder) updates]) => (new ConstructorBuilder()..update(updates)).build() as _$Constructor; _$Constructor._( @@ -59,35 +49,44 @@ class _$Constructor extends Constructor { this.name, this.redirect}) : super._() { - if (annotations == null) + if (annotations == null) { throw new BuiltValueNullFieldError('Constructor', 'annotations'); - if (docs == null) throw new BuiltValueNullFieldError('Constructor', 'docs'); - if (optionalParameters == null) + } + if (docs == null) { + throw new BuiltValueNullFieldError('Constructor', 'docs'); + } + if (optionalParameters == null) { throw new BuiltValueNullFieldError('Constructor', 'optionalParameters'); - if (requiredParameters == null) + } + if (requiredParameters == null) { throw new BuiltValueNullFieldError('Constructor', 'requiredParameters'); - if (initializers == null) + } + if (initializers == null) { throw new BuiltValueNullFieldError('Constructor', 'initializers'); - if (external == null) + } + if (external == null) { throw new BuiltValueNullFieldError('Constructor', 'external'); - if (constant == null) + } + if (constant == null) { throw new BuiltValueNullFieldError('Constructor', 'constant'); - if (factory == null) + } + if (factory == null) { throw new BuiltValueNullFieldError('Constructor', 'factory'); + } } @override - Constructor rebuild(void updates(ConstructorBuilder b)) => + Constructor rebuild(void Function(ConstructorBuilder) updates) => (toBuilder()..update(updates)).build(); @override _$ConstructorBuilder toBuilder() => new _$ConstructorBuilder()..replace(this); @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (identical(other, this)) return true; - if (other is! Constructor) return false; - return annotations == other.annotations && + return other is Constructor && + annotations == other.annotations && docs == other.docs && optionalParameters == other.optionalParameters && requiredParameters == other.requiredParameters && @@ -316,12 +315,14 @@ class _$ConstructorBuilder extends ConstructorBuilder { @override void replace(Constructor other) { - if (other == null) throw new ArgumentError.notNull('other'); + if (other == null) { + throw new ArgumentError.notNull('other'); + } _$v = other as _$Constructor; } @override - void update(void updates(ConstructorBuilder b)) { + void update(void Function(ConstructorBuilder) updates) { if (updates != null) updates(this); } @@ -366,3 +367,5 @@ class _$ConstructorBuilder extends ConstructorBuilder { return _$result; } } + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart index 69e93ff94..1d425889a 100644 --- a/pkgs/code_builder/lib/src/specs/directive.dart +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -14,7 +14,7 @@ part 'directive.g.dart'; @immutable abstract class Directive implements Built, Spec, Comparable { - factory Directive([void updates(DirectiveBuilder b)]) = _$Directive; + factory Directive([void Function(DirectiveBuilder) updates]) = _$Directive; factory Directive.import( String url, { diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart index a1717b2d5..ce34db590 100644 --- a/pkgs/code_builder/lib/src/specs/directive.g.dart +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -6,16 +6,6 @@ part of 'directive.dart'; // BuiltValueGenerator // ************************************************************************** -// ignore_for_file: always_put_control_body_on_new_line -// ignore_for_file: annotate_overrides -// ignore_for_file: avoid_annotating_with_dynamic -// ignore_for_file: avoid_catches_without_on_clauses -// ignore_for_file: avoid_returning_this -// ignore_for_file: lines_longer_than_80_chars -// ignore_for_file: omit_local_variable_types -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - class _$Directive extends Directive { @override final String as; @@ -30,32 +20,41 @@ class _$Directive extends Directive { @override final bool deferred; - factory _$Directive([void updates(DirectiveBuilder b)]) => + factory _$Directive([void Function(DirectiveBuilder) updates]) => (new DirectiveBuilder()..update(updates)).build() as _$Directive; _$Directive._( {this.as, this.url, this.type, this.show, this.hide, this.deferred}) : super._() { - if (url == null) throw new BuiltValueNullFieldError('Directive', 'url'); - if (type == null) throw new BuiltValueNullFieldError('Directive', 'type'); - if (show == null) throw new BuiltValueNullFieldError('Directive', 'show'); - if (hide == null) throw new BuiltValueNullFieldError('Directive', 'hide'); - if (deferred == null) + if (url == null) { + throw new BuiltValueNullFieldError('Directive', 'url'); + } + if (type == null) { + throw new BuiltValueNullFieldError('Directive', 'type'); + } + if (show == null) { + throw new BuiltValueNullFieldError('Directive', 'show'); + } + if (hide == null) { + throw new BuiltValueNullFieldError('Directive', 'hide'); + } + if (deferred == null) { throw new BuiltValueNullFieldError('Directive', 'deferred'); + } } @override - Directive rebuild(void updates(DirectiveBuilder b)) => + Directive rebuild(void Function(DirectiveBuilder) updates) => (toBuilder()..update(updates)).build(); @override _$DirectiveBuilder toBuilder() => new _$DirectiveBuilder()..replace(this); @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (identical(other, this)) return true; - if (other is! Directive) return false; - return as == other.as && + return other is Directive && + as == other.as && url == other.url && type == other.type && show == other.show && @@ -178,12 +177,14 @@ class _$DirectiveBuilder extends DirectiveBuilder { @override void replace(Directive other) { - if (other == null) throw new ArgumentError.notNull('other'); + if (other == null) { + throw new ArgumentError.notNull('other'); + } _$v = other as _$Directive; } @override - void update(void updates(DirectiveBuilder b)) { + void update(void Function(DirectiveBuilder) updates) { if (updates != null) updates(this); } @@ -201,3 +202,5 @@ class _$DirectiveBuilder extends DirectiveBuilder { return _$result; } } + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index cbbf6d4c1..1eb202774 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -373,7 +373,8 @@ abstract class ExpressionVisitor implements SpecVisitor { /// **INTERNAL ONLY**. abstract class ExpressionEmitter implements ExpressionVisitor { @override - visitToCodeExpression(ToCodeExpression expression, [StringSink output]) { + StringSink visitToCodeExpression(ToCodeExpression expression, + [StringSink output]) { output ??= StringBuffer(); expression.code.accept(this, output); if (expression.isStatement) { @@ -383,7 +384,8 @@ abstract class ExpressionEmitter implements ExpressionVisitor { } @override - visitBinaryExpression(BinaryExpression expression, [StringSink output]) { + StringSink visitBinaryExpression(BinaryExpression expression, + [StringSink output]) { output ??= StringBuffer(); expression.left.accept(this, output); if (expression.addSpace) { @@ -400,20 +402,23 @@ abstract class ExpressionEmitter implements ExpressionVisitor { } @override - visitClosureExpression(ClosureExpression expression, [StringSink output]) { + StringSink visitClosureExpression(ClosureExpression expression, + [StringSink output]) { output ??= StringBuffer(); return expression.method.accept(this, output); } @override - visitCodeExpression(CodeExpression expression, [StringSink output]) { + StringSink visitCodeExpression(CodeExpression expression, + [StringSink output]) { output ??= StringBuffer(); final visitor = this as CodeVisitor; return expression.code.accept(visitor, output); } @override - visitInvokeExpression(InvokeExpression expression, [StringSink output]) { + StringSink visitInvokeExpression(InvokeExpression expression, + [StringSink output]) { output ??= StringBuffer(); return _writeConstExpression( output, expression.type == InvokeExpressionType.constInstance, () { @@ -445,7 +450,8 @@ abstract class ExpressionEmitter implements ExpressionVisitor { } @override - visitLiteralExpression(LiteralExpression expression, [StringSink output]) { + StringSink visitLiteralExpression(LiteralExpression expression, + [StringSink output]) { output ??= StringBuffer(); return output..write(expression.literal); } @@ -461,7 +467,7 @@ abstract class ExpressionEmitter implements ExpressionVisitor { bool _withInConstExpression = false; @override - visitLiteralListExpression( + StringSink visitLiteralListExpression( LiteralListExpression expression, [ StringSink output, ]) { @@ -482,7 +488,7 @@ abstract class ExpressionEmitter implements ExpressionVisitor { } @override - visitLiteralSetExpression( + StringSink visitLiteralSetExpression( LiteralSetExpression expression, [ StringSink output, ]) { @@ -503,7 +509,7 @@ abstract class ExpressionEmitter implements ExpressionVisitor { } @override - visitLiteralMapExpression( + StringSink visitLiteralMapExpression( LiteralMapExpression expression, [ StringSink output, ]) { diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 3021fa18c..ba2e7b903 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -7,7 +7,7 @@ part of code_builder.src.specs.expression; /// Converts a runtime Dart [literal] value into an [Expression]. /// /// Unsupported inputs invoke the [onError] callback. -Expression literal(Object literal, {Expression onError(Object value)}) { +Expression literal(Object literal, {Expression Function(Object) onError}) { if (literal is bool) { return literalBool(literal); } diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index 81c564003..ddb0d285e 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -20,7 +20,7 @@ part 'field.g.dart'; abstract class Field extends Object with HasAnnotations, HasDartDocs implements Built, Spec { - factory Field([void updates(FieldBuilder b)]) = _$Field; + factory Field([void Function(FieldBuilder) updates]) = _$Field; Field._(); diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 3bef453fa..5dfccd9bd 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -6,16 +6,6 @@ part of 'field.dart'; // BuiltValueGenerator // ************************************************************************** -// ignore_for_file: always_put_control_body_on_new_line -// ignore_for_file: annotate_overrides -// ignore_for_file: avoid_annotating_with_dynamic -// ignore_for_file: avoid_catches_without_on_clauses -// ignore_for_file: avoid_returning_this -// ignore_for_file: lines_longer_than_80_chars -// ignore_for_file: omit_local_variable_types -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - class _$Field extends Field { @override final BuiltList annotations; @@ -32,7 +22,7 @@ class _$Field extends Field { @override final FieldModifier modifier; - factory _$Field([void updates(FieldBuilder b)]) => + factory _$Field([void Function(FieldBuilder) updates]) => (new FieldBuilder()..update(updates)).build() as _$Field; _$Field._( @@ -44,27 +34,35 @@ class _$Field extends Field { this.type, this.modifier}) : super._() { - if (annotations == null) + if (annotations == null) { throw new BuiltValueNullFieldError('Field', 'annotations'); - if (docs == null) throw new BuiltValueNullFieldError('Field', 'docs'); - if (static == null) throw new BuiltValueNullFieldError('Field', 'static'); - if (name == null) throw new BuiltValueNullFieldError('Field', 'name'); - if (modifier == null) + } + if (docs == null) { + throw new BuiltValueNullFieldError('Field', 'docs'); + } + if (static == null) { + throw new BuiltValueNullFieldError('Field', 'static'); + } + if (name == null) { + throw new BuiltValueNullFieldError('Field', 'name'); + } + if (modifier == null) { throw new BuiltValueNullFieldError('Field', 'modifier'); + } } @override - Field rebuild(void updates(FieldBuilder b)) => + Field rebuild(void Function(FieldBuilder) updates) => (toBuilder()..update(updates)).build(); @override _$FieldBuilder toBuilder() => new _$FieldBuilder()..replace(this); @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (identical(other, this)) return true; - if (other is! Field) return false; - return annotations == other.annotations && + return other is Field && + annotations == other.annotations && docs == other.docs && assignment == other.assignment && static == other.static && @@ -206,12 +204,14 @@ class _$FieldBuilder extends FieldBuilder { @override void replace(Field other) { - if (other == null) throw new ArgumentError.notNull('other'); + if (other == null) { + throw new ArgumentError.notNull('other'); + } _$v = other as _$Field; } @override - void update(void updates(FieldBuilder b)) { + void update(void Function(FieldBuilder) updates) { if (updates != null) updates(this); } @@ -245,3 +245,5 @@ class _$FieldBuilder extends FieldBuilder { return _$result; } } + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/library.dart b/pkgs/code_builder/lib/src/specs/library.dart index f47682809..d5722464d 100644 --- a/pkgs/code_builder/lib/src/specs/library.dart +++ b/pkgs/code_builder/lib/src/specs/library.dart @@ -14,7 +14,7 @@ part 'library.g.dart'; @immutable abstract class Library implements Built, Spec { - factory Library([void updates(LibraryBuilder b)]) = _$Library; + factory Library([void Function(LibraryBuilder) updates]) = _$Library; Library._(); BuiltList get directives; diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index 9935040d0..d302a94bc 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -6,43 +6,37 @@ part of 'library.dart'; // BuiltValueGenerator // ************************************************************************** -// ignore_for_file: always_put_control_body_on_new_line -// ignore_for_file: annotate_overrides -// ignore_for_file: avoid_annotating_with_dynamic -// ignore_for_file: avoid_catches_without_on_clauses -// ignore_for_file: avoid_returning_this -// ignore_for_file: lines_longer_than_80_chars -// ignore_for_file: omit_local_variable_types -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - class _$Library extends Library { @override final BuiltList directives; @override final BuiltList body; - factory _$Library([void updates(LibraryBuilder b)]) => + factory _$Library([void Function(LibraryBuilder) updates]) => (new LibraryBuilder()..update(updates)).build() as _$Library; _$Library._({this.directives, this.body}) : super._() { - if (directives == null) + if (directives == null) { throw new BuiltValueNullFieldError('Library', 'directives'); - if (body == null) throw new BuiltValueNullFieldError('Library', 'body'); + } + if (body == null) { + throw new BuiltValueNullFieldError('Library', 'body'); + } } @override - Library rebuild(void updates(LibraryBuilder b)) => + Library rebuild(void Function(LibraryBuilder) updates) => (toBuilder()..update(updates)).build(); @override _$LibraryBuilder toBuilder() => new _$LibraryBuilder()..replace(this); @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (identical(other, this)) return true; - if (other is! Library) return false; - return directives == other.directives && body == other.body; + return other is Library && + directives == other.directives && + body == other.body; } @override @@ -99,12 +93,14 @@ class _$LibraryBuilder extends LibraryBuilder { @override void replace(Library other) { - if (other == null) throw new ArgumentError.notNull('other'); + if (other == null) { + throw new ArgumentError.notNull('other'); + } _$v = other as _$Library; } @override - void update(void updates(LibraryBuilder b)) { + void update(void Function(LibraryBuilder) updates) { if (updates != null) updates(this); } @@ -131,3 +127,5 @@ class _$LibraryBuilder extends LibraryBuilder { return _$result; } } + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 5fecfe3d1..298fad3dc 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -23,9 +23,9 @@ final Reference _$void = const Reference('void'); abstract class Method extends Object with HasAnnotations, HasGenerics, HasDartDocs implements Built, Spec { - factory Method([void updates(MethodBuilder b)]) = _$Method; + factory Method([void Function(MethodBuilder) updates]) = _$Method; - factory Method.returnsVoid([void updates(MethodBuilder b)]) { + factory Method.returnsVoid([void Function(MethodBuilder) updates]) { return Method((b) { if (updates != null) { updates(b); @@ -161,7 +161,7 @@ enum MethodModifier { abstract class Parameter extends Object with HasAnnotations, HasGenerics, HasDartDocs implements Built { - factory Parameter([void updates(ParameterBuilder b)]) = _$Parameter; + factory Parameter([void Function(ParameterBuilder) updates]) = _$Parameter; Parameter._(); diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index b6b862ada..77a22d16c 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -6,16 +6,6 @@ part of 'method.dart'; // BuiltValueGenerator // ************************************************************************** -// ignore_for_file: always_put_control_body_on_new_line -// ignore_for_file: annotate_overrides -// ignore_for_file: avoid_annotating_with_dynamic -// ignore_for_file: avoid_catches_without_on_clauses -// ignore_for_file: avoid_returning_this -// ignore_for_file: lines_longer_than_80_chars -// ignore_for_file: omit_local_variable_types -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - class _$Method extends Method { @override final BuiltList annotations; @@ -44,7 +34,7 @@ class _$Method extends Method { @override final Reference returns; - factory _$Method([void updates(MethodBuilder b)]) => + factory _$Method([void Function(MethodBuilder) updates]) => (new MethodBuilder()..update(updates)).build() as _$Method; _$Method._( @@ -62,31 +52,41 @@ class _$Method extends Method { this.modifier, this.returns}) : super._() { - if (annotations == null) + if (annotations == null) { throw new BuiltValueNullFieldError('Method', 'annotations'); - if (docs == null) throw new BuiltValueNullFieldError('Method', 'docs'); - if (types == null) throw new BuiltValueNullFieldError('Method', 'types'); - if (optionalParameters == null) + } + if (docs == null) { + throw new BuiltValueNullFieldError('Method', 'docs'); + } + if (types == null) { + throw new BuiltValueNullFieldError('Method', 'types'); + } + if (optionalParameters == null) { throw new BuiltValueNullFieldError('Method', 'optionalParameters'); - if (requiredParameters == null) + } + if (requiredParameters == null) { throw new BuiltValueNullFieldError('Method', 'requiredParameters'); - if (external == null) + } + if (external == null) { throw new BuiltValueNullFieldError('Method', 'external'); - if (static == null) throw new BuiltValueNullFieldError('Method', 'static'); + } + if (static == null) { + throw new BuiltValueNullFieldError('Method', 'static'); + } } @override - Method rebuild(void updates(MethodBuilder b)) => + Method rebuild(void Function(MethodBuilder) updates) => (toBuilder()..update(updates)).build(); @override _$MethodBuilder toBuilder() => new _$MethodBuilder()..replace(this); @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (identical(other, this)) return true; - if (other is! Method) return false; - return annotations == other.annotations && + return other is Method && + annotations == other.annotations && docs == other.docs && types == other.types && optionalParameters == other.optionalParameters && @@ -334,12 +334,14 @@ class _$MethodBuilder extends MethodBuilder { @override void replace(Method other) { - if (other == null) throw new ArgumentError.notNull('other'); + if (other == null) { + throw new ArgumentError.notNull('other'); + } _$v = other as _$Method; } @override - void update(void updates(MethodBuilder b)) { + void update(void Function(MethodBuilder) updates) { if (updates != null) updates(this); } @@ -404,7 +406,7 @@ class _$Parameter extends Parameter { @override final Reference type; - factory _$Parameter([void updates(ParameterBuilder b)]) => + factory _$Parameter([void Function(ParameterBuilder) updates]) => (new ParameterBuilder()..update(updates)).build() as _$Parameter; _$Parameter._( @@ -417,28 +419,38 @@ class _$Parameter extends Parameter { this.types, this.type}) : super._() { - if (name == null) throw new BuiltValueNullFieldError('Parameter', 'name'); - if (named == null) throw new BuiltValueNullFieldError('Parameter', 'named'); - if (toThis == null) + if (name == null) { + throw new BuiltValueNullFieldError('Parameter', 'name'); + } + if (named == null) { + throw new BuiltValueNullFieldError('Parameter', 'named'); + } + if (toThis == null) { throw new BuiltValueNullFieldError('Parameter', 'toThis'); - if (annotations == null) + } + if (annotations == null) { throw new BuiltValueNullFieldError('Parameter', 'annotations'); - if (docs == null) throw new BuiltValueNullFieldError('Parameter', 'docs'); - if (types == null) throw new BuiltValueNullFieldError('Parameter', 'types'); + } + if (docs == null) { + throw new BuiltValueNullFieldError('Parameter', 'docs'); + } + if (types == null) { + throw new BuiltValueNullFieldError('Parameter', 'types'); + } } @override - Parameter rebuild(void updates(ParameterBuilder b)) => + Parameter rebuild(void Function(ParameterBuilder) updates) => (toBuilder()..update(updates)).build(); @override _$ParameterBuilder toBuilder() => new _$ParameterBuilder()..replace(this); @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (identical(other, this)) return true; - if (other is! Parameter) return false; - return defaultTo == other.defaultTo && + return other is Parameter && + defaultTo == other.defaultTo && name == other.name && named == other.named && toThis == other.toThis && @@ -597,12 +609,14 @@ class _$ParameterBuilder extends ParameterBuilder { @override void replace(Parameter other) { - if (other == null) throw new ArgumentError.notNull('other'); + if (other == null) { + throw new ArgumentError.notNull('other'); + } _$v = other as _$Parameter; } @override - void update(void updates(ParameterBuilder b)) { + void update(void Function(ParameterBuilder) updates) { if (updates != null) updates(this); } @@ -639,3 +653,5 @@ class _$ParameterBuilder extends ParameterBuilder { return _$result; } } + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index b7b9014bd..f4187bb21 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -20,7 +20,7 @@ abstract class FunctionType extends Expression with HasGenerics implements Built, Reference, Spec { factory FunctionType([ - void updates(FunctionTypeBuilder b), + void Function(FunctionTypeBuilder) updates, ]) = _$FunctionType; FunctionType._(); diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart index b89237f58..8b0f673a2 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -6,16 +6,6 @@ part of 'type_function.dart'; // BuiltValueGenerator // ************************************************************************** -// ignore_for_file: always_put_control_body_on_new_line -// ignore_for_file: annotate_overrides -// ignore_for_file: avoid_annotating_with_dynamic -// ignore_for_file: avoid_catches_without_on_clauses -// ignore_for_file: avoid_returning_this -// ignore_for_file: lines_longer_than_80_chars -// ignore_for_file: omit_local_variable_types -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - class _$FunctionType extends FunctionType { @override final Reference returnType; @@ -28,7 +18,7 @@ class _$FunctionType extends FunctionType { @override final BuiltMap namedParameters; - factory _$FunctionType([void updates(FunctionTypeBuilder b)]) => + factory _$FunctionType([void Function(FunctionTypeBuilder) updates]) => (new FunctionTypeBuilder()..update(updates)).build() as _$FunctionType; _$FunctionType._( @@ -38,18 +28,22 @@ class _$FunctionType extends FunctionType { this.optionalParameters, this.namedParameters}) : super._() { - if (types == null) + if (types == null) { throw new BuiltValueNullFieldError('FunctionType', 'types'); - if (requiredParameters == null) + } + if (requiredParameters == null) { throw new BuiltValueNullFieldError('FunctionType', 'requiredParameters'); - if (optionalParameters == null) + } + if (optionalParameters == null) { throw new BuiltValueNullFieldError('FunctionType', 'optionalParameters'); - if (namedParameters == null) + } + if (namedParameters == null) { throw new BuiltValueNullFieldError('FunctionType', 'namedParameters'); + } } @override - FunctionType rebuild(void updates(FunctionTypeBuilder b)) => + FunctionType rebuild(void Function(FunctionTypeBuilder) updates) => (toBuilder()..update(updates)).build(); @override @@ -57,10 +51,10 @@ class _$FunctionType extends FunctionType { new _$FunctionTypeBuilder()..replace(this); @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (identical(other, this)) return true; - if (other is! FunctionType) return false; - return returnType == other.returnType && + return other is FunctionType && + returnType == other.returnType && types == other.types && requiredParameters == other.requiredParameters && optionalParameters == other.optionalParameters && @@ -168,12 +162,14 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { @override void replace(FunctionType other) { - if (other == null) throw new ArgumentError.notNull('other'); + if (other == null) { + throw new ArgumentError.notNull('other'); + } _$v = other as _$FunctionType; } @override - void update(void updates(FunctionTypeBuilder b)) { + void update(void Function(FunctionTypeBuilder) updates) { if (updates != null) updates(this); } @@ -209,3 +205,5 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { return _$result; } } + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index 1f864f9c6..5433c1e9a 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -20,7 +20,7 @@ abstract class TypeReference extends Expression with HasGenerics implements Built, Reference, Spec { factory TypeReference([ - void updates(TypeReferenceBuilder b), + void Function(TypeReferenceBuilder) updates, ]) = _$TypeReference; TypeReference._(); diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index bcd362f1f..0e7662fa8 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -6,16 +6,6 @@ part of 'type_reference.dart'; // BuiltValueGenerator // ************************************************************************** -// ignore_for_file: always_put_control_body_on_new_line -// ignore_for_file: annotate_overrides -// ignore_for_file: avoid_annotating_with_dynamic -// ignore_for_file: avoid_catches_without_on_clauses -// ignore_for_file: avoid_returning_this -// ignore_for_file: lines_longer_than_80_chars -// ignore_for_file: omit_local_variable_types -// ignore_for_file: prefer_expression_function_bodies -// ignore_for_file: sort_constructors_first - class _$TypeReference extends TypeReference { @override final String symbol; @@ -26,19 +16,21 @@ class _$TypeReference extends TypeReference { @override final BuiltList types; - factory _$TypeReference([void updates(TypeReferenceBuilder b)]) => + factory _$TypeReference([void Function(TypeReferenceBuilder) updates]) => (new TypeReferenceBuilder()..update(updates)).build() as _$TypeReference; _$TypeReference._({this.symbol, this.url, this.bound, this.types}) : super._() { - if (symbol == null) + if (symbol == null) { throw new BuiltValueNullFieldError('TypeReference', 'symbol'); - if (types == null) + } + if (types == null) { throw new BuiltValueNullFieldError('TypeReference', 'types'); + } } @override - TypeReference rebuild(void updates(TypeReferenceBuilder b)) => + TypeReference rebuild(void Function(TypeReferenceBuilder) updates) => (toBuilder()..update(updates)).build(); @override @@ -46,10 +38,10 @@ class _$TypeReference extends TypeReference { new _$TypeReferenceBuilder()..replace(this); @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (identical(other, this)) return true; - if (other is! TypeReference) return false; - return symbol == other.symbol && + return other is TypeReference && + symbol == other.symbol && url == other.url && bound == other.bound && types == other.types; @@ -139,12 +131,14 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { @override void replace(TypeReference other) { - if (other == null) throw new ArgumentError.notNull('other'); + if (other == null) { + throw new ArgumentError.notNull('other'); + } _$v = other as _$TypeReference; } @override - void update(void updates(TypeReferenceBuilder b)) { + void update(void Function(TypeReferenceBuilder) updates) { if (updates != null) updates(this); } @@ -170,3 +164,5 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { return _$result; } } + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index a99653c44..a67fe4c87 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -7,7 +7,7 @@ author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=2.2.0 <3.0.0' + sdk: '>=2.6.0 <3.0.0' dependencies: built_collection: '>=3.0.0 <5.0.0' @@ -21,8 +21,6 @@ dev_dependencies: build_runner: ^1.1.0 built_value_generator: ^7.0.0 dart_style: ^1.0.0 + pedantic: ^1.0.0 source_gen: ^0.9.0 test: ^1.3.0 - -dependency_overrides: - built_value: ^7.0.0 From c5bb77fcfab3cf427a5fb139fbfda2bdf40f4664 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 13 Mar 2020 12:20:30 -0700 Subject: [PATCH 147/271] Remove author from pubspec --- pkgs/code_builder/pubspec.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index a67fe4c87..3152edb2f 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -3,7 +3,6 @@ version: 3.2.2-dev description: >- A fluent, builder-based library for generating valid Dart code -author: Dart Team homepage: https://github.com/dart-lang/code_builder environment: From 72823c5010b136e301195d8182e93af191ef3970 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 23 Apr 2020 10:12:37 -0700 Subject: [PATCH 148/271] Update contributing instructions (dart-lang/code_builder#272) --- pkgs/code_builder/README.md | 3 ++- pkgs/code_builder/build.disabled.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 9d9f394a2..082e3bc76 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -99,8 +99,9 @@ will be on a best-effort basis. Use [`build_runner`][build_runner]: ```bash +$ pub global activate build_runner $ mv build.disabled.yaml build.yaml -$ pub run build_runner build --delete-conflicting-outputs +$ pub global run build_runner build --delete-conflicting-outputs $ mv build.yaml build.disabled.yaml ``` diff --git a/pkgs/code_builder/build.disabled.yaml b/pkgs/code_builder/build.disabled.yaml index 2eed50399..31e5817d0 100644 --- a/pkgs/code_builder/build.disabled.yaml +++ b/pkgs/code_builder/build.disabled.yaml @@ -6,7 +6,7 @@ targets: builders: _built_value: target: ":code_builder" - import: "../../../tool/src/builder.dart" + import: "tool/src/builder.dart" builder_factories: - "builtValueBuilder" build_extensions: From 3a6efa69bcef7020e64cc181be284e7cc2763b3a Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 23 Apr 2020 15:00:47 -0700 Subject: [PATCH 149/271] Add isNullable field to TypeReference, and isNullSafety to DartEmitter (dart-lang/code_builder#273) Add isNullable field to TypeReference, and useNullSafetySyntax to DartEmitter --- pkgs/code_builder/lib/src/emitter.dart | 23 ++++++-- .../lib/src/specs/type_reference.dart | 13 +++++ .../lib/src/specs/type_reference.g.dart | 35 ++++++++++-- .../test/specs/type_reference_test.dart | 56 +++++++++++++++++++ 4 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 pkgs/code_builder/test/specs/type_reference_test.dart diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index f5ae995c6..767754db2 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -59,15 +59,27 @@ class DartEmitter extends Object /// lint. final bool orderDirectives; + /// If nullable types should be emitted with the nullable suffix ("?"). + /// + /// Null safety syntax should only be enabled if the output will be used with + /// a Dart language version which supports it. + final bool _useNullSafetySyntax; + /// Creates a new instance of [DartEmitter]. /// /// May specify an [Allocator] to use for symbols, otherwise uses a no-op. - DartEmitter([this.allocator = Allocator.none, bool orderDirectives = false]) - : orderDirectives = orderDirectives ?? false; + DartEmitter( + [this.allocator = Allocator.none, + bool orderDirectives = false, + bool useNullSafetySyntax = false]) + : orderDirectives = orderDirectives ?? false, + _useNullSafetySyntax = useNullSafetySyntax ?? false; /// Creates a new instance of [DartEmitter] with simple automatic imports. - factory DartEmitter.scoped({bool orderDirectives = false}) { - return DartEmitter(Allocator.simplePrefixing(), orderDirectives); + factory DartEmitter.scoped( + {bool orderDirectives = false, bool useNullSafetySyntax = false}) { + return DartEmitter( + Allocator.simplePrefixing(), orderDirectives, useNullSafetySyntax); } static bool _isLambdaBody(Code code) => @@ -490,6 +502,9 @@ class DartEmitter extends Object spec.bound.type.accept(this, output); } visitTypeParameters(spec.types.map((r) => r.type), output); + if (_useNullSafetySyntax && (spec.isNullable ?? false)) { + output.write('?'); + } return output; } diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index 5433c1e9a..dee684e70 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -39,6 +39,13 @@ abstract class TypeReference extends Expression @override BuiltList get types; + /// Optional nullability. + /// + /// An emitter may ignore this if the output is not targeting a Dart language + /// version that supports null safety. + @nullable + bool get isNullable; + @override R accept( SpecVisitor visitor, [ @@ -133,4 +140,10 @@ abstract class TypeReferenceBuilder extends Object @override ListBuilder types = ListBuilder(); + + /// Optional nullability. + /// + /// An emitter may ignore this if the output is not targeting a Dart language + /// version that supports null safety. + bool isNullable; } diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index 0e7662fa8..315f3e5dc 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -15,11 +15,14 @@ class _$TypeReference extends TypeReference { final Reference bound; @override final BuiltList types; + @override + final bool isNullable; factory _$TypeReference([void Function(TypeReferenceBuilder) updates]) => (new TypeReferenceBuilder()..update(updates)).build() as _$TypeReference; - _$TypeReference._({this.symbol, this.url, this.bound, this.types}) + _$TypeReference._( + {this.symbol, this.url, this.bound, this.types, this.isNullable}) : super._() { if (symbol == null) { throw new BuiltValueNullFieldError('TypeReference', 'symbol'); @@ -44,14 +47,16 @@ class _$TypeReference extends TypeReference { symbol == other.symbol && url == other.url && bound == other.bound && - types == other.types; + types == other.types && + isNullable == other.isNullable; } @override int get hashCode { return $jf($jc( - $jc($jc($jc(0, symbol.hashCode), url.hashCode), bound.hashCode), - types.hashCode)); + $jc($jc($jc($jc(0, symbol.hashCode), url.hashCode), bound.hashCode), + types.hashCode), + isNullable.hashCode)); } @override @@ -60,7 +65,8 @@ class _$TypeReference extends TypeReference { ..add('symbol', symbol) ..add('url', url) ..add('bound', bound) - ..add('types', types)) + ..add('types', types) + ..add('isNullable', isNullable)) .toString(); } } @@ -116,6 +122,18 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { super.types = types; } + @override + bool get isNullable { + _$this; + return super.isNullable; + } + + @override + set isNullable(bool isNullable) { + _$this; + super.isNullable = isNullable; + } + _$TypeReferenceBuilder() : super._(); TypeReferenceBuilder get _$this { @@ -124,6 +142,7 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { super.url = _$v.url; super.bound = _$v.bound; super.types = _$v.types?.toBuilder(); + super.isNullable = _$v.isNullable; _$v = null; } return this; @@ -148,7 +167,11 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { try { _$result = _$v ?? new _$TypeReference._( - symbol: symbol, url: url, bound: bound, types: types.build()); + symbol: symbol, + url: url, + bound: bound, + types: types.build(), + isNullable: isNullable); } catch (_) { String _$failedField; try { diff --git a/pkgs/code_builder/test/specs/type_reference_test.dart b/pkgs/code_builder/test/specs/type_reference_test.dart new file mode 100644 index 000000000..d6715e5bd --- /dev/null +++ b/pkgs/code_builder/test/specs/type_reference_test.dart @@ -0,0 +1,56 @@ +// Copyright (c) 2020, 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:test/test.dart'; + +import '../common.dart'; + +void main() { + useDartfmt(); + + test('should create a nullable type in a pre-Null Safety library', () { + expect( + TypeReference((b) => b + ..symbol = 'Foo' + ..isNullable = true), + equalsDart(r''' + Foo + '''), + ); + }); + + group('in a Null Safety library', () { + DartEmitter emitter; + + setUp(() => emitter = DartEmitter.scoped(useNullSafetySyntax: true)); + + test('should create a nullable type', () { + expect( + TypeReference((b) => b + ..symbol = 'Foo' + ..isNullable = true), + equalsDart(r'Foo?', emitter), + ); + }); + + test('should create a non-nullable type', () { + expect( + TypeReference((b) => b.symbol = 'Foo'), + equalsDart(r'Foo', emitter), + ); + }); + + test('should create a type with nullable type arguments', () { + expect( + TypeReference((b) => b + ..symbol = 'List' + ..types.add(TypeReference((b) => b + ..symbol = 'int' + ..isNullable = true))), + equalsDart(r'List', emitter), + ); + }); + }); +} From b1bf046ef8ff38fea67b70f2656faa5055ce6b5b Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 28 Apr 2020 11:02:43 -0700 Subject: [PATCH 150/271] Add 'required' and 'covariant' bools to Paramter (dart-lang/code_builder#275) --- pkgs/code_builder/lib/src/emitter.dart | 7 ++ pkgs/code_builder/lib/src/specs/method.dart | 26 +++++++ pkgs/code_builder/lib/src/specs/method.g.dart | 72 ++++++++++++++++--- pkgs/code_builder/test/specs/method_test.dart | 63 ++++++++++++++++ 4 files changed, 157 insertions(+), 11 deletions(-) diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 767754db2..2ffd0cbf4 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -469,6 +469,13 @@ class DartEmitter extends Object }) { spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); + // The `required` keyword must precede the `covariant` keyword. + if (spec.required) { + output.write('required '); + } + if (spec.covariant) { + output.write('covariant '); + } if (spec.type != null) { spec.type.type.accept(this, output); output.write(' '); diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 298fad3dc..3172711e6 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -192,6 +192,19 @@ abstract class Parameter extends Object /// Type of the parameter; @nullable Reference get type; + + /// Whether this parameter should be annotated with the `required` keyword. + /// + /// This is only valid on named parameters. + /// + /// This is only valid when the output is targeting a Dart language version + /// that supports null safety. + bool get required; + + /// Whether this parameter should be annotated with the `covariant` keyword. + /// + /// This is only valid on instance methods. + bool get covariant; } abstract class ParameterBuilder extends Object @@ -226,4 +239,17 @@ abstract class ParameterBuilder extends Object /// Type of the parameter; Reference type; + + /// Whether this parameter should be annotated with the `required` keyword. + /// + /// This is only valid on named parameters. + /// + /// This is only valid when the output is targeting a Dart language version + /// that supports null safety. + bool required = false; + + /// Whether this parameter should be annotated with the `covariant` keyword. + /// + /// This is only valid on instance methods. + bool covariant = false; } diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index 77a22d16c..ba721b57f 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -405,6 +405,10 @@ class _$Parameter extends Parameter { final BuiltList types; @override final Reference type; + @override + final bool required; + @override + final bool covariant; factory _$Parameter([void Function(ParameterBuilder) updates]) => (new ParameterBuilder()..update(updates)).build() as _$Parameter; @@ -417,7 +421,9 @@ class _$Parameter extends Parameter { this.annotations, this.docs, this.types, - this.type}) + this.type, + this.required, + this.covariant}) : super._() { if (name == null) { throw new BuiltValueNullFieldError('Parameter', 'name'); @@ -437,6 +443,12 @@ class _$Parameter extends Parameter { if (types == null) { throw new BuiltValueNullFieldError('Parameter', 'types'); } + if (required == null) { + throw new BuiltValueNullFieldError('Parameter', 'required'); + } + if (covariant == null) { + throw new BuiltValueNullFieldError('Parameter', 'covariant'); + } } @override @@ -457,7 +469,9 @@ class _$Parameter extends Parameter { annotations == other.annotations && docs == other.docs && types == other.types && - type == other.type; + type == other.type && + required == other.required && + covariant == other.covariant; } @override @@ -467,13 +481,19 @@ class _$Parameter extends Parameter { $jc( $jc( $jc( - $jc($jc($jc(0, defaultTo.hashCode), name.hashCode), - named.hashCode), - toThis.hashCode), - annotations.hashCode), - docs.hashCode), - types.hashCode), - type.hashCode)); + $jc( + $jc( + $jc( + $jc($jc(0, defaultTo.hashCode), + name.hashCode), + named.hashCode), + toThis.hashCode), + annotations.hashCode), + docs.hashCode), + types.hashCode), + type.hashCode), + required.hashCode), + covariant.hashCode)); } @override @@ -486,7 +506,9 @@ class _$Parameter extends Parameter { ..add('annotations', annotations) ..add('docs', docs) ..add('types', types) - ..add('type', type)) + ..add('type', type) + ..add('required', required) + ..add('covariant', covariant)) .toString(); } } @@ -590,6 +612,30 @@ class _$ParameterBuilder extends ParameterBuilder { super.type = type; } + @override + bool get required { + _$this; + return super.required; + } + + @override + set required(bool required) { + _$this; + super.required = required; + } + + @override + bool get covariant { + _$this; + return super.covariant; + } + + @override + set covariant(bool covariant) { + _$this; + super.covariant = covariant; + } + _$ParameterBuilder() : super._(); ParameterBuilder get _$this { @@ -602,6 +648,8 @@ class _$ParameterBuilder extends ParameterBuilder { super.docs = _$v.docs?.toBuilder(); super.types = _$v.types?.toBuilder(); super.type = _$v.type; + super.required = _$v.required; + super.covariant = _$v.covariant; _$v = null; } return this; @@ -633,7 +681,9 @@ class _$ParameterBuilder extends ParameterBuilder { annotations: annotations.build(), docs: docs.build(), types: types.build(), - type: type); + type: type, + required: required, + covariant: covariant); } catch (_) { String _$failedField; try { diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 4d2f87690..852297e2f 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -361,6 +361,26 @@ void main() { ); }); + test('should create a method with a covariant parameter with a type', () { + expect( + Method( + (b) => b + ..name = 'fib' + ..requiredParameters.add( + Parameter( + (b) => b + ..name = 'i' + ..covariant = true + ..type = refer('int').type, + ), + ), + ), + equalsDart(r''' + fib(covariant int i); + '''), + ); + }); + test('should create a method with a parameter with a generic type', () { expect( Method( @@ -436,6 +456,49 @@ void main() { ); }); + test('should create a method with a named required parameter', () { + expect( + Method( + (b) => b + ..name = 'fib' + ..optionalParameters.add( + Parameter( + (b) => b + ..name = 'i' + ..named = true + ..required = true + ..type = refer('int').type, + ), + ), + ), + equalsDart(r''' + fib({required int i}); + '''), + ); + }); + + test('should create a method with a named required covariant parameter', () { + expect( + Method( + (b) => b + ..name = 'fib' + ..optionalParameters.add( + Parameter( + (b) => b + ..name = 'i' + ..named = true + ..required = true + ..covariant = true + ..type = refer('int').type, + ), + ), + ), + equalsDart(r''' + fib({required covariant int i}); + '''), + ); + }); + test('should create a method with a named optional parameter', () { expect( Method( From 82170d668fea33f9af3cbb0ea975f4414e02313a Mon Sep 17 00:00:00 2001 From: "Sat Mandir S. Khalsa" Date: Mon, 18 May 2020 19:44:29 +0200 Subject: [PATCH 151/271] Add missing operators and part directive (dart-lang/code_builder#269) --- pkgs/code_builder/CHANGELOG.md | 6 +++++ pkgs/code_builder/lib/src/emitter.dart | 4 +++- .../code_builder/lib/src/specs/directive.dart | 6 +++++ .../lib/src/specs/expression.dart | 19 ++++++++++++++++ pkgs/code_builder/pubspec.yaml | 2 +- ...direcive_test.dart => directive_test.dart} | 6 ++++- .../test/specs/code/expression_test.dart | 22 +++++++++++++++++++ .../code_builder/test/specs/library_test.dart | 14 ++++++++++++ 8 files changed, 76 insertions(+), 3 deletions(-) rename pkgs/code_builder/test/{direcive_test.dart => directive_test.dart} (93%) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index b53f90733..22522025e 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,9 @@ +## 3.3.0-dev + +* Add `??` null-aware operator. +* Add `..` cascade assignment operator. +* Add `part` directive. + ## 3.2.2 * Require minimum Dart SDK of `2.6.0`. diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 2ffd0cbf4..38803edff 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -238,8 +238,10 @@ class DartEmitter extends Object output ??= StringBuffer(); if (spec.type == DirectiveType.import) { output.write('import '); - } else { + } else if (spec.type == DirectiveType.export) { output.write('export '); + } else { + output.write('part '); } output.write("'${spec.url}'"); if (spec.as != null) { diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart index 1d425889a..04018d587 100644 --- a/pkgs/code_builder/lib/src/specs/directive.dart +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -54,6 +54,10 @@ abstract class Directive ..show.addAll(show) ..hide.addAll(hide)); + factory Directive.part(String url) => Directive((builder) => builder + ..type = DirectiveType.part + ..url = url); + Directive._(); @nullable @@ -102,6 +106,7 @@ abstract class DirectiveBuilder enum DirectiveType { import, export, + part, } /// Sort import URIs represented by [a] and [b] to honor the @@ -112,6 +117,7 @@ enum DirectiveType { /// 2. `dart:` /// 3. `package:` /// 4. relative +/// 5. `part`s int _compareDirectives(Directive a, Directive b) { // NOTE: using the fact that `import` is before `export` in the // `DirectiveType` enum – which allows us to compare using `indexOf`. diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 1eb202774..f84bdb49d 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -226,6 +226,15 @@ abstract class Expression implements Spec { ); } + /// Return `{other} ?? {this}`. + Expression ifNullThen(Expression other) { + return BinaryExpression._( + this, + other, + '??', + ); + } + /// Return `{other} ??= {this}`. Expression assignNullAware(Expression other) { return BinaryExpression._( @@ -305,6 +314,16 @@ abstract class Expression implements Spec { ); } + /// Returns an expression accessing `..` on this expression. + Expression cascade(String name) { + return BinaryExpression._( + this, + LiteralExpression._(name), + '..', + addSpace: false, + ); + } + /// Returns an expression accessing `?.` on this expression. Expression nullSafeProperty(String name) { return BinaryExpression._( diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 3152edb2f..17e2c9e0b 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.2.2-dev +version: 3.3.0-dev description: >- A fluent, builder-based library for generating valid Dart code diff --git a/pkgs/code_builder/test/direcive_test.dart b/pkgs/code_builder/test/directive_test.dart similarity index 93% rename from pkgs/code_builder/test/direcive_test.dart rename to pkgs/code_builder/test/directive_test.dart index f5fcaa32c..e19d76207 100644 --- a/pkgs/code_builder/test/direcive_test.dart +++ b/pkgs/code_builder/test/directive_test.dart @@ -15,6 +15,7 @@ void main() { final library = Library((b) => b ..directives.add((Directive.export('../relative.dart'))) ..directives.add((Directive.export('package:foo/foo.dart'))) + ..directives.add((Directive.part('lib.g.dart'))) ..body.add(Field((b) => b ..name = 'relativeRef' ..modifier = FieldModifier.final$ @@ -39,6 +40,7 @@ void main() { equalsDart(r''' export '../relative.dart'; export 'package:foo/foo.dart'; + part 'lib.g.dart'; import '../relative.dart' as _i1; import 'package:foo/foo.dart' as _i2; import 'package:foo/bar.dart' as _i3; @@ -49,7 +51,7 @@ void main() { final pkgRefBar = _i3.Bar(); final collectionRef = _i4.LinkedHashMap();''', DartEmitter.scoped()), ); - }); + }, skip: 'failing due to whitespace issue in equalsDart'); test('should emit a source file with ordered', () { expect( @@ -65,6 +67,8 @@ void main() { export 'package:foo/foo.dart'; export '../relative.dart'; + part 'lib.g.dart'; + final relativeRef = _i1.Relative(); final pkgRefFoo = _i2.Foo(); final pkgRefBar = _i3.Bar(); diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 79b04ccfd..467ec5acf 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -165,6 +165,10 @@ void main() { expect(refer('foo').property('bar'), equalsDart('foo.bar')); }); + test('should emit invoking a cascade property accessor', () { + expect(refer('foo').cascade('bar'), equalsDart('foo..bar')); + }); + test('should emit invoking a null safe property accessor', () { expect(refer('foo').nullSafeProperty('bar'), equalsDart('foo?.bar')); }); @@ -314,6 +318,24 @@ void main() { ); }); + test('should emit an if null assignment', () { + expect( + refer('foo').ifNullThen(literalTrue), + equalsDart('foo ?? true'), + ); + }); + + test('should emit an if null index operator set', () { + expect( + refer('bar') + .index(literalTrue) + .ifNullThen(literalFalse) + .assignVar('foo') + .statement, + equalsDart('var foo = bar[true] ?? false;'), + ); + }); + test('should emit a null-aware assignment', () { expect( refer('foo').assignNullAware(literalTrue), diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index 4000fdf19..6dfbf3d12 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -109,5 +109,19 @@ void main() { ''', DartEmitter(Allocator.simplePrefixing())), ); }); + + test('should emit a source file with part directives', () { + expect( + Library( + (b) => b + ..directives.add( + Directive.part('test.g.dart'), + ), + ), + equalsDart(r''' + part 'test.g.dart'; + ''', DartEmitter()), + ); + }); }); } From 7344b8410f2537cadd20c6b2dc7ee40897cd3e29 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 18 May 2020 10:48:12 -0700 Subject: [PATCH 152/271] Use switch/case over if/else for enum values --- pkgs/code_builder/lib/src/emitter.dart | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 38803edff..358bba09a 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -236,12 +236,16 @@ class DartEmitter extends Object @override StringSink visitDirective(Directive spec, [StringSink output]) { output ??= StringBuffer(); - if (spec.type == DirectiveType.import) { - output.write('import '); - } else if (spec.type == DirectiveType.export) { - output.write('export '); - } else { - output.write('part '); + switch (spec.type) { + case DirectiveType.import: + output.write('import '); + break; + case DirectiveType.export: + output.write('export '); + break; + case DirectiveType.part: + output.write('part '); + break; } output.write("'${spec.url}'"); if (spec.as != null) { From 3043e4253d1ed71bc8ea1a405177cdf8e9f903b2 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 18 May 2020 16:40:43 -0700 Subject: [PATCH 153/271] Sort allocator imports before other directives (dart-lang/code_builder#279) Manually specified directive, most likely exports or part directives, should generally follow imports. Move imports from `refer` URIs to the beginning so that they get the correct order as long as manually specified directives where in the correct order, regardless of sorting directives. --- pkgs/code_builder/lib/src/emitter.dart | 2 +- pkgs/code_builder/test/directive_test.dart | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 358bba09a..8a9e0f429 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -315,7 +315,7 @@ class DartEmitter extends Object } } - final directives = [...spec.directives, ...allocator.imports]; + final directives = [...allocator.imports, ...spec.directives]; if (orderDirectives) { directives.sort(); diff --git a/pkgs/code_builder/test/directive_test.dart b/pkgs/code_builder/test/directive_test.dart index e19d76207..d99922267 100644 --- a/pkgs/code_builder/test/directive_test.dart +++ b/pkgs/code_builder/test/directive_test.dart @@ -38,20 +38,20 @@ void main() { expect( library, equalsDart(r''' - export '../relative.dart'; - export 'package:foo/foo.dart'; - part 'lib.g.dart'; import '../relative.dart' as _i1; import 'package:foo/foo.dart' as _i2; import 'package:foo/bar.dart' as _i3; import 'dart:collection' as _i4; + export '../relative.dart'; + export 'package:foo/foo.dart'; + part 'lib.g.dart'; final relativeRef = _i1.Relative(); final pkgRefFoo = _i2.Foo(); final pkgRefBar = _i3.Bar(); final collectionRef = _i4.LinkedHashMap();''', DartEmitter.scoped()), ); - }, skip: 'failing due to whitespace issue in equalsDart'); + }); test('should emit a source file with ordered', () { expect( From a3ddf975a23b7e3afd564c9647701596f8c50499 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 21 May 2020 09:16:12 -0700 Subject: [PATCH 154/271] Prepare to publish (dart-lang/code_builder#280) --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 22522025e..8ebb1ae33 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.3.0-dev +## 3.3.0 * Add `??` null-aware operator. * Add `..` cascade assignment operator. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 17e2c9e0b..1f48321f2 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.3.0-dev +version: 3.3.0 description: >- A fluent, builder-based library for generating valid Dart code From 7287a5006bce4e840360888ee04feb1148d309c5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 26 May 2020 10:00:01 -0700 Subject: [PATCH 155/271] Fix outdated urls --- pkgs/code_builder/README.md | 5 ++--- pkgs/code_builder/lib/src/emitter.dart | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 082e3bc76..a438d7d3c 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -1,6 +1,5 @@ -[![Pub package](https://img.shields.io/pub/v/code_builder.svg)](https://pub.dartlang.org/packages/code_builder) +[![Pub package](https://img.shields.io/pub/v/code_builder.svg)](https://pub.dev/packages/code_builder) [![Build status](https://travis-ci.org/dart-lang/code_builder.svg)](https://travis-ci.org/dart-lang/code_builder) -[![Latest docs](https://img.shields.io/badge/dartdocs-latest-blue.svg)](https://www.dartdocs.org/documentation/code_builder/latest) [![Gitter chat](https://badges.gitter.im/dart-lang/build.svg)](https://gitter.im/dart-lang/build) A fluent, builder-based library for generating valid Dart code. @@ -105,4 +104,4 @@ $ pub global run build_runner build --delete-conflicting-outputs $ mv build.yaml build.disabled.yaml ``` -[build_runner]: https://pub.dartlang.org/packages/build_runner +[build_runner]: https://pub.dev/packages/build_runner diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 8a9e0f429..870d45954 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -53,9 +53,9 @@ class DartEmitter extends Object /// If directives should be ordered while emitting. /// /// Ordering rules follow the guidance in - /// [Effective Dart](https://www.dartlang.org/guides/language/effective-dart/style#ordering) + /// [Effective Dart](https://dart.dev/guides/language/effective-dart/style#ordering) /// and the - /// [directives_ordering](http://dart-lang.github.io/linter/lints/directives_ordering.html) + /// [directives_ordering](https://dart-lang.github.io/linter/lints/directives_ordering.html) /// lint. final bool orderDirectives; From e6de72a5252e88b66b1b0226d0c15217eb0a6ff2 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 26 May 2020 10:32:53 -0700 Subject: [PATCH 156/271] enable and fix a number of lints (dart-lang/code_builder#281) --- pkgs/code_builder/analysis_options.yaml | 34 ++ pkgs/code_builder/lib/src/allocator.dart | 12 +- pkgs/code_builder/lib/src/base.dart | 5 +- pkgs/code_builder/lib/src/emitter.dart | 12 +- pkgs/code_builder/lib/src/matchers.dart | 11 +- pkgs/code_builder/lib/src/specs/code.dart | 30 +- .../lib/src/specs/expression.dart | 423 ++++++++---------- .../lib/src/specs/expression/binary.dart | 5 +- .../lib/src/specs/expression/closure.dart | 5 +- .../lib/src/specs/expression/code.dart | 5 +- .../lib/src/specs/expression/invoke.dart | 5 +- .../lib/src/specs/expression/literal.dart | 50 +-- pkgs/code_builder/lib/src/specs/method.dart | 17 +- .../code_builder/lib/src/specs/reference.dart | 78 ++-- .../lib/src/specs/type_reference.dart | 70 ++- pkgs/code_builder/tool/src/builder.dart | 8 +- 16 files changed, 348 insertions(+), 422 deletions(-) diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml index 7b57d5c9a..cceb9b380 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/analysis_options.yaml @@ -20,15 +20,49 @@ linter: - throw_in_finally # Style Rules + - avoid_catching_errors + - avoid_private_typedef_functions + - avoid_redundant_argument_values + - avoid_renaming_method_parameters + - avoid_returning_null_for_void + - avoid_unused_constructor_parameters + - await_only_futures - camel_case_types - cascade_invocations - constant_identifier_names - directives_ordering + - file_names - implementation_imports + - join_return_with_assignment + - lines_longer_than_80_chars + - missing_whitespace_between_adjacent_strings + - no_runtimeType_toString - non_constant_identifier_names - only_throw_errors + - package_names + - package_prefixed_library_names + - prefer_asserts_in_initializer_lists - prefer_const_constructors + - prefer_const_declarations + - prefer_expression_function_bodies - prefer_final_locals + - prefer_function_declarations_over_variables - prefer_initializing_formals + - prefer_inlined_adds - prefer_interpolation_to_compose_strings + - prefer_is_not_operator + - prefer_null_aware_operators + - prefer_relative_imports + - prefer_typing_uninitialized_variables + - prefer_void_to_null + - provide_deprecation_message + - sort_pub_dependencies - unnecessary_brace_in_string_interps + - unnecessary_lambdas + - unnecessary_null_aware_assignments + - unnecessary_overrides + - unnecessary_parenthesis + - unnecessary_statements + - unnecessary_string_interpolations + - use_string_buffers + - void_checks diff --git a/pkgs/code_builder/lib/src/allocator.dart b/pkgs/code_builder/lib/src/allocator.dart index dad9d7786..188094648 100644 --- a/pkgs/code_builder/lib/src/allocator.dart +++ b/pkgs/code_builder/lib/src/allocator.dart @@ -57,9 +57,7 @@ class _Allocator implements Allocator { } @override - Iterable get imports { - return _imports.map((u) => Directive.import(u)); - } + Iterable get imports => _imports.map((u) => Directive.import(u)); } class _NullAllocator implements Allocator { @@ -90,9 +88,7 @@ class _PrefixedAllocator implements Allocator { int _nextKey() => _keys++; @override - Iterable get imports { - return _imports.keys.map( - (u) => Directive.import(u, as: '_i${_imports[u]}'), - ); - } + Iterable get imports => _imports.keys.map( + (u) => Directive.import(u, as: '_i${_imports[u]}'), + ); } diff --git a/pkgs/code_builder/lib/src/base.dart b/pkgs/code_builder/lib/src/base.dart index 529dd5be9..d2a5eb11a 100644 --- a/pkgs/code_builder/lib/src/base.dart +++ b/pkgs/code_builder/lib/src/base.dart @@ -17,7 +17,6 @@ class _LazySpec implements Spec { const _LazySpec(this.generate); @override - R accept(SpecVisitor visitor, [R context]) { - return generate().accept(visitor, context); - } + R accept(SpecVisitor visitor, [R context]) => + generate().accept(visitor, context); } diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 870d45954..c31409275 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -77,10 +77,9 @@ class DartEmitter extends Object /// Creates a new instance of [DartEmitter] with simple automatic imports. factory DartEmitter.scoped( - {bool orderDirectives = false, bool useNullSafetySyntax = false}) { - return DartEmitter( - Allocator.simplePrefixing(), orderDirectives, useNullSafetySyntax); - } + {bool orderDirectives = false, bool useNullSafetySyntax = false}) => + DartEmitter( + Allocator.simplePrefixing(), orderDirectives, useNullSafetySyntax); static bool _isLambdaBody(Code code) => code is ToCodeExpression && !code.isStatement; @@ -497,9 +496,8 @@ class DartEmitter extends Object } @override - StringSink visitReference(Reference spec, [StringSink output]) { - return (output ??= StringBuffer())..write(allocator.allocate(spec)); - } + StringSink visitReference(Reference spec, [StringSink output]) => + (output ??= StringBuffer())..write(allocator.allocate(spec)); @override StringSink visitSpec(Spec spec, [StringSink output]) => diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index dda8ac8ec..924e0e0b4 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -27,9 +27,7 @@ class EqualsDart extends Matcher { /// By default, uses [collapseWhitespace], but it is recommended to instead /// use `dart_style` (dartfmt) where possible. See `test/common.dart` for an /// example. - static String Function(String) format = (String source) { - return collapseWhitespace(source); - }; + static String Function(String) format = collapseWhitespace; static String _format(String source) { try { @@ -52,18 +50,19 @@ class EqualsDart extends Matcher { Description describeMismatch( covariant Spec item, Description mismatchDescription, - state, + matchState, verbose, ) { final result = _dart(item, _emitter); return equals(result).describeMismatch( _source, mismatchDescription.add(result), - state, + matchState, verbose, ); } @override - bool matches(covariant Spec item, _) => _dart(item, _emitter) == _source; + bool matches(covariant Spec item, matchState) => + _dart(item, _emitter) == _source; } diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index 4ebabd104..b96d502cd 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -48,16 +48,14 @@ abstract class Code implements Spec { abstract class Block implements Built, Code, Spec { factory Block([void Function(BlockBuilder) updates]) = _$Block; - factory Block.of(Iterable statements) { - return Block((b) => b..statements.addAll(statements)); - } + factory Block.of(Iterable statements) => + Block((b) => b..statements.addAll(statements)); Block._(); @override - R accept(covariant CodeVisitor visitor, [R context]) { - return visitor.visitBlock(this, context); - } + R accept(covariant CodeVisitor visitor, [R context]) => + visitor.visitBlock(this, context); BuiltList get statements; } @@ -121,9 +119,8 @@ class LazyCode implements Code { const LazyCode._(this.generate); @override - R accept(CodeVisitor visitor, [R context]) { - return generate(visitor).accept(visitor, context); - } + R accept(CodeVisitor visitor, [R context]) => + generate(visitor).accept(visitor, context); } /// Returns a generic [Code] that is lazily generated when visited. @@ -135,9 +132,8 @@ class _LazyCode implements Code { const _LazyCode(this.generate); @override - R accept(CodeVisitor visitor, [R context]) { - return generate().accept(visitor, context); - } + R accept(CodeVisitor visitor, [R context]) => + generate().accept(visitor, context); } /// Represents a simple, literal code block to be inserted as-is. @@ -147,9 +143,8 @@ class StaticCode implements Code { const StaticCode._(this.code); @override - R accept(CodeVisitor visitor, [R context]) { - return visitor.visitStaticCode(this, context); - } + R accept(CodeVisitor visitor, [R context]) => + visitor.visitStaticCode(this, context); @override String toString() => code; @@ -162,9 +157,8 @@ class ScopedCode implements Code { const ScopedCode._(this.code); @override - R accept(CodeVisitor visitor, [R context]) { - return visitor.visitScopedCode(this, context); - } + R accept(CodeVisitor visitor, [R context]) => + visitor.visitScopedCode(this, context); @override String toString() => code((ref) => ref.symbol); diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index f84bdb49d..2f67a3ceb 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -37,311 +37,254 @@ abstract class Expression implements Spec { /// The expression as a valid [Code] block. /// /// Also see [statement]. - Code get code => ToCodeExpression(this, false); + Code get code => ToCodeExpression(this); /// The expression as a valid [Code] block with a trailing `;`. Code get statement => ToCodeExpression(this, true); /// Returns the result of `this` `&&` [other]. - Expression and(Expression other) { - return BinaryExpression._(expression, other, '&&'); - } + Expression and(Expression other) => + BinaryExpression._(expression, other, '&&'); /// Returns the result of `this` `||` [other]. - Expression or(Expression other) { - return BinaryExpression._(expression, other, '||'); - } + Expression or(Expression other) => + BinaryExpression._(expression, other, '||'); /// Returns the result of `!this`. - Expression negate() { - return BinaryExpression._(_empty, expression, '!', addSpace: false); - } + Expression negate() => + BinaryExpression._(_empty, expression, '!', addSpace: false); /// Returns the result of `this` `as` [other]. - Expression asA(Expression other) { - return CodeExpression(Block.of([ - const Code('('), - BinaryExpression._( - expression, - other, - 'as', - ).code, - const Code(')') - ])); - } + Expression asA(Expression other) => CodeExpression(Block.of([ + const Code('('), + BinaryExpression._( + expression, + other, + 'as', + ).code, + const Code(')') + ])); /// Returns accessing the index operator (`[]`) on `this`. - Expression index(Expression index) { - return BinaryExpression._( - expression, - CodeExpression(Block.of([ - const Code('['), - index.code, - const Code(']'), - ])), - '', - ); - } + Expression index(Expression index) => BinaryExpression._( + expression, + CodeExpression(Block.of([ + const Code('['), + index.code, + const Code(']'), + ])), + '', + ); /// Returns the result of `this` `is` [other]. - Expression isA(Expression other) { - return BinaryExpression._( - expression, - other, - 'is', - ); - } + Expression isA(Expression other) => BinaryExpression._( + expression, + other, + 'is', + ); /// Returns the result of `this` `is!` [other]. - Expression isNotA(Expression other) { - return BinaryExpression._( - expression, - other, - 'is!', - ); - } + Expression isNotA(Expression other) => BinaryExpression._( + expression, + other, + 'is!', + ); /// Returns the result of `this` `==` [other]. - Expression equalTo(Expression other) { - return BinaryExpression._( - expression, - other, - '==', - ); - } + Expression equalTo(Expression other) => BinaryExpression._( + expression, + other, + '==', + ); /// Returns the result of `this` `!=` [other]. - Expression notEqualTo(Expression other) { - return BinaryExpression._( - expression, - other, - '!=', - ); - } + Expression notEqualTo(Expression other) => BinaryExpression._( + expression, + other, + '!=', + ); /// Returns the result of `this` `>` [other]. - Expression greaterThan(Expression other) { - return BinaryExpression._( - expression, - other, - '>', - ); - } + Expression greaterThan(Expression other) => BinaryExpression._( + expression, + other, + '>', + ); /// Returns the result of `this` `<` [other]. - Expression lessThan(Expression other) { - return BinaryExpression._( - expression, - other, - '<', - ); - } + Expression lessThan(Expression other) => BinaryExpression._( + expression, + other, + '<', + ); /// Returns the result of `this` `>=` [other]. - Expression greaterOrEqualTo(Expression other) { - return BinaryExpression._( - expression, - other, - '>=', - ); - } + Expression greaterOrEqualTo(Expression other) => BinaryExpression._( + expression, + other, + '>=', + ); /// Returns the result of `this` `<=` [other]. - Expression lessOrEqualTo(Expression other) { - return BinaryExpression._( - expression, - other, - '<=', - ); - } + Expression lessOrEqualTo(Expression other) => BinaryExpression._( + expression, + other, + '<=', + ); /// Returns the result of `this` `+` [other]. - Expression operatorAdd(Expression other) { - return BinaryExpression._( - expression, - other, - '+', - ); - } + Expression operatorAdd(Expression other) => BinaryExpression._( + expression, + other, + '+', + ); /// Returns the result of `this` `-` [other]. - Expression operatorSubstract(Expression other) { - return BinaryExpression._( - expression, - other, - '-', - ); - } + Expression operatorSubstract(Expression other) => BinaryExpression._( + expression, + other, + '-', + ); /// Returns the result of `this` `/` [other]. - Expression operatorDivide(Expression other) { - return BinaryExpression._( - expression, - other, - '/', - ); - } + Expression operatorDivide(Expression other) => BinaryExpression._( + expression, + other, + '/', + ); /// Returns the result of `this` `*` [other]. - Expression operatorMultiply(Expression other) { - return BinaryExpression._( - expression, - other, - '*', - ); - } + Expression operatorMultiply(Expression other) => BinaryExpression._( + expression, + other, + '*', + ); /// Returns the result of `this` `%` [other]. - Expression operatorEuclideanModulo(Expression other) { - return BinaryExpression._( - expression, - other, - '%', - ); - } + Expression operatorEuclideanModulo(Expression other) => BinaryExpression._( + expression, + other, + '%', + ); - Expression conditional(Expression whenTrue, Expression whenFalse) { - return BinaryExpression._( - expression, - BinaryExpression._(whenTrue, whenFalse, ':'), - '?', - ); - } + Expression conditional(Expression whenTrue, Expression whenFalse) => + BinaryExpression._( + expression, + BinaryExpression._(whenTrue, whenFalse, ':'), + '?', + ); /// This expression preceded by `await`. - Expression get awaited { - return BinaryExpression._( - _empty, - this, - 'await', - ); - } + Expression get awaited => BinaryExpression._( + _empty, + this, + 'await', + ); /// Return `{other} = {this}`. - Expression assign(Expression other) { - return BinaryExpression._( - this, - other, - '=', - ); - } + Expression assign(Expression other) => BinaryExpression._( + this, + other, + '=', + ); /// Return `{other} ?? {this}`. - Expression ifNullThen(Expression other) { - return BinaryExpression._( - this, - other, - '??', - ); - } + Expression ifNullThen(Expression other) => BinaryExpression._( + this, + other, + '??', + ); /// Return `{other} ??= {this}`. - Expression assignNullAware(Expression other) { - return BinaryExpression._( - this, - other, - '??=', - ); - } + Expression assignNullAware(Expression other) => BinaryExpression._( + this, + other, + '??=', + ); /// Return `var {name} = {this}`. - Expression assignVar(String name, [Reference type]) { - return BinaryExpression._( - type == null - ? LiteralExpression._('var $name') - : BinaryExpression._( - type.expression, - LiteralExpression._(name), - '', - ), - this, - '=', - ); - } + Expression assignVar(String name, [Reference type]) => BinaryExpression._( + type == null + ? LiteralExpression._('var $name') + : BinaryExpression._( + type.expression, + LiteralExpression._(name), + '', + ), + this, + '=', + ); /// Return `final {name} = {this}`. - Expression assignFinal(String name, [Reference type]) { - return BinaryExpression._( - type == null - ? const LiteralExpression._('final') - : BinaryExpression._( - const LiteralExpression._('final'), - type.expression, - '', - ), - this, - '$name =', - ); - } + Expression assignFinal(String name, [Reference type]) => BinaryExpression._( + type == null + ? const LiteralExpression._('final') + : BinaryExpression._( + const LiteralExpression._('final'), + type.expression, + '', + ), + this, + '$name =', + ); /// Return `const {name} = {this}`. - Expression assignConst(String name, [Reference type]) { - return BinaryExpression._( - type == null - ? const LiteralExpression._('const') - : BinaryExpression._( - const LiteralExpression._('const'), - type.expression, - '', - ), - this, - '$name =', - isConst: true, - ); - } + Expression assignConst(String name, [Reference type]) => BinaryExpression._( + type == null + ? const LiteralExpression._('const') + : BinaryExpression._( + const LiteralExpression._('const'), + type.expression, + '', + ), + this, + '$name =', + isConst: true, + ); /// Call this expression as a method. Expression call( Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], - ]) { - return InvokeExpression._( - this, - positionalArguments.toList(), - namedArguments, - typeArguments, - ); - } + ]) => + InvokeExpression._( + this, + positionalArguments.toList(), + namedArguments, + typeArguments, + ); /// Returns an expression accessing `.` on this expression. - Expression property(String name) { - return BinaryExpression._( - this, - LiteralExpression._(name), - '.', - addSpace: false, - ); - } + Expression property(String name) => BinaryExpression._( + this, + LiteralExpression._(name), + '.', + addSpace: false, + ); /// Returns an expression accessing `..` on this expression. - Expression cascade(String name) { - return BinaryExpression._( - this, - LiteralExpression._(name), - '..', - addSpace: false, - ); - } + Expression cascade(String name) => BinaryExpression._( + this, + LiteralExpression._(name), + '..', + addSpace: false, + ); /// Returns an expression accessing `?.` on this expression. - Expression nullSafeProperty(String name) { - return BinaryExpression._( - this, - LiteralExpression._(name), - '?.', - addSpace: false, - ); - } + Expression nullSafeProperty(String name) => BinaryExpression._( + this, + LiteralExpression._(name), + '?.', + addSpace: false, + ); /// This expression preceded by `return`. - Expression get returned { - return BinaryExpression._( - const LiteralExpression._('return'), - this, - '', - ); - } + Expression get returned => BinaryExpression._( + const LiteralExpression._('return'), + this, + '', + ); /// May be overridden to support other types implementing [Expression]. @visibleForOverriding @@ -363,10 +306,8 @@ class ToCodeExpression implements Code { const ToCodeExpression(this.code, [this.isStatement = false]); @override - R accept(CodeVisitor visitor, [R context]) { - return (visitor as ExpressionVisitor) - .visitToCodeExpression(this, context); - } + R accept(CodeVisitor visitor, [R context]) => + (visitor as ExpressionVisitor).visitToCodeExpression(this, context); @override String toString() => code.toString(); diff --git a/pkgs/code_builder/lib/src/specs/expression/binary.dart b/pkgs/code_builder/lib/src/specs/expression/binary.dart index 1f7e76e4d..b3a8808b2 100644 --- a/pkgs/code_builder/lib/src/specs/expression/binary.dart +++ b/pkgs/code_builder/lib/src/specs/expression/binary.dart @@ -21,7 +21,6 @@ class BinaryExpression extends Expression { }); @override - R accept(ExpressionVisitor visitor, [R context]) { - return visitor.visitBinaryExpression(this, context); - } + R accept(ExpressionVisitor visitor, [R context]) => + visitor.visitBinaryExpression(this, context); } diff --git a/pkgs/code_builder/lib/src/specs/expression/closure.dart b/pkgs/code_builder/lib/src/specs/expression/closure.dart index 1af27609a..f10eeeed1 100644 --- a/pkgs/code_builder/lib/src/specs/expression/closure.dart +++ b/pkgs/code_builder/lib/src/specs/expression/closure.dart @@ -18,7 +18,6 @@ class ClosureExpression extends Expression { const ClosureExpression._(this.method); @override - R accept(ExpressionVisitor visitor, [R context]) { - return visitor.visitClosureExpression(this, context); - } + R accept(ExpressionVisitor visitor, [R context]) => + visitor.visitClosureExpression(this, context); } diff --git a/pkgs/code_builder/lib/src/specs/expression/code.dart b/pkgs/code_builder/lib/src/specs/expression/code.dart index 7465448e7..3a5421937 100644 --- a/pkgs/code_builder/lib/src/specs/expression/code.dart +++ b/pkgs/code_builder/lib/src/specs/expression/code.dart @@ -13,7 +13,6 @@ class CodeExpression extends Expression { const CodeExpression(this.code); @override - R accept(ExpressionVisitor visitor, [R context]) { - return visitor.visitCodeExpression(this, context); - } + R accept(ExpressionVisitor visitor, [R context]) => + visitor.visitCodeExpression(this, context); } diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index 3ac586fe3..fb563952c 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -42,9 +42,8 @@ class InvokeExpression extends Expression { ]) : type = InvokeExpressionType.constInstance; @override - R accept(ExpressionVisitor visitor, [R context]) { - return visitor.visitInvokeExpression(this, context); - } + R accept(ExpressionVisitor visitor, [R context]) => + visitor.visitInvokeExpression(this, context); @override String toString() => diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index ba2e7b903..b4ae81a1e 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -66,42 +66,36 @@ Expression literalString(String value, {bool raw = false}) { } /// Creates a literal list expression from [values]. -LiteralListExpression literalList(Iterable values, [Reference type]) { - return LiteralListExpression._(false, values.toList(), type); -} +LiteralListExpression literalList(Iterable values, [Reference type]) => + LiteralListExpression._(false, values.toList(), type); /// Creates a literal `const` list expression from [values]. -LiteralListExpression literalConstList(List values, [Reference type]) { - return LiteralListExpression._(true, values, type); -} +LiteralListExpression literalConstList(List values, [Reference type]) => + LiteralListExpression._(true, values, type); /// Creates a literal set expression from [values]. -LiteralSetExpression literalSet(Iterable values, [Reference type]) { - return LiteralSetExpression._(false, values.toSet(), type); -} +LiteralSetExpression literalSet(Iterable values, [Reference type]) => + LiteralSetExpression._(false, values.toSet(), type); /// Creates a literal `const` set expression from [values]. -LiteralSetExpression literalConstSet(Set values, [Reference type]) { - return LiteralSetExpression._(true, values, type); -} +LiteralSetExpression literalConstSet(Set values, [Reference type]) => + LiteralSetExpression._(true, values, type); /// Create a literal map expression from [values]. LiteralMapExpression literalMap( Map values, [ Reference keyType, Reference valueType, -]) { - return LiteralMapExpression._(false, values, keyType, valueType); -} +]) => + LiteralMapExpression._(false, values, keyType, valueType); /// Create a literal `const` map expression from [values]. LiteralMapExpression literalConstMap( Map values, [ Reference keyType, Reference valueType, -]) { - return LiteralMapExpression._(true, values, keyType, valueType); -} +]) => + LiteralMapExpression._(true, values, keyType, valueType); /// Represents a literal value in Dart source code. /// @@ -119,9 +113,8 @@ class LiteralExpression extends Expression { const LiteralExpression._(this.literal); @override - R accept(ExpressionVisitor visitor, [R context]) { - return visitor.visitLiteralExpression(this, context); - } + R accept(ExpressionVisitor visitor, [R context]) => + visitor.visitLiteralExpression(this, context); @override String toString() => literal; @@ -135,9 +128,8 @@ class LiteralListExpression extends Expression { const LiteralListExpression._(this.isConst, this.values, this.type); @override - R accept(ExpressionVisitor visitor, [R context]) { - return visitor.visitLiteralListExpression(this, context); - } + R accept(ExpressionVisitor visitor, [R context]) => + visitor.visitLiteralListExpression(this, context); @override String toString() => '[${values.map(literal).join(', ')}]'; @@ -151,9 +143,8 @@ class LiteralSetExpression extends Expression { const LiteralSetExpression._(this.isConst, this.values, this.type); @override - R accept(ExpressionVisitor visitor, [R context]) { - return visitor.visitLiteralSetExpression(this, context); - } + R accept(ExpressionVisitor visitor, [R context]) => + visitor.visitLiteralSetExpression(this, context); @override String toString() => '{${values.map(literal).join(', ')}}'; @@ -173,9 +164,8 @@ class LiteralMapExpression extends Expression { ); @override - R accept(ExpressionVisitor visitor, [R context]) { - return visitor.visitLiteralMapExpression(this, context); - } + R accept(ExpressionVisitor visitor, [R context]) => + visitor.visitLiteralMapExpression(this, context); @override String toString() => '{$values}'; diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 3172711e6..cd6ae1e12 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -17,7 +17,7 @@ import 'reference.dart'; part 'method.g.dart'; -final Reference _$void = const Reference('void'); +const _$void = Reference('void'); @immutable abstract class Method extends Object @@ -25,14 +25,13 @@ abstract class Method extends Object implements Built, Spec { factory Method([void Function(MethodBuilder) updates]) = _$Method; - factory Method.returnsVoid([void Function(MethodBuilder) updates]) { - return Method((b) { - if (updates != null) { - updates(b); - } - b.returns = _$void; - }); - } + factory Method.returnsVoid([void Function(MethodBuilder) updates]) => + Method((b) { + if (updates != null) { + updates(b); + } + b.returns = _$void; + }); Method._(); diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 102d33040..355d84c4a 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -14,9 +14,7 @@ import 'expression.dart'; import 'type_reference.dart'; /// Short-hand for `Reference(symbol, url)`. -Reference refer(String symbol, [String url]) { - return Reference(symbol, url); -} +Reference refer(String symbol, [String url]) => Reference(symbol, url); /// A reference to [symbol], such as a class, or top-level method or field. /// @@ -46,23 +44,21 @@ class Reference extends Expression implements Spec { int get hashCode => '$url#$symbol'.hashCode; @override - bool operator ==(Object o) => - o is Reference && o.url == url && o.symbol == symbol; + bool operator ==(Object other) => + other is Reference && other.url == url && other.symbol == symbol; /// Returns a new instance of this expression. Expression newInstance( Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], - ]) { - return InvokeExpression.newOf( - this, - positionalArguments.toList(), - namedArguments, - typeArguments, - null, - ); - } + ]) => + InvokeExpression.newOf( + this, + positionalArguments.toList(), + namedArguments, + typeArguments, + ); /// Returns a new instance of this expression with a named constructor. Expression newInstanceNamed( @@ -70,30 +66,27 @@ class Reference extends Expression implements Spec { Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], - ]) { - return InvokeExpression.newOf( - this, - positionalArguments.toList(), - namedArguments, - typeArguments, - name, - ); - } + ]) => + InvokeExpression.newOf( + this, + positionalArguments.toList(), + namedArguments, + typeArguments, + name, + ); /// Returns a const instance of this expression. Expression constInstance( Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], - ]) { - return InvokeExpression.constOf( - this, - positionalArguments.toList(), - namedArguments, - typeArguments, - null, - ); - } + ]) => + InvokeExpression.constOf( + this, + positionalArguments.toList(), + namedArguments, + typeArguments, + ); /// Returns a const instance of this expression with a named constructor. Expression constInstanceNamed( @@ -101,20 +94,17 @@ class Reference extends Expression implements Spec { Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], - ]) { - return InvokeExpression.constOf( - this, - positionalArguments.toList(), - namedArguments, - typeArguments, - name, - ); - } + ]) => + InvokeExpression.constOf( + this, + positionalArguments.toList(), + namedArguments, + typeArguments, + name, + ); @override - Expression get expression { - return CodeExpression(Code.scope((a) => a(this))); - } + Expression get expression => CodeExpression(Code.scope((a) => a(this))); @override String toString() => (newBuiltValueToStringHelper('Reference') diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index dee684e70..4424598f7 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -54,9 +54,7 @@ abstract class TypeReference extends Expression visitor.visitType(this, context); @override - Expression get expression { - return CodeExpression(Code.scope((a) => a(this))); - } + Expression get expression => CodeExpression(Code.scope((a) => a(this))); @override TypeReference get type => this; @@ -66,15 +64,13 @@ abstract class TypeReference extends Expression Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], - ]) { - return InvokeExpression.newOf( - this, - positionalArguments.toList(), - namedArguments, - typeArguments, - null, - ); - } + ]) => + InvokeExpression.newOf( + this, + positionalArguments.toList(), + namedArguments, + typeArguments, + ); @override Expression newInstanceNamed( @@ -82,30 +78,27 @@ abstract class TypeReference extends Expression Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], - ]) { - return InvokeExpression.newOf( - this, - positionalArguments.toList(), - namedArguments, - typeArguments, - name, - ); - } + ]) => + InvokeExpression.newOf( + this, + positionalArguments.toList(), + namedArguments, + typeArguments, + name, + ); @override Expression constInstance( Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], - ]) { - return InvokeExpression.constOf( - this, - positionalArguments.toList(), - namedArguments, - typeArguments, - null, - ); - } + ]) => + InvokeExpression.constOf( + this, + positionalArguments.toList(), + namedArguments, + typeArguments, + ); @override Expression constInstanceNamed( @@ -113,15 +106,14 @@ abstract class TypeReference extends Expression Iterable positionalArguments, [ Map namedArguments = const {}, List typeArguments = const [], - ]) { - return InvokeExpression.constOf( - this, - positionalArguments.toList(), - namedArguments, - typeArguments, - name, - ); - } + ]) => + InvokeExpression.constOf( + this, + positionalArguments.toList(), + namedArguments, + typeArguments, + name, + ); } abstract class TypeReferenceBuilder extends Object diff --git a/pkgs/code_builder/tool/src/builder.dart b/pkgs/code_builder/tool/src/builder.dart index ff9581495..3863325de 100644 --- a/pkgs/code_builder/tool/src/builder.dart +++ b/pkgs/code_builder/tool/src/builder.dart @@ -7,8 +7,6 @@ import 'package:built_value_generator/built_value_generator.dart'; import 'package:source_gen/source_gen.dart'; /// Returns a [Builder] to generate `.g.dart` files for `built_value`. -Builder builtValueBuilder(BuilderOptions _) { - return PartBuilder([ - const BuiltValueGenerator(), - ], '.g.dart'); -} +Builder builtValueBuilder(BuilderOptions _) => PartBuilder([ + const BuiltValueGenerator(), + ], '.g.dart'); From f5607aa7c01cd4fd742dcc46fd8af5083e505a10 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 9 Jun 2020 13:42:25 -0700 Subject: [PATCH 157/271] Add an isNullable field to FunctionType (dart-lang/code_builder#284) --- pkgs/code_builder/lib/src/emitter.dart | 6 ++- .../lib/src/specs/type_function.dart | 9 +++++ .../lib/src/specs/type_function.g.dart | 37 ++++++++++++++---- .../test/specs/code/expression_test.dart | 39 +++++++++++++++++++ 4 files changed, 82 insertions(+), 9 deletions(-) diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index c31409275..ce197b1dd 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -373,7 +373,11 @@ class DartEmitter extends Object }); output.write('}'); } - return output..write(')'); + output.write(')'); + if (_useNullSafetySyntax && (spec.isNullable ?? false)) { + output.write('?'); + } + return output; } @override diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index f4187bb21..c10ca5188 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -57,6 +57,13 @@ abstract class FunctionType extends Expression @override Reference get type => this; + /// Optional nullability. + /// + /// An emitter may ignore this if the output is not targeting a Dart language + /// version that supports null safety. + @nullable + bool get isNullable; + @override Expression newInstance( Iterable positionalArguments, [ @@ -113,4 +120,6 @@ abstract class FunctionTypeBuilder extends Object MapBuilder namedParameters = MapBuilder(); + + bool isNullable; } diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart index 8b0f673a2..2c9906c0d 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -17,6 +17,8 @@ class _$FunctionType extends FunctionType { final BuiltList optionalParameters; @override final BuiltMap namedParameters; + @override + final bool isNullable; factory _$FunctionType([void Function(FunctionTypeBuilder) updates]) => (new FunctionTypeBuilder()..update(updates)).build() as _$FunctionType; @@ -26,7 +28,8 @@ class _$FunctionType extends FunctionType { this.types, this.requiredParameters, this.optionalParameters, - this.namedParameters}) + this.namedParameters, + this.isNullable}) : super._() { if (types == null) { throw new BuiltValueNullFieldError('FunctionType', 'types'); @@ -58,17 +61,20 @@ class _$FunctionType extends FunctionType { types == other.types && requiredParameters == other.requiredParameters && optionalParameters == other.optionalParameters && - namedParameters == other.namedParameters; + namedParameters == other.namedParameters && + isNullable == other.isNullable; } @override int get hashCode { return $jf($jc( $jc( - $jc($jc($jc(0, returnType.hashCode), types.hashCode), - requiredParameters.hashCode), - optionalParameters.hashCode), - namedParameters.hashCode)); + $jc( + $jc($jc($jc(0, returnType.hashCode), types.hashCode), + requiredParameters.hashCode), + optionalParameters.hashCode), + namedParameters.hashCode), + isNullable.hashCode)); } @override @@ -78,7 +84,8 @@ class _$FunctionType extends FunctionType { ..add('types', types) ..add('requiredParameters', requiredParameters) ..add('optionalParameters', optionalParameters) - ..add('namedParameters', namedParameters)) + ..add('namedParameters', namedParameters) + ..add('isNullable', isNullable)) .toString(); } } @@ -146,6 +153,18 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { super.namedParameters = namedParameters; } + @override + bool get isNullable { + _$this; + return super.isNullable; + } + + @override + set isNullable(bool isNullable) { + _$this; + super.isNullable = isNullable; + } + _$FunctionTypeBuilder() : super._(); FunctionTypeBuilder get _$this { @@ -155,6 +174,7 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { super.requiredParameters = _$v.requiredParameters?.toBuilder(); super.optionalParameters = _$v.optionalParameters?.toBuilder(); super.namedParameters = _$v.namedParameters?.toBuilder(); + super.isNullable = _$v.isNullable; _$v = null; } return this; @@ -183,7 +203,8 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { types: types.build(), requiredParameters: requiredParameters.build(), optionalParameters: optionalParameters.build(), - namedParameters: namedParameters.build()); + namedParameters: namedParameters.build(), + isNullable: isNullable); } catch (_) { String _$failedField; try { diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 467ec5acf..196fcab62 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -301,6 +301,45 @@ void main() { ); }); + test('should emit a nullable function type in a Null Safety library', () { + final emitter = DartEmitter.scoped(useNullSafetySyntax: true); + expect( + FunctionType((b) => b + ..requiredParameters.add(refer('String')) + ..isNullable = true), + equalsDart('Function(String)?', emitter), + ); + }); + + test('should emit a nullable function type in pre-Null Safety library', () { + expect( + FunctionType((b) => b + ..requiredParameters.add(refer('String')) + ..isNullable = true), + equalsDart('Function(String)'), + ); + }); + + test('should emit a non-nullable function type in a Null Safety library', () { + final emitter = DartEmitter.scoped(useNullSafetySyntax: true); + expect( + FunctionType((b) => b + ..requiredParameters.add(refer('String')) + ..isNullable = false), + equalsDart('Function(String)', emitter), + ); + }); + + test('should emit a non-nullable function type in pre-Null Safety library', + () { + expect( + FunctionType((b) => b + ..requiredParameters.add(refer('String')) + ..isNullable = false), + equalsDart('Function(String)'), + ); + }); + test('should emit a closure', () { expect( refer('map').property('putIfAbsent').call([ From b7a545367beed9c8589bbde56a4e6ef4a2c7be5e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 9 Jun 2020 15:25:52 -0700 Subject: [PATCH 158/271] Explicitly use SDK dartfmt (dart-lang/code_builder#285) Trying to fix CI --- pkgs/code_builder/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index 342584ece..b425c9ff0 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -7,7 +7,7 @@ dart: dart_task: - test - dartanalyzer: --fatal-infos --fatal-warnings . -- dartfmt +- dartfmt: sdk branches: only: [master] From 7a43c6fea7d2af12381dbe5eb6ed1800ccf820c7 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 18 Jun 2020 09:55:02 -0700 Subject: [PATCH 159/271] Add a thrown getter to Expression (dart-lang/code_builder#287) Fixes dart-lang/code_builder#286 Allow an expression to be thrown as part of a function expression body, or as a statement with `.statement`. --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/lib/src/specs/expression.dart | 7 +++++++ pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/code/expression_test.dart | 7 +++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 8ebb1ae33..1e3801352 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.4.0-dev + +* Introduce `Expression.thrown` for throwing an expression. + ## 3.3.0 * Add `??` null-aware operator. diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 2f67a3ceb..c186a7ee5 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -286,6 +286,13 @@ abstract class Expression implements Spec { '', ); + /// This expression preceded by `throw`. + Expression get thrown => BinaryExpression._( + const LiteralExpression._('throw'), + this, + '', + ); + /// May be overridden to support other types implementing [Expression]. @visibleForOverriding Expression get expression => this; diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 1f48321f2..6c7f466cb 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.3.0 +version: 3.4.0-dev description: >- A fluent, builder-based library for generating valid Dart code diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 196fcab62..cecbc66a3 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -453,6 +453,13 @@ void main() { ); }); + test('should emit throw', () { + expect( + literalNull.thrown, + equalsDart('throw null'), + ); + }); + test('should emit an explicit cast', () { expect( refer('foo').asA(refer('String')).property('length'), From 1fd404f87656ae3c34d2086e61eb83cb78e68240 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 6 Jul 2020 15:51:41 -0700 Subject: [PATCH 160/271] Bump min Dart SDK to 2.7 (dart-lang/code_builder#290) Works-around issue with testing Dart 2.6 in CI and changes to pkg:analyzer Specifically, it seems there was a change to a non-public analyzer API that is picked up by packages on Dart 2.6 but the SDK constraint on `dart_style` prevents picking up a version of that package with the fix. --- pkgs/code_builder/.travis.yml | 2 +- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml index b425c9ff0..dda7d52d5 100644 --- a/pkgs/code_builder/.travis.yml +++ b/pkgs/code_builder/.travis.yml @@ -2,7 +2,7 @@ language: dart dart: - dev - - 2.6.0 + - 2.7.0 dart_task: - test diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 1e3801352..a727d4f1d 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ ## 3.4.0-dev * Introduce `Expression.thrown` for throwing an expression. +* Update SDK requirement to `>=2.7.0 <3.0.0`. ## 3.3.0 diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 6c7f466cb..d759ecc18 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -6,7 +6,7 @@ description: >- homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=2.6.0 <3.0.0' + sdk: '>=2.7.0 <3.0.0' dependencies: built_collection: '>=3.0.0 <5.0.0' From 51a1617ee54b7818c46cd79d5f716e20c1256a1c Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 8 Jul 2020 09:55:50 -0700 Subject: [PATCH 161/271] Bump to 3.4.0 (dart-lang/code_builder#291) --- pkgs/code_builder/CHANGELOG.md | 6 +++++- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index a727d4f1d..e296c8de2 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ -## 3.4.0-dev +## 3.4.0 * Introduce `Expression.thrown` for throwing an expression. +* Introduce `FunctionType.isNullable`. * Update SDK requirement to `>=2.7.0 <3.0.0`. ## 3.3.0 @@ -8,6 +9,9 @@ * Add `??` null-aware operator. * Add `..` cascade assignment operator. * Add `part` directive. +* Introduce `TypeReference.isNullable`. +* Add an option in `DartEmitter` to emit nullable types with trailing `?` + characters. ## 3.2.2 diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index d759ecc18..053ccd058 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.4.0-dev +version: 3.4.0 description: >- A fluent, builder-based library for generating valid Dart code From 7f62294ed0df825de3478b723c53de488ce27a08 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 13 Aug 2020 12:10:06 -0700 Subject: [PATCH 162/271] Flip expected and actual in mismatch description (dart-lang/code_builder#294) Fixes dart-lang/code_builder#293 When describing a mismatch the _expected_ value should be passed to `equals`, not the actual value. Also remove the source from the start of the mismatch description since it's already present in the nested "Actual" field. Other refactoring: - Rename `_source` to `_expectedSource` and `result` to `actualSource` for clarity. - Expand the doc comment for `equalsDart`. --- pkgs/code_builder/CHANGELOG.md | 5 ++++ pkgs/code_builder/lib/src/matchers.dart | 23 +++++++++++------- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/matcher_test.dart | 30 ++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 pkgs/code_builder/test/matcher_test.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index e296c8de2..1d775d41d 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,8 @@ +## 3.4.1-dev + +* Fix confusing mismatch description from `equalsDart`. + https://github.com/dart-lang/code_builder/issues/293 + ## 3.4.0 * Introduce `Expression.thrown` for throwing an expression. diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index 924e0e0b4..a443ce925 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -11,7 +11,11 @@ import 'emitter.dart'; String _dart(Spec spec, DartEmitter emitter) => EqualsDart._format(spec.accept(emitter).toString()); -/// Returns a matcher for Dart source code. +/// Returns a matcher for [Spec] objects that emit code matching [source]. +/// +/// 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, @@ -39,12 +43,13 @@ class EqualsDart extends Matcher { } final DartEmitter _emitter; - final String _source; + final String _expectedSource; - const EqualsDart._(this._source, this._emitter); + const EqualsDart._(this._expectedSource, this._emitter); @override - Description describe(Description description) => description.add(_source); + Description describe(Description description) => + description.add(_expectedSource); @override Description describeMismatch( @@ -53,10 +58,10 @@ class EqualsDart extends Matcher { matchState, verbose, ) { - final result = _dart(item, _emitter); - return equals(result).describeMismatch( - _source, - mismatchDescription.add(result), + final actualSource = _dart(item, _emitter); + return equals(_expectedSource).describeMismatch( + actualSource, + mismatchDescription, matchState, verbose, ); @@ -64,5 +69,5 @@ class EqualsDart extends Matcher { @override bool matches(covariant Spec item, matchState) => - _dart(item, _emitter) == _source; + _dart(item, _emitter) == _expectedSource; } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 053ccd058..aa44389eb 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.4.0 +version: 3.4.1-dev description: >- A fluent, builder-based library for generating valid Dart code diff --git a/pkgs/code_builder/test/matcher_test.dart b/pkgs/code_builder/test/matcher_test.dart new file mode 100644 index 000000000..c9475a847 --- /dev/null +++ b/pkgs/code_builder/test/matcher_test.dart @@ -0,0 +1,30 @@ +// Copyright (c) 2020, 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:test/test.dart'; + +void main() { + test('describes mismatches', () { + const actual = Code('final x=1;'); + equalsDart('final y=2;').expectMismatch(actual, ''' + Expected: final y=2; + Actual: StaticCode: + Which: is different. + Expected: final y=2; + Actual: final x=1; + ^ + Differ at offset 6 +'''); + }); +} + +extension on Matcher { + void expectMismatch(dynamic actual, String mismatch) { + expect( + () => expect(actual, this), + throwsA(isA().having( + (e) => e.message, 'message', equalsIgnoringWhitespace(mismatch)))); + } +} From 24fc5f53ee32ffdf3199f7903f2d3b5f49627cdb Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 17 Aug 2020 19:49:22 -0700 Subject: [PATCH 163/271] Prepare to publish 3.4.1 (dart-lang/code_builder#295) --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 1d775d41d..e4c0e5038 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.4.1-dev +## 3.4.1 * Fix confusing mismatch description from `equalsDart`. https://github.com/dart-lang/code_builder/issues/293 diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index aa44389eb..3a9d0ef32 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.4.1-dev +version: 3.4.1 description: >- A fluent, builder-based library for generating valid Dart code From c8c4deb40163d6244f8ba6ab124c2f0e5f6dec49 Mon Sep 17 00:00:00 2001 From: Tarekk Mohamed Abdalla Date: Mon, 28 Sep 2020 19:26:20 +0200 Subject: [PATCH 164/271] Add Enum support (dart-lang/code_builder#292) --- pkgs/code_builder/CHANGELOG.md | 4 + pkgs/code_builder/example/example.dart | 30 ++ pkgs/code_builder/lib/code_builder.dart | 2 + pkgs/code_builder/lib/src/emitter.dart | 19 ++ pkgs/code_builder/lib/src/specs/enum.dart | 91 ++++++ pkgs/code_builder/lib/src/specs/enum.g.dart | 323 ++++++++++++++++++++ pkgs/code_builder/lib/src/visitors.dart | 3 + pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/enum_test.dart | 76 +++++ 9 files changed, 549 insertions(+), 1 deletion(-) create mode 100644 pkgs/code_builder/lib/src/specs/enum.dart create mode 100644 pkgs/code_builder/lib/src/specs/enum.g.dart create mode 100644 pkgs/code_builder/test/specs/enum_test.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index e4c0e5038..b5c2b91bf 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.5.0 + +* Add support for defining enums. + ## 3.4.1 * Fix confusing mismatch description from `equalsDart`. diff --git a/pkgs/code_builder/example/example.dart b/pkgs/code_builder/example/example.dart index 577752bbb..6d8584fa6 100644 --- a/pkgs/code_builder/example/example.dart +++ b/pkgs/code_builder/example/example.dart @@ -10,6 +10,7 @@ final _dartfmt = DartFormatter(); void main() { print('animalClass():\n${'=' * 40}\n${animalClass()}'); print('scopedLibrary():\n${'=' * 40}\n${scopedLibrary()}'); + print('jsonEnum():\n${'=' * 40}\n${jsonEnum()}'); } /// Outputs: @@ -52,3 +53,32 @@ String scopedLibrary() { final library = Library((b) => b.body.addAll(methods)); return _dartfmt.format('${library.accept(DartEmitter.scoped())}'); } + +/// Outputs: +/// +/// ```dart +/// enum Unit { +/// @JsonKey('m') +/// metric, +/// @JsonKey('i') +/// imperial +/// } +/// ``` +String jsonEnum() { + final values = [ + 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)); + return _dartfmt.format('${e.accept(DartEmitter())}'); +} diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 2be4733f2..564299a8e 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -12,6 +12,8 @@ export 'src/specs/code.dart' export 'src/specs/constructor.dart' show Constructor, ConstructorBuilder; export 'src/specs/directive.dart' show Directive, DirectiveType, DirectiveBuilder; +export 'src/specs/enum.dart' + show Enum, EnumBuilder, EnumValue, EnumValueBuilder; export 'src/specs/expression.dart' show ToCodeExpression, diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index ce197b1dd..e993fddd9 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -8,6 +8,7 @@ import 'specs/class.dart'; import 'specs/code.dart'; import 'specs/constructor.dart'; import 'specs/directive.dart'; +import 'specs/enum.dart'; import 'specs/expression.dart'; import 'specs/field.dart'; import 'specs/library.dart'; @@ -535,6 +536,24 @@ class DartEmitter extends Object } return output; } + + @override + StringSink visitEnum(Enum spec, [StringSink output]) { + output ??= StringBuffer(); + spec.docs.forEach(output.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, output)); + output.writeln('enum ${spec.name} {'); + spec.values.forEach((v) { + v.docs.forEach(output.writeln); + v.annotations.forEach((a) => visitAnnotation(a, output)); + output.write(v.name); + if (v != spec.values.last) { + output.writeln(','); + } + }); + output.writeln('}'); + return output; + } } /// Returns `true` if: diff --git a/pkgs/code_builder/lib/src/specs/enum.dart b/pkgs/code_builder/lib/src/specs/enum.dart new file mode 100644 index 000000000..cb50ab171 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/enum.dart @@ -0,0 +1,91 @@ +// Copyright (c) 2020, 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:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; +import 'package:meta/meta.dart'; + +import '../../code_builder.dart'; +import '../mixins/annotations.dart'; +import '../mixins/dartdoc.dart'; +import '../visitors.dart'; + +part 'enum.g.dart'; + +@immutable +abstract class Enum extends Object + with HasAnnotations, HasDartDocs + implements Built, Spec { + factory Enum([void Function(EnumBuilder) updates]) = _$Enum; + + Enum._(); + + String get name; + + BuiltList get values; + + @override + BuiltList get annotations; + + @override + BuiltList get docs; + + @override + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitEnum(this, context); +} + +abstract class EnumBuilder extends Object + with HasAnnotationsBuilder, HasDartDocsBuilder + implements Builder { + factory EnumBuilder() = _$EnumBuilder; + + EnumBuilder._(); + + String name; + + ListBuilder values = ListBuilder(); + + @override + ListBuilder annotations = ListBuilder(); + + @override + ListBuilder docs = ListBuilder(); +} + +@immutable +abstract class EnumValue extends Object + with HasAnnotations, HasDartDocs + implements Built { + factory EnumValue([void Function(EnumValueBuilder) updates]) = _$EnumValue; + + EnumValue._(); + + String get name; + + @override + BuiltList get annotations; + + @override + BuiltList get docs; +} + +abstract class EnumValueBuilder extends Object + with HasAnnotationsBuilder, HasDartDocsBuilder + implements Builder { + factory EnumValueBuilder() = _$EnumValueBuilder; + + EnumValueBuilder._(); + + String name; + + @override + ListBuilder annotations = ListBuilder(); + + @override + ListBuilder docs = ListBuilder(); +} diff --git a/pkgs/code_builder/lib/src/specs/enum.g.dart b/pkgs/code_builder/lib/src/specs/enum.g.dart new file mode 100644 index 000000000..8834ebdd9 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/enum.g.dart @@ -0,0 +1,323 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'enum.dart'; + +// ************************************************************************** +// BuiltValueGenerator +// ************************************************************************** + +class _$Enum extends Enum { + @override + final String name; + @override + final BuiltList values; + @override + final BuiltList annotations; + @override + final BuiltList docs; + + factory _$Enum([void Function(EnumBuilder) updates]) => + (new EnumBuilder()..update(updates)).build() as _$Enum; + + _$Enum._({this.name, this.values, this.annotations, this.docs}) : super._() { + if (name == null) { + throw new BuiltValueNullFieldError('Enum', 'name'); + } + if (values == null) { + throw new BuiltValueNullFieldError('Enum', 'values'); + } + if (annotations == null) { + throw new BuiltValueNullFieldError('Enum', 'annotations'); + } + if (docs == null) { + throw new BuiltValueNullFieldError('Enum', 'docs'); + } + } + + @override + Enum rebuild(void Function(EnumBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + _$EnumBuilder toBuilder() => new _$EnumBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Enum && + name == other.name && + values == other.values && + annotations == other.annotations && + docs == other.docs; + } + + @override + int get hashCode { + return $jf($jc( + $jc($jc($jc(0, name.hashCode), values.hashCode), annotations.hashCode), + docs.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Enum') + ..add('name', name) + ..add('values', values) + ..add('annotations', annotations) + ..add('docs', docs)) + .toString(); + } +} + +class _$EnumBuilder extends EnumBuilder { + _$Enum _$v; + + @override + String get name { + _$this; + return super.name; + } + + @override + set name(String name) { + _$this; + super.name = name; + } + + @override + ListBuilder get values { + _$this; + return super.values ??= new ListBuilder(); + } + + @override + set values(ListBuilder values) { + _$this; + super.values = values; + } + + @override + ListBuilder get annotations { + _$this; + return super.annotations ??= new ListBuilder(); + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs ??= new ListBuilder(); + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + _$EnumBuilder() : super._(); + + EnumBuilder get _$this { + if (_$v != null) { + super.name = _$v.name; + super.values = _$v.values?.toBuilder(); + super.annotations = _$v.annotations?.toBuilder(); + super.docs = _$v.docs?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(Enum other) { + if (other == null) { + throw new ArgumentError.notNull('other'); + } + _$v = other as _$Enum; + } + + @override + void update(void Function(EnumBuilder) updates) { + if (updates != null) updates(this); + } + + @override + _$Enum build() { + _$Enum _$result; + try { + _$result = _$v ?? + new _$Enum._( + name: name, + values: values.build(), + annotations: annotations.build(), + docs: docs.build()); + } catch (_) { + String _$failedField; + try { + _$failedField = 'values'; + values.build(); + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'Enum', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +class _$EnumValue extends EnumValue { + @override + final String name; + @override + final BuiltList annotations; + @override + final BuiltList docs; + + factory _$EnumValue([void Function(EnumValueBuilder) updates]) => + (new EnumValueBuilder()..update(updates)).build() as _$EnumValue; + + _$EnumValue._({this.name, this.annotations, this.docs}) : super._() { + if (name == null) { + throw new BuiltValueNullFieldError('EnumValue', 'name'); + } + if (annotations == null) { + throw new BuiltValueNullFieldError('EnumValue', 'annotations'); + } + if (docs == null) { + throw new BuiltValueNullFieldError('EnumValue', 'docs'); + } + } + + @override + EnumValue rebuild(void Function(EnumValueBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + _$EnumValueBuilder toBuilder() => new _$EnumValueBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is EnumValue && + name == other.name && + annotations == other.annotations && + docs == other.docs; + } + + @override + int get hashCode { + return $jf( + $jc($jc($jc(0, name.hashCode), annotations.hashCode), docs.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('EnumValue') + ..add('name', name) + ..add('annotations', annotations) + ..add('docs', docs)) + .toString(); + } +} + +class _$EnumValueBuilder extends EnumValueBuilder { + _$EnumValue _$v; + + @override + String get name { + _$this; + return super.name; + } + + @override + set name(String name) { + _$this; + super.name = name; + } + + @override + ListBuilder get annotations { + _$this; + return super.annotations ??= new ListBuilder(); + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs ??= new ListBuilder(); + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + _$EnumValueBuilder() : super._(); + + EnumValueBuilder get _$this { + if (_$v != null) { + super.name = _$v.name; + super.annotations = _$v.annotations?.toBuilder(); + super.docs = _$v.docs?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(EnumValue other) { + if (other == null) { + throw new ArgumentError.notNull('other'); + } + _$v = other as _$EnumValue; + } + + @override + void update(void Function(EnumValueBuilder) updates) { + if (updates != null) updates(this); + } + + @override + _$EnumValue build() { + _$EnumValue _$result; + try { + _$result = _$v ?? + new _$EnumValue._( + name: name, annotations: annotations.build(), docs: docs.build()); + } catch (_) { + String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'EnumValue', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 62b47bc75..1447b830a 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -8,6 +8,7 @@ import 'base.dart'; import 'specs/class.dart'; import 'specs/constructor.dart'; import 'specs/directive.dart'; +import 'specs/enum.dart'; import 'specs/expression.dart'; import 'specs/field.dart'; import 'specs/library.dart'; @@ -24,6 +25,8 @@ abstract class SpecVisitor { T visitClass(Class spec, [T context]); + T visitEnum(Enum spec, [T context]); + T visitConstructor(Constructor spec, String clazz, [T context]); T visitDirective(Directive spec, [T context]); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 3a9d0ef32..abc1d67bb 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.4.1 +version: 3.5.0 description: >- A fluent, builder-based library for generating valid Dart code diff --git a/pkgs/code_builder/test/specs/enum_test.dart b/pkgs/code_builder/test/specs/enum_test.dart new file mode 100644 index 000000000..d9ee402bd --- /dev/null +++ b/pkgs/code_builder/test/specs/enum_test.dart @@ -0,0 +1,76 @@ +// Copyright (c) 2020, 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:test/test.dart'; + +import '../common.dart'; + +void main() { + useDartfmt(); + + test('should create an enum', () { + expect( + Enum((b) => b + ..name = 'E' + ..values.addAll([ + EnumValue((b) => b..name = 'a'), + EnumValue((b) => b..name = 'b'), + ])), + equalsDart(r''' + enum E { + a, + b + } + ''')); + }); + + test('should create an enum with annotations', () { + expect( + Enum((b) => b + ..annotations.addAll([ + refer('deprecated'), + refer('Deprecated').call([literalString('This is an old enum')]) + ]) + ..name = 'V' + ..values.addAll([ + EnumValue((b) => b..name = 'x'), + ])), + equalsDart(r''' + @deprecated + @Deprecated('This is an old enum') + enum V { + x + } + ''')); + }); + + test('should create an enum with annotated values', () { + expect( + Enum((b) => b + ..name = 'Status' + ..values.addAll([ + EnumValue((b) => b + ..name = 'okay' + ..annotations.addAll([ + refer('deprecated'), + refer('Deprecated').call([literalString('use Good insted')]), + ])), + EnumValue((b) => b + ..name = 'good' + ..annotations.addAll([ + refer('JsonKey').call([literalString('good')]) + ])), + ])), + equalsDart(r''' + enum Status { + @deprecated + @Deprecated('use Good insted') + okay, + @JsonKey('good') + good + } + ''')); + }); +} From 6b74c087c0489eebc25a4c2a2da4182035066920 Mon Sep 17 00:00:00 2001 From: Vsevolod <56274212+vr19860507@users.noreply.github.com> Date: Fri, 9 Oct 2020 00:45:17 +0300 Subject: [PATCH 165/271] Fix const factory constructors (dart-lang/code_builder#300) Fixes dart-lang/code_builder#288 Reorder output to write `const` before `factory`. --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/emitter.dart | 6 +++--- pkgs/code_builder/test/specs/class_test.dart | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index b5c2b91bf..c1dbf3f23 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ ## 3.5.0 * Add support for defining enums. +* Fix keyword ordering for `const factory` constructors. ## 3.4.1 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index e993fddd9..bd5b32d1d 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -157,12 +157,12 @@ class DartEmitter extends Object if (spec.external) { output.write('external '); } - if (spec.factory) { - output.write('factory '); - } if (spec.constant) { output.write('const '); } + if (spec.factory) { + output.write('factory '); + } output.write(clazz); if (spec.name != null) { output..write('.')..write(spec.name); diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 2b0698cfe..ebf67779c 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -248,6 +248,22 @@ void main() { ); }); + test('should create a class with a const factory constructor', () { + expect( + Class((b) => b + ..name = 'Foo' + ..constructors.add(Constructor((b) => b + ..factory = true + ..constant = true + ..redirect = refer('_Foo')))), + equalsDart(r''' + class Foo { + const factory Foo() = _Foo; + } + '''), + ); + }); + test('should create a class with a factory lambda constructor', () { expect( Class((b) => b From b066666cf36943ee29235358d91c8626b8292ae1 Mon Sep 17 00:00:00 2001 From: smolck <46855713+smolck@users.noreply.github.com> Date: Fri, 6 Nov 2020 18:33:15 -0600 Subject: [PATCH 166/271] Add extension support (dart-lang/code_builder#297) * Add support for Extension methods * Remove unused comment * Remove invalid code * Update code * Allow extension name to be null Co-authored-by: Nish Tahir --- pkgs/code_builder/lib/code_builder.dart | 1 + pkgs/code_builder/lib/src/emitter.dart | 32 +++ .../code_builder/lib/src/specs/extension.dart | 80 ++++++ .../lib/src/specs/extension.g.dart | 256 ++++++++++++++++++ pkgs/code_builder/lib/src/visitors.dart | 3 + .../test/specs/extension_test.dart | 159 +++++++++++ 6 files changed, 531 insertions(+) create mode 100644 pkgs/code_builder/lib/src/specs/extension.dart create mode 100644 pkgs/code_builder/lib/src/specs/extension.g.dart create mode 100644 pkgs/code_builder/test/specs/extension_test.dart diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 564299a8e..60adee8d0 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -39,6 +39,7 @@ export 'src/specs/expression.dart' literalString, literalTrue, literalFalse; +export 'src/specs/extension.dart' show Extension, ExtensionBuilder; export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; export 'src/specs/library.dart' show Library, LibraryBuilder; export 'src/specs/method.dart' diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index bd5b32d1d..b68023511 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -10,6 +10,7 @@ import 'specs/constructor.dart'; import 'specs/directive.dart'; import 'specs/enum.dart'; import 'specs/expression.dart'; +import 'specs/extension.dart'; import 'specs/field.dart'; import 'specs/library.dart'; import 'specs/method.dart'; @@ -233,6 +234,37 @@ class DartEmitter extends Object return output; } + @override + StringSink visitExtension(Extension spec, [StringSink output]) { + output ??= StringBuffer(); + spec.docs.forEach(output.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, output)); + + output.write('extension'); + if (spec.name != null) { + output.write(' ${spec.name}'); + } + visitTypeParameters(spec.types.map((r) => r.type), output); + if (spec.on != null) { + output.write(' on '); + spec.on.type.accept(this, output); + } + output.write(' {'); + spec.fields.forEach((f) { + visitField(f, output); + output.writeln(); + }); + spec.methods.forEach((m) { + visitMethod(m, output); + if (_isLambdaMethod(m)) { + output.write(';'); + } + output.writeln(); + }); + output.writeln(' }'); + return output; + } + @override StringSink visitDirective(Directive spec, [StringSink output]) { output ??= StringBuffer(); diff --git a/pkgs/code_builder/lib/src/specs/extension.dart b/pkgs/code_builder/lib/src/specs/extension.dart new file mode 100644 index 000000000..92604719e --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/extension.dart @@ -0,0 +1,80 @@ +// Copyright (c) 2020, 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:built_value/built_value.dart'; +import 'package:built_collection/built_collection.dart'; +import 'package:meta/meta.dart'; + +import '../../code_builder.dart'; +import '../base.dart'; +import '../mixins/annotations.dart'; +import '../mixins/dartdoc.dart'; +import '../mixins/generics.dart'; +import '../visitors.dart'; +import 'expression.dart'; +import 'field.dart'; +import 'method.dart'; +import 'reference.dart'; + +part 'extension.g.dart'; + +@immutable +abstract class Extension extends Object + with HasAnnotations, HasDartDocs, HasGenerics + implements Built, Spec { + factory Extension([void Function(ExtensionBuilder b) updates]) = _$Extension; + + Extension._(); + + @override + BuiltList get annotations; + + @override + BuiltList get docs; + + @nullable + Reference get on; + + @override + BuiltList get types; + + BuiltList get methods; + BuiltList get fields; + + /// Name of the extension - optional. + @nullable + String get name; + + @override + R accept( + SpecVisitor visitor, [ + R context, + ]) => + visitor.visitExtension(this, context); +} + +abstract class ExtensionBuilder extends Object + with HasAnnotationsBuilder, HasDartDocsBuilder, HasGenericsBuilder + implements Builder { + factory ExtensionBuilder() = _$ExtensionBuilder; + + ExtensionBuilder._(); + + @override + ListBuilder annotations = ListBuilder(); + + @override + ListBuilder docs = ListBuilder(); + + Reference on; + + @override + ListBuilder types = ListBuilder(); + + ListBuilder methods = ListBuilder(); + ListBuilder fields = ListBuilder(); + + /// Name of the extension - optional. + String name; +} diff --git a/pkgs/code_builder/lib/src/specs/extension.g.dart b/pkgs/code_builder/lib/src/specs/extension.g.dart new file mode 100644 index 000000000..befd295f3 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/extension.g.dart @@ -0,0 +1,256 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'extension.dart'; + +// ************************************************************************** +// BuiltValueGenerator +// ************************************************************************** + +class _$Extension extends Extension { + @override + final BuiltList annotations; + @override + final BuiltList docs; + @override + final Reference on; + @override + final BuiltList types; + @override + final BuiltList methods; + @override + final BuiltList fields; + @override + final String name; + + factory _$Extension([void Function(ExtensionBuilder) updates]) => + (new ExtensionBuilder()..update(updates)).build() as _$Extension; + + _$Extension._( + {this.annotations, + this.docs, + this.on, + this.types, + this.methods, + this.fields, + this.name}) + : super._() { + if (annotations == null) { + throw new BuiltValueNullFieldError('Extension', 'annotations'); + } + if (docs == null) { + throw new BuiltValueNullFieldError('Extension', 'docs'); + } + if (types == null) { + throw new BuiltValueNullFieldError('Extension', 'types'); + } + if (methods == null) { + throw new BuiltValueNullFieldError('Extension', 'methods'); + } + if (fields == null) { + throw new BuiltValueNullFieldError('Extension', 'fields'); + } + } + + @override + Extension rebuild(void Function(ExtensionBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + _$ExtensionBuilder toBuilder() => new _$ExtensionBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Extension && + annotations == other.annotations && + docs == other.docs && + on == other.on && + types == other.types && + methods == other.methods && + fields == other.fields && + name == other.name; + } + + @override + int get hashCode { + return $jf($jc( + $jc( + $jc( + $jc( + $jc($jc($jc(0, annotations.hashCode), docs.hashCode), + on.hashCode), + types.hashCode), + methods.hashCode), + fields.hashCode), + name.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Extension') + ..add('annotations', annotations) + ..add('docs', docs) + ..add('on', on) + ..add('types', types) + ..add('methods', methods) + ..add('fields', fields) + ..add('name', name)) + .toString(); + } +} + +class _$ExtensionBuilder extends ExtensionBuilder { + _$Extension _$v; + + @override + ListBuilder get annotations { + _$this; + return super.annotations ??= new ListBuilder(); + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs ??= new ListBuilder(); + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + @override + Reference get on { + _$this; + return super.on; + } + + @override + set on(Reference on) { + _$this; + super.on = on; + } + + @override + ListBuilder get types { + _$this; + return super.types ??= new ListBuilder(); + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + + @override + ListBuilder get methods { + _$this; + return super.methods ??= new ListBuilder(); + } + + @override + set methods(ListBuilder methods) { + _$this; + super.methods = methods; + } + + @override + ListBuilder get fields { + _$this; + return super.fields ??= new ListBuilder(); + } + + @override + set fields(ListBuilder fields) { + _$this; + super.fields = fields; + } + + @override + String get name { + _$this; + return super.name; + } + + @override + set name(String name) { + _$this; + super.name = name; + } + + _$ExtensionBuilder() : super._(); + + ExtensionBuilder get _$this { + if (_$v != null) { + super.annotations = _$v.annotations?.toBuilder(); + super.docs = _$v.docs?.toBuilder(); + super.on = _$v.on; + super.types = _$v.types?.toBuilder(); + super.methods = _$v.methods?.toBuilder(); + super.fields = _$v.fields?.toBuilder(); + super.name = _$v.name; + _$v = null; + } + return this; + } + + @override + void replace(Extension other) { + if (other == null) { + throw new ArgumentError.notNull('other'); + } + _$v = other as _$Extension; + } + + @override + void update(void Function(ExtensionBuilder) updates) { + if (updates != null) updates(this); + } + + @override + _$Extension build() { + _$Extension _$result; + try { + _$result = _$v ?? + new _$Extension._( + annotations: annotations.build(), + docs: docs.build(), + on: on, + types: types.build(), + methods: methods.build(), + fields: fields.build(), + name: name); + } catch (_) { + String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + + _$failedField = 'types'; + types.build(); + _$failedField = 'methods'; + methods.build(); + _$failedField = 'fields'; + fields.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'Extension', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 1447b830a..ed2ab4d8d 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -10,6 +10,7 @@ import 'specs/constructor.dart'; import 'specs/directive.dart'; import 'specs/enum.dart'; import 'specs/expression.dart'; +import 'specs/extension.dart'; import 'specs/field.dart'; import 'specs/library.dart'; import 'specs/method.dart'; @@ -25,6 +26,8 @@ abstract class SpecVisitor { T visitClass(Class spec, [T context]); + T visitExtension(Extension spec, [T context]); + T visitEnum(Enum spec, [T context]); T visitConstructor(Constructor spec, String clazz, [T context]); diff --git a/pkgs/code_builder/test/specs/extension_test.dart b/pkgs/code_builder/test/specs/extension_test.dart new file mode 100644 index 000000000..fad908969 --- /dev/null +++ b/pkgs/code_builder/test/specs/extension_test.dart @@ -0,0 +1,159 @@ +// 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:code_builder/src/specs/extension.dart'; +import 'package:test/test.dart'; + +import '../common.dart'; + +void main() { + useDartfmt(); + + test('should create an extension', () { + expect( + Extension((b) => b + ..name = 'Foo' + ..on = TypeReference((b) => b.symbol = 'Bar')), + equalsDart(r''' + extension Foo on Bar {} + '''), + ); + }); + + test('should create an extension without an identifier', () { + expect( + Extension((b) => b..on = TypeReference((b) => b.symbol = 'Bar')), + equalsDart(r''' + extension on Bar {} + '''), + ); + }); + + test('should create an extension with documentation', () { + expect( + Extension( + (b) => b + ..name = 'Foo' + ..on = TypeReference((b) => b.symbol = 'Bar') + ..docs.addAll( + const [ + '/// My favorite extension.', + ], + ), + ), + equalsDart(r''' + /// My favorite extension. + extension Foo on Bar {} + '''), + ); + }); + + test('should create an extension with annotations', () { + expect( + Extension( + (b) => b + ..name = 'Foo' + ..on = TypeReference((b) => b.symbol = 'Bar') + ..annotations.addAll([ + refer('deprecated'), + refer('Deprecated') + .call([literalString('This is an old extension')]) + ]), + ), + equalsDart(r''' + @deprecated + @Deprecated('This is an old extension') + extension Foo on Bar {} + '''), + ); + }); + + test('should create an extension with a generic type', () { + expect( + Extension((b) => b + ..name = 'Foo' + ..on = TypeReference((b) => b.symbol = 'Bar') + ..types.add(refer('T'))), + equalsDart(r''' + extension Foo on Bar {} + '''), + ); + }); + + test('should create an extension with multiple generic types', () { + expect( + Extension( + (b) => b + ..name = 'Map' + ..on = TypeReference((b) => b.symbol = 'Bar') + ..types.addAll([ + refer('K'), + refer('V'), + ]), + ), + equalsDart(r''' + extension Map on Bar {} + '''), + ); + }); + + test('should create an extension with a bound generic type', () { + expect( + Extension((b) => b + ..name = 'Foo' + ..on = TypeReference((b) => b.symbol = 'Bar') + ..types.add(TypeReference((b) => b + ..symbol = 'T' + ..bound = TypeReference((b) => b + ..symbol = 'Comparable' + ..types.add(refer('T').type))))), + equalsDart(r''' + extension Foo> on Bar {} + '''), + ); + }); + + test('should create an extension with a method', () { + expect( + Extension((b) => b + ..name = 'Foo' + ..on = TypeReference((b) => b.symbol = 'Bar') + ..methods.add(Method((b) => b + ..name = 'parseInt' + ..returns = refer('int') + ..body = Code.scope( + (a) => 'return int.parse(this);', + )))), + equalsDart(r''' + extension Foo on Bar { + int parseInt() { + return int.parse(this); + } + } + '''), + ); + }); + + test('should create an extension with a method', () { + expect( + Extension((b) => b + ..name = 'Foo' + ..on = TypeReference((b) => b.symbol = 'Bar') + ..methods.add(Method((b) => b + ..name = 'parseInt' + ..returns = refer('int') + ..body = Code.scope( + (a) => 'return int.parse(this);', + )))), + equalsDart(r''' + extension Foo on Bar { + int parseInt() { + return int.parse(this); + } + } + '''), + ); + }); +} From d4bb9a60c349a77bb4bbd1ef8c3420782f4cb936 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Fri, 6 Nov 2020 16:35:01 -0800 Subject: [PATCH 167/271] Update CHANGELOG.md --- pkgs/code_builder/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index c1dbf3f23..3d87f63a5 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,5 @@ +* Added support for `extension` methods. + ## 3.5.0 * Add support for defining enums. From d22f8c432453894962b63c115cafbc957516784b Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Sat, 26 Dec 2020 17:29:44 +0100 Subject: [PATCH 168/271] Migrate to GitHub Actions (dart-lang/code_builder#304) --- .../.github/workflows/test-package.yml | 72 +++++++++++++++++++ pkgs/code_builder/.travis.yml | 17 ----- pkgs/code_builder/README.md | 20 +++--- 3 files changed, 83 insertions(+), 26 deletions(-) create mode 100644 pkgs/code_builder/.github/workflows/test-package.yml delete mode 100644 pkgs/code_builder/.travis.yml diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml new file mode 100644 index 000000000..28a508667 --- /dev/null +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -0,0 +1,72 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev and 2.7.0. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + version: [latest] + include: + - sdk: stable + version: 2.7.0 + steps: + - uses: actions/checkout@v2 + - uses: cedx/setup-dart@v2 # TODO(dart-lang/setup-dart#3): use the official setup-dart action + with: + release-channel: ${{ matrix.sdk }} + version: ${{ matrix.version }} + - id: install + name: Install dependencies + run: pub get + - name: Check formatting + run: dartfmt --dry-run --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dartanalyzer --fatal-infos --fatal-warnings . + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev, 2.7.0 + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + version: [latest] + include: + - os: ubuntu-latest + sdk: stable + version: 2.7.0 + steps: + - uses: actions/checkout@v2 + - uses: cedx/setup-dart@v2 # TODO(dart-lang/setup-dart#3): use the official setup-dart action + with: + release-channel: ${{ matrix.sdk }} + version: ${{ matrix.version }} + - id: install + name: Install dependencies + run: pub get + - name: Run VM tests + run: pub run test --platform vm + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/code_builder/.travis.yml b/pkgs/code_builder/.travis.yml deleted file mode 100644 index dda7d52d5..000000000 --- a/pkgs/code_builder/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: dart - -dart: - - dev - - 2.7.0 - -dart_task: -- test -- dartanalyzer: --fatal-infos --fatal-warnings . -- dartfmt: sdk - -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index a438d7d3c..89d973f37 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -1,5 +1,5 @@ [![Pub package](https://img.shields.io/pub/v/code_builder.svg)](https://pub.dev/packages/code_builder) -[![Build status](https://travis-ci.org/dart-lang/code_builder.svg)](https://travis-ci.org/dart-lang/code_builder) +[![Build Status](https://github.com/dart-lang/code_builder/workflows/Dart%20CI/badge.svg?branch=master)](https://github.com/dart-lang/code_builder/actions?query=workflow%3A%22Dart+CI%22+branch%3Amaster) [![Gitter chat](https://badges.gitter.im/dart-lang/build.svg)](https://gitter.im/dart-lang/build) A fluent, builder-based library for generating valid Dart code. @@ -29,15 +29,16 @@ void main() { ``` Outputs: + ```dart class Animal extends Organism { void eat() => print('Yum!'); } ``` -Have a complicated set of dependencies for your generated code? -`code_builder` supports automatic scoping of your ASTs to automatically -use prefixes to avoid symbol conflicts: +Have a complicated set of dependencies for your generated code? `code_builder` +supports automatic scoping of your ASTs to automatically use prefixes to avoid +symbol conflicts: ```dart import 'package:code_builder/code_builder.dart'; @@ -60,6 +61,7 @@ void main() { ``` Outputs: + ```dart import 'package:a/a.dart' as _i1; import 'package:b/b.dart' as _i2; @@ -70,8 +72,8 @@ _i2.Other doOther() {} ## Contributing -* Read and help us document common patterns over [at the wiki][wiki]. -* Is there a *bug* in the code? [File an issue][issue]. +- Read and help us document common patterns over [at the wiki][wiki]. +- Is there a _bug_ in the code? [File an issue][issue]. If a feature is missing (the Dart language is always evolving) or you'd like an easier or better way to do something, consider [opening a pull request][pull]. @@ -91,9 +93,9 @@ will be on a best-effort basis. ### Updating generated (`.g.dart`) files -> **NOTE**: There is currently a limitation in `build_runner` that requires -> a workaround for developing this package. We expect this to be unnecessary -> in the future. +> **NOTE**: There is currently a limitation in `build_runner` that requires a +> workaround for developing this package. We expect this to be unnecessary in +> the future. Use [`build_runner`][build_runner]: From d73eb6985ca66a89fd7fb3fa1a6f1cd2a706c909 Mon Sep 17 00:00:00 2001 From: David Morgan Date: Tue, 12 Jan 2021 06:26:54 +0100 Subject: [PATCH 169/271] Widen deps range on built_value to allow null safety. (dart-lang/code_builder#306) * Widen deps range on built_value to allow null safety. * pubspec and changelog Co-authored-by: Nate Bosch --- pkgs/code_builder/CHANGELOG.md | 5 ++++- pkgs/code_builder/pubspec.yaml | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 3d87f63a5..b80e4d914 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,7 @@ -* Added support for `extension` methods. +## 3.6.0 + +* Add support for creating `extension` methods. +* Expand constraint on `built_value` to allow null safe migrated version. ## 3.5.0 diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index abc1d67bb..8c8982d36 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.5.0 +version: 3.6.0 description: >- A fluent, builder-based library for generating valid Dart code @@ -9,8 +9,8 @@ environment: sdk: '>=2.7.0 <3.0.0' dependencies: - built_collection: '>=3.0.0 <5.0.0' - built_value: ^7.0.0 + built_collection: '>=3.0.0 <6.0.0' + built_value: '>=7.0.0 <9.0.0' collection: ^1.14.0 matcher: ^0.12.0 meta: ^1.0.5 From 2f8f2d21c67a9b635b425be4f7002ab7c36b27df Mon Sep 17 00:00:00 2001 From: Yanko Diev Date: Tue, 9 Feb 2021 20:05:21 +0200 Subject: [PATCH 170/271] Adds 'part of' directive support (dart-lang/code_builder#308) * Add partOf directive support * Add a test for the 'part of' directive * dartfmt the code --- pkgs/code_builder/lib/src/emitter.dart | 3 +++ pkgs/code_builder/lib/src/specs/directive.dart | 5 +++++ pkgs/code_builder/test/specs/library_test.dart | 14 ++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index b68023511..14093cb0f 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -278,6 +278,9 @@ class DartEmitter extends Object case DirectiveType.part: output.write('part '); break; + case DirectiveType.partOf: + output.write('part of '); + break; } output.write("'${spec.url}'"); if (spec.as != null) { diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart index 04018d587..ee28f84d1 100644 --- a/pkgs/code_builder/lib/src/specs/directive.dart +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -58,6 +58,10 @@ abstract class Directive ..type = DirectiveType.part ..url = url); + factory Directive.partOf(String url) => Directive((builder) => builder + ..type = DirectiveType.partOf + ..url = url); + Directive._(); @nullable @@ -107,6 +111,7 @@ enum DirectiveType { import, export, part, + partOf, } /// Sort import URIs represented by [a] and [b] to honor the diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index 6dfbf3d12..9dcb3fa2b 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -123,5 +123,19 @@ void main() { ''', DartEmitter()), ); }); + + test('should emit a source file with part of directives', () { + expect( + Library( + (b) => b + ..directives.add( + Directive.partOf('test.dart'), + ), + ), + equalsDart(r''' + part of 'test.dart'; + ''', DartEmitter()), + ); + }); }); } From cf2677c9f27bb442b06a5a4b999c5021307e62ea Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 9 Mar 2021 10:24:53 -0800 Subject: [PATCH 171/271] Add genericClosure on Method (dart-lang/code_builder#312) --- pkgs/code_builder/CHANGELOG.md | 5 +++++ .../lib/src/specs/expression/closure.dart | 9 +++++++++ pkgs/code_builder/lib/src/specs/method.dart | 3 +++ pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 12 ++++++++++++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index b80e4d914..7b9b59f14 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,8 @@ +## 3.7.0-dev + +* Add support for converting a Method to a generic closure, with + `Method.genericClosure`. + ## 3.6.0 * Add support for creating `extension` methods. diff --git a/pkgs/code_builder/lib/src/specs/expression/closure.dart b/pkgs/code_builder/lib/src/specs/expression/closure.dart index f10eeeed1..4f9e1a1de 100644 --- a/pkgs/code_builder/lib/src/specs/expression/closure.dart +++ b/pkgs/code_builder/lib/src/specs/expression/closure.dart @@ -4,6 +4,7 @@ part of code_builder.src.specs.expression; +/// Returns [method] as closure, removing its return type and type parameters. Expression toClosure(Method method) { final withoutTypes = method.rebuild((b) { b.returns = null; @@ -12,6 +13,14 @@ Expression toClosure(Method method) { return ClosureExpression._(withoutTypes); } +/// Returns [method] as a (possibly) generic closure, removing its return type. +Expression toGenericClosure(Method method) { + final withoutReturnType = method.rebuild((b) { + b.returns = null; + }); + return ClosureExpression._(withoutReturnType); +} + class ClosureExpression extends Expression { final Method method; diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index cd6ae1e12..9be39296e 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -94,6 +94,9 @@ abstract class Method extends Object /// This method as a closure. Expression get closure => toClosure(this); + + /// This method as a (possibly) generic closure. + Expression get genericClosure => toGenericClosure(this); } abstract class MethodBuilder extends Object diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 8c8982d36..fc63a2b40 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.6.0 +version: 3.7.0-dev description: >- A fluent, builder-based library for generating valid Dart code diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index cecbc66a3..123506351 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -350,6 +350,18 @@ void main() { ); }); + test('should emit a generic closure', () { + expect( + refer('map').property('putIfAbsent').call([ + literalString('foo'), + Method((b) => b + ..types.add(refer('T')) + ..body = literalTrue.code).genericClosure, + ]), + equalsDart("map.putIfAbsent('foo', () => true)"), + ); + }); + test('should emit an assignment', () { expect( refer('foo').assign(literalTrue), From bd66bc16f7adc3121469145a3e0cf0fbce3288c7 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 10 Mar 2021 11:51:54 -0800 Subject: [PATCH 172/271] Bump to 3.7.0 (dart-lang/code_builder#314) --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 7b9b59f14..d23919e4a 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.7.0-dev +## 3.7.0 * Add support for converting a Method to a generic closure, with `Method.genericClosure`. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index fc63a2b40..ec8525b38 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 3.7.0-dev +version: 3.7.0 description: >- A fluent, builder-based library for generating valid Dart code From 6905435c8595448e8569516f3a353d91ae16a696 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Thu, 1 Apr 2021 16:28:55 -0700 Subject: [PATCH 173/271] Update LICENSE (dart-lang/code_builder#316) Changes to comply with internal review --- pkgs/code_builder/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/LICENSE b/pkgs/code_builder/LICENSE index 82e9b524a..237243134 100644 --- a/pkgs/code_builder/LICENSE +++ b/pkgs/code_builder/LICENSE @@ -1,4 +1,5 @@ -Copyright 2016, the Dart project authors. All rights reserved. +Copyright 2016, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From 7fc0f0fb3e6f496e2c07d89832243cb7aff2443c Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 5 Apr 2021 07:29:46 -0700 Subject: [PATCH 174/271] Migrate to null safety (dart-lang/code_builder#317) We will want to evaluate some of the pending breaking changes before releasing. --- .../.github/workflows/test-package.yml | 8 +- pkgs/code_builder/CHANGELOG.md | 4 + pkgs/code_builder/lib/src/allocator.dart | 10 +- pkgs/code_builder/lib/src/base.dart | 4 +- pkgs/code_builder/lib/src/emitter.dart | 202 +++++++------- pkgs/code_builder/lib/src/matchers.dart | 2 +- .../lib/src/mixins/annotations.dart | 2 +- pkgs/code_builder/lib/src/mixins/dartdoc.dart | 2 +- .../code_builder/lib/src/mixins/generics.dart | 2 +- pkgs/code_builder/lib/src/specs/class.dart | 14 +- pkgs/code_builder/lib/src/specs/class.g.dart | 130 ++++----- pkgs/code_builder/lib/src/specs/code.dart | 24 +- pkgs/code_builder/lib/src/specs/code.g.dart | 25 +- .../lib/src/specs/constructor.dart | 21 +- .../lib/src/specs/constructor.g.dart | 134 +++++---- .../code_builder/lib/src/specs/directive.dart | 13 +- .../lib/src/specs/directive.g.dart | 80 +++--- pkgs/code_builder/lib/src/specs/enum.dart | 6 +- pkgs/code_builder/lib/src/specs/enum.g.dart | 109 ++++---- .../lib/src/specs/expression.dart | 140 +++++----- .../lib/src/specs/expression/binary.dart | 2 +- .../lib/src/specs/expression/closure.dart | 2 +- .../lib/src/specs/expression/code.dart | 2 +- .../lib/src/specs/expression/invoke.dart | 12 +- .../lib/src/specs/expression/literal.dart | 46 ++-- .../code_builder/lib/src/specs/extension.dart | 12 +- .../lib/src/specs/extension.g.dart | 82 +++--- pkgs/code_builder/lib/src/specs/field.dart | 14 +- pkgs/code_builder/lib/src/specs/field.g.dart | 88 +++--- pkgs/code_builder/lib/src/specs/library.dart | 2 +- .../code_builder/lib/src/specs/library.g.dart | 33 +-- pkgs/code_builder/lib/src/specs/method.dart | 56 ++-- pkgs/code_builder/lib/src/specs/method.g.dart | 254 ++++++++---------- .../code_builder/lib/src/specs/reference.dart | 6 +- .../lib/src/specs/type_function.dart | 21 +- .../lib/src/specs/type_function.g.dart | 74 +++-- .../lib/src/specs/type_reference.dart | 19 +- .../lib/src/specs/type_reference.g.dart | 66 ++--- pkgs/code_builder/lib/src/visitors.dart | 28 +- pkgs/code_builder/pubspec.yaml | 32 ++- .../test/specs/type_reference_test.dart | 2 +- pkgs/code_builder/tool/src/builder.dart | 2 + 42 files changed, 854 insertions(+), 933 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 28a508667..2db209de0 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ env: jobs: # Check code formatting and static analysis on a single OS (linux) - # against Dart dev and 2.7.0. + # against Dart dev and 2.12.0. analyze: runs-on: ubuntu-latest strategy: @@ -24,7 +24,7 @@ jobs: version: [latest] include: - sdk: stable - version: 2.7.0 + version: 2.12.0 steps: - uses: actions/checkout@v2 - uses: cedx/setup-dart@v2 # TODO(dart-lang/setup-dart#3): use the official setup-dart action @@ -43,7 +43,7 @@ jobs: # Run tests on a matrix consisting of two dimensions: # 1. OS: ubuntu-latest, (macos-latest, windows-latest) - # 2. release channel: dev, 2.7.0 + # 2. release channel: dev, 2.12.0 test: needs: analyze runs-on: ${{ matrix.os }} @@ -57,7 +57,7 @@ jobs: include: - os: ubuntu-latest sdk: stable - version: 2.7.0 + version: 2.12.0 steps: - uses: actions/checkout@v2 - uses: cedx/setup-dart@v2 # TODO(dart-lang/setup-dart#3): use the official setup-dart action diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index d23919e4a..2cf35f19f 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.0.0-dev + +* Migrate to null safety. + ## 3.7.0 * Add support for converting a Method to a generic closure, with diff --git a/pkgs/code_builder/lib/src/allocator.dart b/pkgs/code_builder/lib/src/allocator.dart index 188094648..f2300f91e 100644 --- a/pkgs/code_builder/lib/src/allocator.dart +++ b/pkgs/code_builder/lib/src/allocator.dart @@ -50,8 +50,9 @@ class _Allocator implements Allocator { @override String allocate(Reference reference) { - if (reference.url != null) { - _imports.add(reference.url); + final url = reference.url; + if (url != null) { + _imports.add(url); } return reference.symbol; } @@ -79,10 +80,11 @@ class _PrefixedAllocator implements Allocator { @override String allocate(Reference reference) { final symbol = reference.symbol; - if (reference.url == null || _doNotPrefix.contains(reference.url)) { + final url = reference.url; + if (url == null || _doNotPrefix.contains(url)) { return symbol; } - return '_i${_imports.putIfAbsent(reference.url, _nextKey)}.$symbol'; + return '_i${_imports.putIfAbsent(url, _nextKey)}.$symbol'; } int _nextKey() => _keys++; diff --git a/pkgs/code_builder/lib/src/base.dart b/pkgs/code_builder/lib/src/base.dart index d2a5eb11a..216b9a982 100644 --- a/pkgs/code_builder/lib/src/base.dart +++ b/pkgs/code_builder/lib/src/base.dart @@ -5,7 +5,7 @@ import 'visitors.dart'; abstract class Spec { - R accept(SpecVisitor visitor, [R context]); + R accept(SpecVisitor visitor, [R? context]); } /// Returns a generic [Spec] that is lazily generated when visited. @@ -17,6 +17,6 @@ class _LazySpec implements Spec { const _LazySpec(this.generate); @override - R accept(SpecVisitor visitor, [R context]) => + R accept(SpecVisitor visitor, [R? context]) => generate().accept(visitor, context); } diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 14093cb0f..9934bdaef 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -72,8 +72,8 @@ class DartEmitter extends Object /// May specify an [Allocator] to use for symbols, otherwise uses a no-op. DartEmitter( [this.allocator = Allocator.none, - bool orderDirectives = false, - bool useNullSafetySyntax = false]) + bool? orderDirectives = false, + bool? useNullSafetySyntax = false]) : orderDirectives = orderDirectives ?? false, _useNullSafetySyntax = useNullSafetySyntax ?? false; @@ -83,7 +83,7 @@ class DartEmitter extends Object DartEmitter( Allocator.simplePrefixing(), orderDirectives, useNullSafetySyntax); - static bool _isLambdaBody(Code code) => + static bool _isLambdaBody(Code? code) => code is ToCodeExpression && !code.isStatement; /// Whether the provided [method] is considered a lambda method. @@ -96,7 +96,7 @@ class DartEmitter extends Object constructor.factory && _isLambdaBody(constructor.body); @override - StringSink visitAnnotation(Expression spec, [StringSink output]) { + StringSink visitAnnotation(Expression spec, [StringSink? output]) { (output ??= StringBuffer()).write('@'); spec.accept(this, output); output.write(' '); @@ -104,54 +104,54 @@ class DartEmitter extends Object } @override - StringSink visitClass(Class spec, [StringSink output]) { - output ??= StringBuffer(); - spec.docs.forEach(output.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, output)); + StringSink visitClass(Class spec, [StringSink? output]) { + final out = output ??= StringBuffer(); + spec.docs.forEach(out.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, out)); if (spec.abstract) { - output.write('abstract '); + out.write('abstract '); } - output.write('class ${spec.name}'); - visitTypeParameters(spec.types.map((r) => r.type), output); + out.write('class ${spec.name}'); + visitTypeParameters(spec.types.map((r) => r.type), out); if (spec.extend != null) { - output.write(' extends '); - spec.extend.type.accept(this, output); + out.write(' extends '); + spec.extend!.type.accept(this, out); } if (spec.mixins.isNotEmpty) { - output + out ..write(' with ') ..writeAll( spec.mixins.map((m) => m.type.accept(this)), ','); } if (spec.implements.isNotEmpty) { - output + out ..write(' implements ') ..writeAll( spec.implements.map((m) => m.type.accept(this)), ','); } - output.write(' {'); + out.write(' {'); spec.constructors.forEach((c) { - visitConstructor(c, spec.name, output); - output.writeln(); + visitConstructor(c, spec.name, out); + out.writeln(); }); spec.fields.forEach((f) { - visitField(f, output); - output.writeln(); + visitField(f, out); + out.writeln(); }); spec.methods.forEach((m) { - visitMethod(m, output); + visitMethod(m, out); if (_isLambdaMethod(m)) { - output.write(';'); + out.write(';'); } - output.writeln(); + out.writeln(); }); - output.writeln(' }'); - return output; + out.writeln(' }'); + return out; } @override StringSink visitConstructor(Constructor spec, String clazz, - [StringSink output]) { + [StringSink? output]) { output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); @@ -215,16 +215,16 @@ class DartEmitter extends Object } if (spec.redirect != null) { output.write(' = '); - spec.redirect.type.accept(this, output); + spec.redirect!.type.accept(this, output); output.write(';'); } else if (spec.body != null) { if (_isLambdaConstructor(spec)) { output.write(' => '); - spec.body.accept(this, output); + spec.body!.accept(this, output); output.write(';'); } else { output.write(' { '); - spec.body.accept(this, output); + spec.body!.accept(this, output); output.write(' }'); } } else { @@ -235,38 +235,38 @@ class DartEmitter extends Object } @override - StringSink visitExtension(Extension spec, [StringSink output]) { - output ??= StringBuffer(); - spec.docs.forEach(output.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, output)); + StringSink visitExtension(Extension spec, [StringSink? output]) { + final out = output ??= StringBuffer(); + spec.docs.forEach(out.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, out)); - output.write('extension'); + out.write('extension'); if (spec.name != null) { - output.write(' ${spec.name}'); + out.write(' ${spec.name}'); } - visitTypeParameters(spec.types.map((r) => r.type), output); + visitTypeParameters(spec.types.map((r) => r.type), out); if (spec.on != null) { - output.write(' on '); - spec.on.type.accept(this, output); + out.write(' on '); + spec.on!.type.accept(this, out); } - output.write(' {'); + out.write(' {'); spec.fields.forEach((f) { - visitField(f, output); - output.writeln(); + visitField(f, out); + out.writeln(); }); spec.methods.forEach((m) { - visitMethod(m, output); + visitMethod(m, out); if (_isLambdaMethod(m)) { - output.write(';'); + out.write(';'); } - output.writeln(); + out.writeln(); }); - output.writeln(' }'); - return output; + out.writeln(' }'); + return out; } @override - StringSink visitDirective(Directive spec, [StringSink output]) { + StringSink visitDirective(Directive spec, [StringSink? output]) { output ??= StringBuffer(); switch (spec.type) { case DirectiveType.import: @@ -303,7 +303,7 @@ class DartEmitter extends Object } @override - StringSink visitField(Field spec, [StringSink output]) { + StringSink visitField(Field spec, [StringSink? output]) { output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); @@ -324,14 +324,14 @@ class DartEmitter extends Object break; } if (spec.type != null) { - spec.type.type.accept(this, output); + spec.type!.type.accept(this, output); output.write(' '); } output.write(spec.name); if (spec.assignment != null) { output.write(' = '); startConstCode(spec.modifier == FieldModifier.constant, () { - spec.assignment.accept(this, output); + spec.assignment!.accept(this, output); }); } output.writeln(';'); @@ -339,7 +339,7 @@ class DartEmitter extends Object } @override - StringSink visitLibrary(Library spec, [StringSink output]) { + StringSink visitLibrary(Library spec, [StringSink? output]) { output ??= StringBuffer(); // Process the body first in order to prime the allocators. final body = StringBuffer(); @@ -356,7 +356,7 @@ class DartEmitter extends Object directives.sort(); } - Directive previous; + Directive? previous; for (final directive in directives) { if (_newLineBetween(orderDirectives, previous, directive)) { // Note: dartfmt handles creating new lines between directives. @@ -372,52 +372,52 @@ class DartEmitter extends Object } @override - StringSink visitFunctionType(FunctionType spec, [StringSink output]) { - output ??= StringBuffer(); + StringSink visitFunctionType(FunctionType spec, [StringSink? output]) { + final out = output ??= StringBuffer(); if (spec.returnType != null) { - spec.returnType.accept(this, output); - output.write(' '); + spec.returnType!.accept(this, out); + out.write(' '); } - output.write('Function'); + out.write('Function'); if (spec.types.isNotEmpty) { - output.write('<'); - visitAll(spec.types, output, (spec) { - spec.accept(this, output); + out.write('<'); + visitAll(spec.types, out, (spec) { + spec.accept(this, out); }); - output.write('>'); + out.write('>'); } - output.write('('); - visitAll(spec.requiredParameters, output, (spec) { - spec.accept(this, output); + out.write('('); + visitAll(spec.requiredParameters, out, (spec) { + spec.accept(this, out); }); if (spec.requiredParameters.isNotEmpty && (spec.optionalParameters.isNotEmpty || spec.namedParameters.isNotEmpty)) { - output.write(', '); + out.write(', '); } if (spec.optionalParameters.isNotEmpty) { - output.write('['); - visitAll(spec.optionalParameters, output, (spec) { - spec.accept(this, output); + out.write('['); + visitAll(spec.optionalParameters, out, (spec) { + spec.accept(this, out); }); - output.write(']'); + out.write(']'); } else if (spec.namedParameters.isNotEmpty) { - output.write('{'); - visitAll(spec.namedParameters.keys, output, (name) { - spec.namedParameters[name].accept(this, output); - output..write(' ')..write(name); + out.write('{'); + visitAll(spec.namedParameters.keys, out, (name) { + spec.namedParameters[name]!.accept(this, out); + out..write(' ')..write(name); }); - output.write('}'); + out.write('}'); } - output.write(')'); + out.write(')'); if (_useNullSafetySyntax && (spec.isNullable ?? false)) { - output.write('?'); + out.write('?'); } - return output; + return out; } @override - StringSink visitMethod(Method spec, [StringSink output]) { + StringSink visitMethod(Method spec, [StringSink? output]) { output ??= StringBuffer(); spec.docs.forEach(output.writeln); spec.annotations.forEach((a) => visitAnnotation(a, output)); @@ -428,7 +428,7 @@ class DartEmitter extends Object output.write('static '); } if (spec.returns != null) { - spec.returns.accept(this, output); + spec.returns!.accept(this, output); output.write(' '); } if (spec.type == MethodType.getter) { @@ -478,7 +478,7 @@ class DartEmitter extends Object } if (spec.body != null) { if (spec.modifier != null) { - switch (spec.modifier) { + switch (spec.modifier!) { case MethodModifier.async: output.write(' async '); break; @@ -495,7 +495,7 @@ class DartEmitter extends Object } else { output.write(' { '); } - spec.body.accept(this, output); + spec.body!.accept(this, output); if (!_isLambdaMethod(spec)) { output.write(' } '); } @@ -522,7 +522,7 @@ class DartEmitter extends Object output.write('covariant '); } if (spec.type != null) { - spec.type.type.accept(this, output); + spec.type!.type.accept(this, output); output.write(' '); } if (spec.toThis) { @@ -531,26 +531,26 @@ class DartEmitter extends Object output.write(spec.name); if (optional && spec.defaultTo != null) { output.write(' = '); - spec.defaultTo.accept(this, output); + spec.defaultTo!.accept(this, output); } } @override - StringSink visitReference(Reference spec, [StringSink output]) => + StringSink visitReference(Reference spec, [StringSink? output]) => (output ??= StringBuffer())..write(allocator.allocate(spec)); @override - StringSink visitSpec(Spec spec, [StringSink output]) => + StringSink visitSpec(Spec spec, [StringSink? output]) => spec.accept(this, output); @override - StringSink visitType(TypeReference spec, [StringSink output]) { + StringSink visitType(TypeReference spec, [StringSink? output]) { output ??= StringBuffer(); // Intentionally not .accept to avoid stack overflow. visitReference(spec, output); if (spec.bound != null) { output.write(' extends '); - spec.bound.type.accept(this, output); + spec.bound!.type.accept(this, output); } visitTypeParameters(spec.types.map((r) => r.type), output); if (_useNullSafetySyntax && (spec.isNullable ?? false)) { @@ -561,7 +561,7 @@ class DartEmitter extends Object @override StringSink visitTypeParameters(Iterable specs, - [StringSink output]) { + [StringSink? output]) { output ??= StringBuffer(); if (specs.isNotEmpty) { output @@ -573,21 +573,21 @@ class DartEmitter extends Object } @override - StringSink visitEnum(Enum spec, [StringSink output]) { - output ??= StringBuffer(); - spec.docs.forEach(output.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, output)); - output.writeln('enum ${spec.name} {'); + StringSink visitEnum(Enum spec, [StringSink? output]) { + final out = output ??= StringBuffer(); + spec.docs.forEach(out.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, out)); + out.writeln('enum ${spec.name} {'); spec.values.forEach((v) { - v.docs.forEach(output.writeln); - v.annotations.forEach((a) => visitAnnotation(a, output)); - output.write(v.name); + v.docs.forEach(out.writeln); + v.annotations.forEach((a) => visitAnnotation(a, out)); + out.write(v.name); if (v != spec.values.last) { - output.writeln(','); + out.writeln(','); } }); - output.writeln('}'); - return output; + out.writeln('}'); + return out; } } @@ -596,14 +596,14 @@ class DartEmitter extends Object /// * [ordered] is `true` /// * [a] is non-`null` /// * If there should be an empty line before [b] if it's emitted after [a]. -bool _newLineBetween(bool ordered, Directive a, Directive b) { +bool _newLineBetween(bool ordered, Directive? a, Directive? b) { if (!ordered) return false; if (a == null) return false; assert(b != null); // Put a line between imports and exports - if (a.type != b.type) return true; + if (a.type != b!.type) return true; // Within exports, don't put in extra blank lines if (a.type == DirectiveType.export) { diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index a443ce925..11d3d6d73 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -18,7 +18,7 @@ String _dart(Spec spec, DartEmitter emitter) => /// be overridden with [emitter]. Matcher equalsDart( String source, [ - DartEmitter emitter, + DartEmitter? emitter, ]) => EqualsDart._(EqualsDart._format(source), emitter ?? DartEmitter()); diff --git a/pkgs/code_builder/lib/src/mixins/annotations.dart b/pkgs/code_builder/lib/src/mixins/annotations.dart index f8bc94836..b4b3be284 100644 --- a/pkgs/code_builder/lib/src/mixins/annotations.dart +++ b/pkgs/code_builder/lib/src/mixins/annotations.dart @@ -15,5 +15,5 @@ abstract class HasAnnotations { /// Compliment to the [HasAnnotations] mixin for metadata [annotations]. abstract class HasAnnotationsBuilder { /// Annotations as metadata on the node. - ListBuilder annotations; + abstract ListBuilder annotations; } diff --git a/pkgs/code_builder/lib/src/mixins/dartdoc.dart b/pkgs/code_builder/lib/src/mixins/dartdoc.dart index ae44bd17a..52d69c04a 100644 --- a/pkgs/code_builder/lib/src/mixins/dartdoc.dart +++ b/pkgs/code_builder/lib/src/mixins/dartdoc.dart @@ -11,5 +11,5 @@ abstract class HasDartDocs { abstract class HasDartDocsBuilder { /// Dart docs. - ListBuilder docs; + abstract ListBuilder docs; } diff --git a/pkgs/code_builder/lib/src/mixins/generics.dart b/pkgs/code_builder/lib/src/mixins/generics.dart index 04a049e3f..51aae63f6 100644 --- a/pkgs/code_builder/lib/src/mixins/generics.dart +++ b/pkgs/code_builder/lib/src/mixins/generics.dart @@ -13,5 +13,5 @@ abstract class HasGenerics { abstract class HasGenericsBuilder { /// Generic type parameters. - ListBuilder types; + abstract ListBuilder types; } diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart index 77175f23a..13e586f5a 100644 --- a/pkgs/code_builder/lib/src/specs/class.dart +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -36,8 +36,7 @@ abstract class Class extends Object @override BuiltList get docs; - @nullable - Reference get extend; + Reference? get extend; BuiltList get implements; @@ -56,7 +55,7 @@ abstract class Class extends Object @override R accept( SpecVisitor visitor, [ - R context, + R? context, ]) => visitor.visitClass(this, context); } @@ -68,6 +67,11 @@ abstract class ClassBuilder extends Object ClassBuilder._(); + @override + void update(void Function(ClassBuilder)? updates) { + updates?.call(this); + } + /// Whether the class is `abstract`. bool abstract = false; @@ -77,7 +81,7 @@ abstract class ClassBuilder extends Object @override ListBuilder docs = ListBuilder(); - Reference extend; + Reference? extend; ListBuilder implements = ListBuilder(); ListBuilder mixins = ListBuilder(); @@ -90,5 +94,5 @@ abstract class ClassBuilder extends Object ListBuilder fields = ListBuilder(); /// Name of the class. - String name; + String? name; } diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index 916b96bc5..f007824d8 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -14,7 +14,7 @@ class _$Class extends Class { @override final BuiltList docs; @override - final Reference extend; + final Reference? extend; @override final BuiltList implements; @override @@ -30,52 +30,33 @@ class _$Class extends Class { @override final String name; - factory _$Class([void Function(ClassBuilder) updates]) => + factory _$Class([void Function(ClassBuilder)? updates]) => (new ClassBuilder()..update(updates)).build() as _$Class; _$Class._( - {this.abstract, - this.annotations, - this.docs, + {required this.abstract, + required this.annotations, + required this.docs, this.extend, - this.implements, - this.mixins, - this.types, - this.constructors, - this.methods, - this.fields, - this.name}) + required this.implements, + required this.mixins, + required this.types, + required this.constructors, + required this.methods, + required this.fields, + required this.name}) : super._() { - if (abstract == null) { - throw new BuiltValueNullFieldError('Class', 'abstract'); - } - if (annotations == null) { - throw new BuiltValueNullFieldError('Class', 'annotations'); - } - if (docs == null) { - throw new BuiltValueNullFieldError('Class', 'docs'); - } - if (implements == null) { - throw new BuiltValueNullFieldError('Class', 'implements'); - } - if (mixins == null) { - throw new BuiltValueNullFieldError('Class', 'mixins'); - } - if (types == null) { - throw new BuiltValueNullFieldError('Class', 'types'); - } - if (constructors == null) { - throw new BuiltValueNullFieldError('Class', 'constructors'); - } - if (methods == null) { - throw new BuiltValueNullFieldError('Class', 'methods'); - } - if (fields == null) { - throw new BuiltValueNullFieldError('Class', 'fields'); - } - if (name == null) { - throw new BuiltValueNullFieldError('Class', 'name'); - } + BuiltValueNullFieldError.checkNotNull(abstract, 'Class', 'abstract'); + BuiltValueNullFieldError.checkNotNull(annotations, 'Class', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, 'Class', 'docs'); + BuiltValueNullFieldError.checkNotNull(implements, 'Class', 'implements'); + BuiltValueNullFieldError.checkNotNull(mixins, 'Class', 'mixins'); + BuiltValueNullFieldError.checkNotNull(types, 'Class', 'types'); + BuiltValueNullFieldError.checkNotNull( + constructors, 'Class', 'constructors'); + BuiltValueNullFieldError.checkNotNull(methods, 'Class', 'methods'); + BuiltValueNullFieldError.checkNotNull(fields, 'Class', 'fields'); + BuiltValueNullFieldError.checkNotNull(name, 'Class', 'name'); } @override @@ -145,7 +126,7 @@ class _$Class extends Class { } class _$ClassBuilder extends ClassBuilder { - _$Class _$v; + _$Class? _$v; @override bool get abstract { @@ -162,7 +143,7 @@ class _$ClassBuilder extends ClassBuilder { @override ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations; } @override @@ -174,7 +155,7 @@ class _$ClassBuilder extends ClassBuilder { @override ListBuilder get docs { _$this; - return super.docs ??= new ListBuilder(); + return super.docs; } @override @@ -184,13 +165,13 @@ class _$ClassBuilder extends ClassBuilder { } @override - Reference get extend { + Reference? get extend { _$this; return super.extend; } @override - set extend(Reference extend) { + set extend(Reference? extend) { _$this; super.extend = extend; } @@ -198,7 +179,7 @@ class _$ClassBuilder extends ClassBuilder { @override ListBuilder get implements { _$this; - return super.implements ??= new ListBuilder(); + return super.implements; } @override @@ -210,7 +191,7 @@ class _$ClassBuilder extends ClassBuilder { @override ListBuilder get mixins { _$this; - return super.mixins ??= new ListBuilder(); + return super.mixins; } @override @@ -222,7 +203,7 @@ class _$ClassBuilder extends ClassBuilder { @override ListBuilder get types { _$this; - return super.types ??= new ListBuilder(); + return super.types; } @override @@ -234,7 +215,7 @@ class _$ClassBuilder extends ClassBuilder { @override ListBuilder get constructors { _$this; - return super.constructors ??= new ListBuilder(); + return super.constructors; } @override @@ -246,7 +227,7 @@ class _$ClassBuilder extends ClassBuilder { @override ListBuilder get methods { _$this; - return super.methods ??= new ListBuilder(); + return super.methods; } @override @@ -258,7 +239,7 @@ class _$ClassBuilder extends ClassBuilder { @override ListBuilder get fields { _$this; - return super.fields ??= new ListBuilder(); + return super.fields; } @override @@ -268,13 +249,13 @@ class _$ClassBuilder extends ClassBuilder { } @override - String get name { + String? get name { _$this; return super.name; } @override - set name(String name) { + set name(String? name) { _$this; super.name = name; } @@ -282,18 +263,19 @@ class _$ClassBuilder extends ClassBuilder { _$ClassBuilder() : super._(); ClassBuilder get _$this { - if (_$v != null) { - super.abstract = _$v.abstract; - super.annotations = _$v.annotations?.toBuilder(); - super.docs = _$v.docs?.toBuilder(); - super.extend = _$v.extend; - super.implements = _$v.implements?.toBuilder(); - super.mixins = _$v.mixins?.toBuilder(); - super.types = _$v.types?.toBuilder(); - super.constructors = _$v.constructors?.toBuilder(); - super.methods = _$v.methods?.toBuilder(); - super.fields = _$v.fields?.toBuilder(); - super.name = _$v.name; + final $v = _$v; + if ($v != null) { + super.abstract = $v.abstract; + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); + super.extend = $v.extend; + super.implements = $v.implements.toBuilder(); + super.mixins = $v.mixins.toBuilder(); + super.types = $v.types.toBuilder(); + super.constructors = $v.constructors.toBuilder(); + super.methods = $v.methods.toBuilder(); + super.fields = $v.fields.toBuilder(); + super.name = $v.name; _$v = null; } return this; @@ -301,14 +283,12 @@ class _$ClassBuilder extends ClassBuilder { @override void replace(Class other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$Class; } @override - void update(void Function(ClassBuilder) updates) { + void update(void Function(ClassBuilder)? updates) { if (updates != null) updates(this); } @@ -318,7 +298,8 @@ class _$ClassBuilder extends ClassBuilder { try { _$result = _$v ?? new _$Class._( - abstract: abstract, + abstract: BuiltValueNullFieldError.checkNotNull( + abstract, 'Class', 'abstract'), annotations: annotations.build(), docs: docs.build(), extend: extend, @@ -328,9 +309,10 @@ class _$ClassBuilder extends ClassBuilder { constructors: constructors.build(), methods: methods.build(), fields: fields.build(), - name: name); + name: + BuiltValueNullFieldError.checkNotNull(name, 'Class', 'name')); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'annotations'; annotations.build(); diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index b96d502cd..c441852af 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -41,7 +41,7 @@ abstract class Code implements Spec { ) = ScopedCode._; @override - R accept(covariant CodeVisitor visitor, [R context]); + R accept(covariant CodeVisitor visitor, [R? context]); } /// Represents blocks of statements of Dart code. @@ -54,7 +54,7 @@ abstract class Block implements Built, Code, Spec { Block._(); @override - R accept(covariant CodeVisitor visitor, [R context]) => + R accept(covariant CodeVisitor visitor, [R? context]) => visitor.visitBlock(this, context); BuiltList get statements; @@ -79,11 +79,11 @@ abstract class BlockBuilder implements Builder { /// /// **INTERNAL ONLY**. abstract class CodeVisitor implements SpecVisitor { - T visitBlock(Block code, [T context]); + T visitBlock(Block code, [T? context]); - T visitStaticCode(StaticCode code, [T context]); + T visitStaticCode(StaticCode code, [T? context]); - T visitScopedCode(ScopedCode code, [T context]); + T visitScopedCode(ScopedCode code, [T? context]); } /// Knowledge of how to write valid Dart code from [CodeVisitor]. @@ -92,7 +92,7 @@ abstract class CodeEmitter implements CodeVisitor { Allocator get allocator; @override - StringSink visitBlock(Block block, [StringSink output]) { + StringSink visitBlock(Block block, [StringSink? output]) { output ??= StringBuffer(); return visitAll(block.statements, output, (statement) { statement.accept(this, output); @@ -100,13 +100,13 @@ abstract class CodeEmitter implements CodeVisitor { } @override - StringSink visitStaticCode(StaticCode code, [StringSink output]) { + StringSink visitStaticCode(StaticCode code, [StringSink? output]) { output ??= StringBuffer(); return output..write(code.code); } @override - StringSink visitScopedCode(ScopedCode code, [StringSink output]) { + StringSink visitScopedCode(ScopedCode code, [StringSink? output]) { output ??= StringBuffer(); return output..write(code.code(allocator.allocate)); } @@ -119,7 +119,7 @@ class LazyCode implements Code { const LazyCode._(this.generate); @override - R accept(CodeVisitor visitor, [R context]) => + R accept(CodeVisitor visitor, [R? context]) => generate(visitor).accept(visitor, context); } @@ -132,7 +132,7 @@ class _LazyCode implements Code { const _LazyCode(this.generate); @override - R accept(CodeVisitor visitor, [R context]) => + R accept(CodeVisitor visitor, [R? context]) => generate().accept(visitor, context); } @@ -143,7 +143,7 @@ class StaticCode implements Code { const StaticCode._(this.code); @override - R accept(CodeVisitor visitor, [R context]) => + R accept(CodeVisitor visitor, [R? context]) => visitor.visitStaticCode(this, context); @override @@ -157,7 +157,7 @@ class ScopedCode implements Code { const ScopedCode._(this.code); @override - R accept(CodeVisitor visitor, [R context]) => + R accept(CodeVisitor visitor, [R? context]) => visitor.visitScopedCode(this, context); @override diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart index 63a6eab18..db4911918 100644 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -10,13 +10,11 @@ class _$Block extends Block { @override final BuiltList statements; - factory _$Block([void Function(BlockBuilder) updates]) => + factory _$Block([void Function(BlockBuilder)? updates]) => (new BlockBuilder()..update(updates)).build() as _$Block; - _$Block._({this.statements}) : super._() { - if (statements == null) { - throw new BuiltValueNullFieldError('Block', 'statements'); - } + _$Block._({required this.statements}) : super._() { + BuiltValueNullFieldError.checkNotNull(statements, 'Block', 'statements'); } @override @@ -45,12 +43,12 @@ class _$Block extends Block { } class _$BlockBuilder extends BlockBuilder { - _$Block _$v; + _$Block? _$v; @override ListBuilder get statements { _$this; - return super.statements ??= new ListBuilder(); + return super.statements; } @override @@ -62,8 +60,9 @@ class _$BlockBuilder extends BlockBuilder { _$BlockBuilder() : super._(); BlockBuilder get _$this { - if (_$v != null) { - super.statements = _$v.statements?.toBuilder(); + final $v = _$v; + if ($v != null) { + super.statements = $v.statements.toBuilder(); _$v = null; } return this; @@ -71,14 +70,12 @@ class _$BlockBuilder extends BlockBuilder { @override void replace(Block other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$Block; } @override - void update(void Function(BlockBuilder) updates) { + void update(void Function(BlockBuilder)? updates) { if (updates != null) updates(this); } @@ -88,7 +85,7 @@ class _$BlockBuilder extends BlockBuilder { try { _$result = _$v ?? new _$Block._(statements: statements.build()); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'statements'; statements.build(); diff --git a/pkgs/code_builder/lib/src/specs/constructor.dart b/pkgs/code_builder/lib/src/specs/constructor.dart index fb9f68932..381f3c568 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.dart @@ -40,8 +40,7 @@ abstract class Constructor extends Object BuiltList get initializers; /// Body of the method. - @nullable - Code get body; + Code? get body; /// Whether the constructor should be prefixed with `external`. bool get external; @@ -53,16 +52,13 @@ abstract class Constructor extends Object bool get factory; /// Whether this constructor is a simple lambda expression. - @nullable - bool get lambda; + bool? get lambda; /// Name of the constructor - optional. - @nullable - String get name; + String? get name; /// If non-null, redirect to this constructor. - @nullable - Reference get redirect; + Reference? get redirect; } abstract class ConstructorBuilder extends Object @@ -88,7 +84,7 @@ abstract class ConstructorBuilder extends Object ListBuilder initializers = ListBuilder(); /// Body of the constructor. - Code body; + Code? body; /// Whether the constructor should be prefixed with `const`. bool constant = false; @@ -100,12 +96,11 @@ abstract class ConstructorBuilder extends Object bool factory = false; /// Whether this constructor is a simple lambda expression. - bool lambda; + bool? lambda; /// Name of the constructor - optional. - String name; + String? name; /// If non-null, redirect to this constructor. - @nullable - Reference redirect; + Reference? redirect; } diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index 0f803d9f3..5a6c4d733 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -18,7 +18,7 @@ class _$Constructor extends Constructor { @override final BuiltList initializers; @override - final Code body; + final Code? body; @override final bool external; @override @@ -26,53 +26,41 @@ class _$Constructor extends Constructor { @override final bool factory; @override - final bool lambda; + final bool? lambda; @override - final String name; + final String? name; @override - final Reference redirect; + final Reference? redirect; - factory _$Constructor([void Function(ConstructorBuilder) updates]) => + factory _$Constructor([void Function(ConstructorBuilder)? updates]) => (new ConstructorBuilder()..update(updates)).build() as _$Constructor; _$Constructor._( - {this.annotations, - this.docs, - this.optionalParameters, - this.requiredParameters, - this.initializers, + {required this.annotations, + required this.docs, + required this.optionalParameters, + required this.requiredParameters, + required this.initializers, this.body, - this.external, - this.constant, - this.factory, + required this.external, + required this.constant, + required this.factory, this.lambda, this.name, this.redirect}) : super._() { - if (annotations == null) { - throw new BuiltValueNullFieldError('Constructor', 'annotations'); - } - if (docs == null) { - throw new BuiltValueNullFieldError('Constructor', 'docs'); - } - if (optionalParameters == null) { - throw new BuiltValueNullFieldError('Constructor', 'optionalParameters'); - } - if (requiredParameters == null) { - throw new BuiltValueNullFieldError('Constructor', 'requiredParameters'); - } - if (initializers == null) { - throw new BuiltValueNullFieldError('Constructor', 'initializers'); - } - if (external == null) { - throw new BuiltValueNullFieldError('Constructor', 'external'); - } - if (constant == null) { - throw new BuiltValueNullFieldError('Constructor', 'constant'); - } - if (factory == null) { - throw new BuiltValueNullFieldError('Constructor', 'factory'); - } + BuiltValueNullFieldError.checkNotNull( + annotations, 'Constructor', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, 'Constructor', 'docs'); + BuiltValueNullFieldError.checkNotNull( + optionalParameters, 'Constructor', 'optionalParameters'); + BuiltValueNullFieldError.checkNotNull( + requiredParameters, 'Constructor', 'requiredParameters'); + BuiltValueNullFieldError.checkNotNull( + initializers, 'Constructor', 'initializers'); + BuiltValueNullFieldError.checkNotNull(external, 'Constructor', 'external'); + BuiltValueNullFieldError.checkNotNull(constant, 'Constructor', 'constant'); + BuiltValueNullFieldError.checkNotNull(factory, 'Constructor', 'factory'); } @override @@ -146,12 +134,12 @@ class _$Constructor extends Constructor { } class _$ConstructorBuilder extends ConstructorBuilder { - _$Constructor _$v; + _$Constructor? _$v; @override ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations; } @override @@ -163,7 +151,7 @@ class _$ConstructorBuilder extends ConstructorBuilder { @override ListBuilder get docs { _$this; - return super.docs ??= new ListBuilder(); + return super.docs; } @override @@ -175,7 +163,7 @@ class _$ConstructorBuilder extends ConstructorBuilder { @override ListBuilder get optionalParameters { _$this; - return super.optionalParameters ??= new ListBuilder(); + return super.optionalParameters; } @override @@ -187,7 +175,7 @@ class _$ConstructorBuilder extends ConstructorBuilder { @override ListBuilder get requiredParameters { _$this; - return super.requiredParameters ??= new ListBuilder(); + return super.requiredParameters; } @override @@ -199,7 +187,7 @@ class _$ConstructorBuilder extends ConstructorBuilder { @override ListBuilder get initializers { _$this; - return super.initializers ??= new ListBuilder(); + return super.initializers; } @override @@ -209,13 +197,13 @@ class _$ConstructorBuilder extends ConstructorBuilder { } @override - Code get body { + Code? get body { _$this; return super.body; } @override - set body(Code body) { + set body(Code? body) { _$this; super.body = body; } @@ -257,37 +245,37 @@ class _$ConstructorBuilder extends ConstructorBuilder { } @override - bool get lambda { + bool? get lambda { _$this; return super.lambda; } @override - set lambda(bool lambda) { + set lambda(bool? lambda) { _$this; super.lambda = lambda; } @override - String get name { + String? get name { _$this; return super.name; } @override - set name(String name) { + set name(String? name) { _$this; super.name = name; } @override - Reference get redirect { + Reference? get redirect { _$this; return super.redirect; } @override - set redirect(Reference redirect) { + set redirect(Reference? redirect) { _$this; super.redirect = redirect; } @@ -295,19 +283,20 @@ class _$ConstructorBuilder extends ConstructorBuilder { _$ConstructorBuilder() : super._(); ConstructorBuilder get _$this { - if (_$v != null) { - super.annotations = _$v.annotations?.toBuilder(); - super.docs = _$v.docs?.toBuilder(); - super.optionalParameters = _$v.optionalParameters?.toBuilder(); - super.requiredParameters = _$v.requiredParameters?.toBuilder(); - super.initializers = _$v.initializers?.toBuilder(); - super.body = _$v.body; - super.external = _$v.external; - super.constant = _$v.constant; - super.factory = _$v.factory; - super.lambda = _$v.lambda; - super.name = _$v.name; - super.redirect = _$v.redirect; + final $v = _$v; + if ($v != null) { + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); + super.optionalParameters = $v.optionalParameters.toBuilder(); + super.requiredParameters = $v.requiredParameters.toBuilder(); + super.initializers = $v.initializers.toBuilder(); + super.body = $v.body; + super.external = $v.external; + super.constant = $v.constant; + super.factory = $v.factory; + super.lambda = $v.lambda; + super.name = $v.name; + super.redirect = $v.redirect; _$v = null; } return this; @@ -315,14 +304,12 @@ class _$ConstructorBuilder extends ConstructorBuilder { @override void replace(Constructor other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$Constructor; } @override - void update(void Function(ConstructorBuilder) updates) { + void update(void Function(ConstructorBuilder)? updates) { if (updates != null) updates(this); } @@ -338,14 +325,17 @@ class _$ConstructorBuilder extends ConstructorBuilder { requiredParameters: requiredParameters.build(), initializers: initializers.build(), body: body, - external: external, - constant: constant, - factory: factory, + external: BuiltValueNullFieldError.checkNotNull( + external, 'Constructor', 'external'), + constant: BuiltValueNullFieldError.checkNotNull( + constant, 'Constructor', 'constant'), + factory: BuiltValueNullFieldError.checkNotNull( + factory, 'Constructor', 'factory'), lambda: lambda, name: name, redirect: redirect); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'annotations'; annotations.build(); diff --git a/pkgs/code_builder/lib/src/specs/directive.dart b/pkgs/code_builder/lib/src/specs/directive.dart index ee28f84d1..e10c0ea2a 100644 --- a/pkgs/code_builder/lib/src/specs/directive.dart +++ b/pkgs/code_builder/lib/src/specs/directive.dart @@ -18,7 +18,7 @@ abstract class Directive factory Directive.import( String url, { - String as, + String? as, List show = const [], List hide = const [], }) => @@ -64,8 +64,7 @@ abstract class Directive Directive._(); - @nullable - String get as; + String? get as; String get url; @@ -80,7 +79,7 @@ abstract class Directive @override R accept( SpecVisitor visitor, [ - R context, + R? context, ]) => visitor.visitDirective(this, context); @@ -96,15 +95,15 @@ abstract class DirectiveBuilder bool deferred = false; - String as; + String? as; - String url; + String? url; List show = []; List hide = []; - DirectiveType type; + DirectiveType? type; } enum DirectiveType { diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart index ce34db590..500f5cda2 100644 --- a/pkgs/code_builder/lib/src/specs/directive.g.dart +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -8,7 +8,7 @@ part of 'directive.dart'; class _$Directive extends Directive { @override - final String as; + final String? as; @override final String url; @override @@ -20,27 +20,22 @@ class _$Directive extends Directive { @override final bool deferred; - factory _$Directive([void Function(DirectiveBuilder) updates]) => + factory _$Directive([void Function(DirectiveBuilder)? updates]) => (new DirectiveBuilder()..update(updates)).build() as _$Directive; _$Directive._( - {this.as, this.url, this.type, this.show, this.hide, this.deferred}) + {this.as, + required this.url, + required this.type, + required this.show, + required this.hide, + required this.deferred}) : super._() { - if (url == null) { - throw new BuiltValueNullFieldError('Directive', 'url'); - } - if (type == null) { - throw new BuiltValueNullFieldError('Directive', 'type'); - } - if (show == null) { - throw new BuiltValueNullFieldError('Directive', 'show'); - } - if (hide == null) { - throw new BuiltValueNullFieldError('Directive', 'hide'); - } - if (deferred == null) { - throw new BuiltValueNullFieldError('Directive', 'deferred'); - } + BuiltValueNullFieldError.checkNotNull(url, 'Directive', 'url'); + BuiltValueNullFieldError.checkNotNull(type, 'Directive', 'type'); + BuiltValueNullFieldError.checkNotNull(show, 'Directive', 'show'); + BuiltValueNullFieldError.checkNotNull(hide, 'Directive', 'hide'); + BuiltValueNullFieldError.checkNotNull(deferred, 'Directive', 'deferred'); } @override @@ -86,40 +81,40 @@ class _$Directive extends Directive { } class _$DirectiveBuilder extends DirectiveBuilder { - _$Directive _$v; + _$Directive? _$v; @override - String get as { + String? get as { _$this; return super.as; } @override - set as(String as) { + set as(String? as) { _$this; super.as = as; } @override - String get url { + String? get url { _$this; return super.url; } @override - set url(String url) { + set url(String? url) { _$this; super.url = url; } @override - DirectiveType get type { + DirectiveType? get type { _$this; return super.type; } @override - set type(DirectiveType type) { + set type(DirectiveType? type) { _$this; super.type = type; } @@ -163,13 +158,14 @@ class _$DirectiveBuilder extends DirectiveBuilder { _$DirectiveBuilder() : super._(); DirectiveBuilder get _$this { - if (_$v != null) { - super.as = _$v.as; - super.url = _$v.url; - super.type = _$v.type; - super.show = _$v.show; - super.hide = _$v.hide; - super.deferred = _$v.deferred; + final $v = _$v; + if ($v != null) { + super.as = $v.as; + super.url = $v.url; + super.type = $v.type; + super.show = $v.show; + super.hide = $v.hide; + super.deferred = $v.deferred; _$v = null; } return this; @@ -177,14 +173,12 @@ class _$DirectiveBuilder extends DirectiveBuilder { @override void replace(Directive other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$Directive; } @override - void update(void Function(DirectiveBuilder) updates) { + void update(void Function(DirectiveBuilder)? updates) { if (updates != null) updates(this); } @@ -193,11 +187,15 @@ class _$DirectiveBuilder extends DirectiveBuilder { final _$result = _$v ?? new _$Directive._( as: as, - url: url, - type: type, - show: show, - hide: hide, - deferred: deferred); + url: BuiltValueNullFieldError.checkNotNull(url, 'Directive', 'url'), + type: BuiltValueNullFieldError.checkNotNull( + type, 'Directive', 'type'), + show: BuiltValueNullFieldError.checkNotNull( + show, 'Directive', 'show'), + hide: BuiltValueNullFieldError.checkNotNull( + hide, 'Directive', 'hide'), + deferred: BuiltValueNullFieldError.checkNotNull( + deferred, 'Directive', 'deferred')); replace(_$result); return _$result; } diff --git a/pkgs/code_builder/lib/src/specs/enum.dart b/pkgs/code_builder/lib/src/specs/enum.dart index cb50ab171..c299f2105 100644 --- a/pkgs/code_builder/lib/src/specs/enum.dart +++ b/pkgs/code_builder/lib/src/specs/enum.dart @@ -34,7 +34,7 @@ abstract class Enum extends Object @override R accept( SpecVisitor visitor, [ - R context, + R? context, ]) => visitor.visitEnum(this, context); } @@ -46,7 +46,7 @@ abstract class EnumBuilder extends Object EnumBuilder._(); - String name; + String? name; ListBuilder values = ListBuilder(); @@ -81,7 +81,7 @@ abstract class EnumValueBuilder extends Object EnumValueBuilder._(); - String name; + String? name; @override ListBuilder annotations = ListBuilder(); diff --git a/pkgs/code_builder/lib/src/specs/enum.g.dart b/pkgs/code_builder/lib/src/specs/enum.g.dart index 8834ebdd9..4e82863e9 100644 --- a/pkgs/code_builder/lib/src/specs/enum.g.dart +++ b/pkgs/code_builder/lib/src/specs/enum.g.dart @@ -16,22 +16,19 @@ class _$Enum extends Enum { @override final BuiltList docs; - factory _$Enum([void Function(EnumBuilder) updates]) => + factory _$Enum([void Function(EnumBuilder)? updates]) => (new EnumBuilder()..update(updates)).build() as _$Enum; - _$Enum._({this.name, this.values, this.annotations, this.docs}) : super._() { - if (name == null) { - throw new BuiltValueNullFieldError('Enum', 'name'); - } - if (values == null) { - throw new BuiltValueNullFieldError('Enum', 'values'); - } - if (annotations == null) { - throw new BuiltValueNullFieldError('Enum', 'annotations'); - } - if (docs == null) { - throw new BuiltValueNullFieldError('Enum', 'docs'); - } + _$Enum._( + {required this.name, + required this.values, + required this.annotations, + required this.docs}) + : super._() { + BuiltValueNullFieldError.checkNotNull(name, 'Enum', 'name'); + BuiltValueNullFieldError.checkNotNull(values, 'Enum', 'values'); + BuiltValueNullFieldError.checkNotNull(annotations, 'Enum', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, 'Enum', 'docs'); } @override @@ -70,16 +67,16 @@ class _$Enum extends Enum { } class _$EnumBuilder extends EnumBuilder { - _$Enum _$v; + _$Enum? _$v; @override - String get name { + String? get name { _$this; return super.name; } @override - set name(String name) { + set name(String? name) { _$this; super.name = name; } @@ -87,7 +84,7 @@ class _$EnumBuilder extends EnumBuilder { @override ListBuilder get values { _$this; - return super.values ??= new ListBuilder(); + return super.values; } @override @@ -99,7 +96,7 @@ class _$EnumBuilder extends EnumBuilder { @override ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations; } @override @@ -111,7 +108,7 @@ class _$EnumBuilder extends EnumBuilder { @override ListBuilder get docs { _$this; - return super.docs ??= new ListBuilder(); + return super.docs; } @override @@ -123,11 +120,12 @@ class _$EnumBuilder extends EnumBuilder { _$EnumBuilder() : super._(); EnumBuilder get _$this { - if (_$v != null) { - super.name = _$v.name; - super.values = _$v.values?.toBuilder(); - super.annotations = _$v.annotations?.toBuilder(); - super.docs = _$v.docs?.toBuilder(); + final $v = _$v; + if ($v != null) { + super.name = $v.name; + super.values = $v.values.toBuilder(); + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); _$v = null; } return this; @@ -135,14 +133,12 @@ class _$EnumBuilder extends EnumBuilder { @override void replace(Enum other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$Enum; } @override - void update(void Function(EnumBuilder) updates) { + void update(void Function(EnumBuilder)? updates) { if (updates != null) updates(this); } @@ -152,12 +148,12 @@ class _$EnumBuilder extends EnumBuilder { try { _$result = _$v ?? new _$Enum._( - name: name, + name: BuiltValueNullFieldError.checkNotNull(name, 'Enum', 'name'), values: values.build(), annotations: annotations.build(), docs: docs.build()); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'values'; values.build(); @@ -184,19 +180,16 @@ class _$EnumValue extends EnumValue { @override final BuiltList docs; - factory _$EnumValue([void Function(EnumValueBuilder) updates]) => + factory _$EnumValue([void Function(EnumValueBuilder)? updates]) => (new EnumValueBuilder()..update(updates)).build() as _$EnumValue; - _$EnumValue._({this.name, this.annotations, this.docs}) : super._() { - if (name == null) { - throw new BuiltValueNullFieldError('EnumValue', 'name'); - } - if (annotations == null) { - throw new BuiltValueNullFieldError('EnumValue', 'annotations'); - } - if (docs == null) { - throw new BuiltValueNullFieldError('EnumValue', 'docs'); - } + _$EnumValue._( + {required this.name, required this.annotations, required this.docs}) + : super._() { + BuiltValueNullFieldError.checkNotNull(name, 'EnumValue', 'name'); + BuiltValueNullFieldError.checkNotNull( + annotations, 'EnumValue', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, 'EnumValue', 'docs'); } @override @@ -232,16 +225,16 @@ class _$EnumValue extends EnumValue { } class _$EnumValueBuilder extends EnumValueBuilder { - _$EnumValue _$v; + _$EnumValue? _$v; @override - String get name { + String? get name { _$this; return super.name; } @override - set name(String name) { + set name(String? name) { _$this; super.name = name; } @@ -249,7 +242,7 @@ class _$EnumValueBuilder extends EnumValueBuilder { @override ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations; } @override @@ -261,7 +254,7 @@ class _$EnumValueBuilder extends EnumValueBuilder { @override ListBuilder get docs { _$this; - return super.docs ??= new ListBuilder(); + return super.docs; } @override @@ -273,10 +266,11 @@ class _$EnumValueBuilder extends EnumValueBuilder { _$EnumValueBuilder() : super._(); EnumValueBuilder get _$this { - if (_$v != null) { - super.name = _$v.name; - super.annotations = _$v.annotations?.toBuilder(); - super.docs = _$v.docs?.toBuilder(); + final $v = _$v; + if ($v != null) { + super.name = $v.name; + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); _$v = null; } return this; @@ -284,14 +278,12 @@ class _$EnumValueBuilder extends EnumValueBuilder { @override void replace(EnumValue other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$EnumValue; } @override - void update(void Function(EnumValueBuilder) updates) { + void update(void Function(EnumValueBuilder)? updates) { if (updates != null) updates(this); } @@ -301,9 +293,12 @@ class _$EnumValueBuilder extends EnumValueBuilder { try { _$result = _$v ?? new _$EnumValue._( - name: name, annotations: annotations.build(), docs: docs.build()); + name: BuiltValueNullFieldError.checkNotNull( + name, 'EnumValue', 'name'), + annotations: annotations.build(), + docs: docs.build()); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'annotations'; annotations.build(); diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index c186a7ee5..21cc69178 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -32,7 +32,7 @@ abstract class Expression implements Spec { static const _empty = CodeExpression(Code('')); @override - R accept(covariant ExpressionVisitor visitor, [R context]); + R accept(covariant ExpressionVisitor visitor, [R? context]); /// The expression as a valid [Code] block. /// @@ -203,7 +203,7 @@ abstract class Expression implements Spec { ); /// Return `var {name} = {this}`. - Expression assignVar(String name, [Reference type]) => BinaryExpression._( + Expression assignVar(String name, [Reference? type]) => BinaryExpression._( type == null ? LiteralExpression._('var $name') : BinaryExpression._( @@ -216,7 +216,7 @@ abstract class Expression implements Spec { ); /// Return `final {name} = {this}`. - Expression assignFinal(String name, [Reference type]) => BinaryExpression._( + Expression assignFinal(String name, [Reference? type]) => BinaryExpression._( type == null ? const LiteralExpression._('final') : BinaryExpression._( @@ -229,7 +229,7 @@ abstract class Expression implements Spec { ); /// Return `const {name} = {this}`. - Expression assignConst(String name, [Reference type]) => BinaryExpression._( + Expression assignConst(String name, [Reference? type]) => BinaryExpression._( type == null ? const LiteralExpression._('const') : BinaryExpression._( @@ -313,7 +313,7 @@ class ToCodeExpression implements Code { const ToCodeExpression(this.code, [this.isStatement = false]); @override - R accept(CodeVisitor visitor, [R context]) => + R accept(CodeVisitor visitor, [R? context]) => (visitor as ExpressionVisitor).visitToCodeExpression(this, context); @override @@ -324,15 +324,15 @@ class ToCodeExpression implements Code { /// /// **INTERNAL ONLY**. abstract class ExpressionVisitor implements SpecVisitor { - T visitToCodeExpression(ToCodeExpression code, [T context]); - T visitBinaryExpression(BinaryExpression expression, [T context]); - T visitClosureExpression(ClosureExpression expression, [T context]); - T visitCodeExpression(CodeExpression expression, [T context]); - T visitInvokeExpression(InvokeExpression expression, [T context]); - T visitLiteralExpression(LiteralExpression expression, [T context]); - T visitLiteralListExpression(LiteralListExpression expression, [T context]); - T visitLiteralSetExpression(LiteralSetExpression expression, [T context]); - T visitLiteralMapExpression(LiteralMapExpression expression, [T context]); + T visitToCodeExpression(ToCodeExpression code, [T? context]); + T visitBinaryExpression(BinaryExpression expression, [T? context]); + T visitClosureExpression(ClosureExpression expression, [T? context]); + T visitCodeExpression(CodeExpression expression, [T? context]); + T visitInvokeExpression(InvokeExpression expression, [T? context]); + T visitLiteralExpression(LiteralExpression expression, [T? context]); + T visitLiteralListExpression(LiteralListExpression expression, [T? context]); + T visitLiteralSetExpression(LiteralSetExpression expression, [T? context]); + T visitLiteralMapExpression(LiteralMapExpression expression, [T? context]); } /// Knowledge of how to write valid Dart code from [ExpressionVisitor]. @@ -341,7 +341,7 @@ abstract class ExpressionVisitor implements SpecVisitor { abstract class ExpressionEmitter implements ExpressionVisitor { @override StringSink visitToCodeExpression(ToCodeExpression expression, - [StringSink output]) { + [StringSink? output]) { output ??= StringBuffer(); expression.code.accept(this, output); if (expression.isStatement) { @@ -352,7 +352,7 @@ abstract class ExpressionEmitter implements ExpressionVisitor { @override StringSink visitBinaryExpression(BinaryExpression expression, - [StringSink output]) { + [StringSink? output]) { output ??= StringBuffer(); expression.left.accept(this, output); if (expression.addSpace) { @@ -370,14 +370,14 @@ abstract class ExpressionEmitter implements ExpressionVisitor { @override StringSink visitClosureExpression(ClosureExpression expression, - [StringSink output]) { + [StringSink? output]) { output ??= StringBuffer(); return expression.method.accept(this, output); } @override StringSink visitCodeExpression(CodeExpression expression, - [StringSink output]) { + [StringSink? output]) { output ??= StringBuffer(); final visitor = this as CodeVisitor; return expression.code.accept(visitor, output); @@ -385,45 +385,45 @@ abstract class ExpressionEmitter implements ExpressionVisitor { @override StringSink visitInvokeExpression(InvokeExpression expression, - [StringSink output]) { - output ??= StringBuffer(); + [StringSink? output]) { + final out = output ??= StringBuffer(); return _writeConstExpression( - output, expression.type == InvokeExpressionType.constInstance, () { - expression.target.accept(this, output); + out, expression.type == InvokeExpressionType.constInstance, () { + expression.target.accept(this, out); if (expression.name != null) { - output..write('.')..write(expression.name); + out..write('.')..write(expression.name); } if (expression.typeArguments.isNotEmpty) { - output.write('<'); - visitAll(expression.typeArguments, output, (type) { - type.accept(this, output); + out.write('<'); + visitAll(expression.typeArguments, out, (type) { + type.accept(this, out); }); - output.write('>'); + out.write('>'); } - output.write('('); - visitAll(expression.positionalArguments, output, (spec) { - spec.accept(this, output); + out.write('('); + visitAll(expression.positionalArguments, out, (spec) { + spec.accept(this, out); }); if (expression.positionalArguments.isNotEmpty && expression.namedArguments.isNotEmpty) { - output.write(', '); + out.write(', '); } - visitAll(expression.namedArguments.keys, output, (name) { - output..write(name)..write(': '); - expression.namedArguments[name].accept(this, output); + visitAll(expression.namedArguments.keys, out, (name) { + out..write(name)..write(': '); + expression.namedArguments[name]!.accept(this, out); }); - return output..write(')'); + return out..write(')'); }); } @override StringSink visitLiteralExpression(LiteralExpression expression, - [StringSink output]) { + [StringSink? output]) { output ??= StringBuffer(); return output..write(expression.literal); } - void _acceptLiteral(Object literalOrSpec, StringSink output) { + void _acceptLiteral(Object? literalOrSpec, StringSink output) { if (literalOrSpec is Spec) { literalOrSpec.accept(this, output); return; @@ -436,71 +436,71 @@ abstract class ExpressionEmitter implements ExpressionVisitor { @override StringSink visitLiteralListExpression( LiteralListExpression expression, [ - StringSink output, + StringSink? output, ]) { - output ??= StringBuffer(); + final out = output ??= StringBuffer(); return _writeConstExpression(output, expression.isConst, () { if (expression.type != null) { - output.write('<'); - expression.type.accept(this, output); - output.write('>'); + out.write('<'); + expression.type!.accept(this, output); + out.write('>'); } - output.write('['); - visitAll(expression.values, output, (value) { - _acceptLiteral(value, output); + out.write('['); + visitAll(expression.values, out, (value) { + _acceptLiteral(value, out); }); - return output..write(']'); + return out..write(']'); }); } @override StringSink visitLiteralSetExpression( LiteralSetExpression expression, [ - StringSink output, + StringSink? output, ]) { - output ??= StringBuffer(); + final out = output ??= StringBuffer(); return _writeConstExpression(output, expression.isConst, () { if (expression.type != null) { - output.write('<'); - expression.type.accept(this, output); - output.write('>'); + out.write('<'); + expression.type!.accept(this, output); + out.write('>'); } - output.write('{'); - visitAll(expression.values, output, (value) { - _acceptLiteral(value, output); + out.write('{'); + visitAll(expression.values, out, (value) { + _acceptLiteral(value, out); }); - return output..write('}'); + return out..write('}'); }); } @override StringSink visitLiteralMapExpression( LiteralMapExpression expression, [ - StringSink output, + StringSink? output, ]) { - output ??= StringBuffer(); - return _writeConstExpression(output, expression.isConst, () { + final out = output ??= StringBuffer(); + return _writeConstExpression(out, expression.isConst, () { if (expression.keyType != null) { - output.write('<'); - expression.keyType.accept(this, output); - output.write(', '); + out.write('<'); + expression.keyType!.accept(this, out); + out.write(', '); if (expression.valueType == null) { - const Reference('dynamic', 'dart:core').accept(this, output); + const Reference('dynamic', 'dart:core').accept(this, out); } else { - expression.valueType.accept(this, output); + expression.valueType!.accept(this, out); } - output.write('>'); + out.write('>'); } - output.write('{'); - visitAll(expression.values.keys, output, (key) { + out.write('{'); + visitAll(expression.values.keys, out, (key) { final value = expression.values[key]; - _acceptLiteral(key, output); - output.write(': '); - _acceptLiteral(value, output); + _acceptLiteral(key, out); + out.write(': '); + _acceptLiteral(value, out); }); - return output..write('}'); + return out..write('}'); }); } diff --git a/pkgs/code_builder/lib/src/specs/expression/binary.dart b/pkgs/code_builder/lib/src/specs/expression/binary.dart index b3a8808b2..4672a26d0 100644 --- a/pkgs/code_builder/lib/src/specs/expression/binary.dart +++ b/pkgs/code_builder/lib/src/specs/expression/binary.dart @@ -21,6 +21,6 @@ class BinaryExpression extends Expression { }); @override - R accept(ExpressionVisitor visitor, [R context]) => + R accept(ExpressionVisitor visitor, [R? context]) => visitor.visitBinaryExpression(this, context); } diff --git a/pkgs/code_builder/lib/src/specs/expression/closure.dart b/pkgs/code_builder/lib/src/specs/expression/closure.dart index 4f9e1a1de..0506465ac 100644 --- a/pkgs/code_builder/lib/src/specs/expression/closure.dart +++ b/pkgs/code_builder/lib/src/specs/expression/closure.dart @@ -27,6 +27,6 @@ class ClosureExpression extends Expression { const ClosureExpression._(this.method); @override - R accept(ExpressionVisitor visitor, [R context]) => + R accept(ExpressionVisitor visitor, [R? context]) => visitor.visitClosureExpression(this, context); } diff --git a/pkgs/code_builder/lib/src/specs/expression/code.dart b/pkgs/code_builder/lib/src/specs/expression/code.dart index 3a5421937..0eb0c3d03 100644 --- a/pkgs/code_builder/lib/src/specs/expression/code.dart +++ b/pkgs/code_builder/lib/src/specs/expression/code.dart @@ -13,6 +13,6 @@ class CodeExpression extends Expression { const CodeExpression(this.code); @override - R accept(ExpressionVisitor visitor, [R context]) => + R accept(ExpressionVisitor visitor, [R? context]) => visitor.visitCodeExpression(this, context); } diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index fb563952c..448ce3e39 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -10,18 +10,18 @@ class InvokeExpression extends Expression { final Expression target; /// Optional; type of invocation. - final InvokeExpressionType type; + final InvokeExpressionType? type; final List positionalArguments; final Map namedArguments; final List typeArguments; - final String name; + final String? name; const InvokeExpression._( this.target, this.positionalArguments, [ this.namedArguments = const {}, - this.typeArguments, + this.typeArguments = const [], this.name, ]) : type = null; @@ -29,7 +29,7 @@ class InvokeExpression extends Expression { this.target, this.positionalArguments, [ this.namedArguments = const {}, - this.typeArguments, + this.typeArguments = const [], this.name, ]) : type = InvokeExpressionType.newInstance; @@ -37,12 +37,12 @@ class InvokeExpression extends Expression { this.target, this.positionalArguments, [ this.namedArguments = const {}, - this.typeArguments, + this.typeArguments = const [], this.name, ]) : type = InvokeExpressionType.constInstance; @override - R accept(ExpressionVisitor visitor, [R context]) => + R accept(ExpressionVisitor visitor, [R? context]) => visitor.visitInvokeExpression(this, context); @override diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index b4ae81a1e..4c896d7e0 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -7,7 +7,7 @@ part of code_builder.src.specs.expression; /// Converts a runtime Dart [literal] value into an [Expression]. /// /// Unsupported inputs invoke the [onError] callback. -Expression literal(Object literal, {Expression Function(Object) onError}) { +Expression literal(Object? literal, {Expression Function(Object)? onError}) { if (literal is bool) { return literalBool(literal); } @@ -66,34 +66,36 @@ Expression literalString(String value, {bool raw = false}) { } /// Creates a literal list expression from [values]. -LiteralListExpression literalList(Iterable values, [Reference type]) => +LiteralListExpression literalList(Iterable values, + [Reference? type]) => LiteralListExpression._(false, values.toList(), type); /// Creates a literal `const` list expression from [values]. -LiteralListExpression literalConstList(List values, [Reference type]) => +LiteralListExpression literalConstList(List values, + [Reference? type]) => LiteralListExpression._(true, values, type); /// Creates a literal set expression from [values]. -LiteralSetExpression literalSet(Iterable values, [Reference type]) => +LiteralSetExpression literalSet(Iterable values, [Reference? type]) => LiteralSetExpression._(false, values.toSet(), type); /// Creates a literal `const` set expression from [values]. -LiteralSetExpression literalConstSet(Set values, [Reference type]) => +LiteralSetExpression literalConstSet(Set values, [Reference? type]) => LiteralSetExpression._(true, values, type); /// Create a literal map expression from [values]. LiteralMapExpression literalMap( - Map values, [ - Reference keyType, - Reference valueType, + Map values, [ + Reference? keyType, + Reference? valueType, ]) => LiteralMapExpression._(false, values, keyType, valueType); /// Create a literal `const` map expression from [values]. LiteralMapExpression literalConstMap( - Map values, [ - Reference keyType, - Reference valueType, + Map values, [ + Reference? keyType, + Reference? valueType, ]) => LiteralMapExpression._(true, values, keyType, valueType); @@ -113,7 +115,7 @@ class LiteralExpression extends Expression { const LiteralExpression._(this.literal); @override - R accept(ExpressionVisitor visitor, [R context]) => + R accept(ExpressionVisitor visitor, [R? context]) => visitor.visitLiteralExpression(this, context); @override @@ -122,13 +124,13 @@ class LiteralExpression extends Expression { class LiteralListExpression extends Expression { final bool isConst; - final List values; - final Reference type; + final List values; + final Reference? type; const LiteralListExpression._(this.isConst, this.values, this.type); @override - R accept(ExpressionVisitor visitor, [R context]) => + R accept(ExpressionVisitor visitor, [R? context]) => visitor.visitLiteralListExpression(this, context); @override @@ -137,13 +139,13 @@ class LiteralListExpression extends Expression { class LiteralSetExpression extends Expression { final bool isConst; - final Set values; - final Reference type; + final Set values; + final Reference? type; const LiteralSetExpression._(this.isConst, this.values, this.type); @override - R accept(ExpressionVisitor visitor, [R context]) => + R accept(ExpressionVisitor visitor, [R? context]) => visitor.visitLiteralSetExpression(this, context); @override @@ -152,9 +154,9 @@ class LiteralSetExpression extends Expression { class LiteralMapExpression extends Expression { final bool isConst; - final Map values; - final Reference keyType; - final Reference valueType; + final Map values; + final Reference? keyType; + final Reference? valueType; const LiteralMapExpression._( this.isConst, @@ -164,7 +166,7 @@ class LiteralMapExpression extends Expression { ); @override - R accept(ExpressionVisitor visitor, [R context]) => + R accept(ExpressionVisitor visitor, [R? context]) => visitor.visitLiteralMapExpression(this, context); @override diff --git a/pkgs/code_builder/lib/src/specs/extension.dart b/pkgs/code_builder/lib/src/specs/extension.dart index 92604719e..bc4055def 100644 --- a/pkgs/code_builder/lib/src/specs/extension.dart +++ b/pkgs/code_builder/lib/src/specs/extension.dart @@ -33,8 +33,7 @@ abstract class Extension extends Object @override BuiltList get docs; - @nullable - Reference get on; + Reference? get on; @override BuiltList get types; @@ -43,13 +42,12 @@ abstract class Extension extends Object BuiltList get fields; /// Name of the extension - optional. - @nullable - String get name; + String? get name; @override R accept( SpecVisitor visitor, [ - R context, + R? context, ]) => visitor.visitExtension(this, context); } @@ -67,7 +65,7 @@ abstract class ExtensionBuilder extends Object @override ListBuilder docs = ListBuilder(); - Reference on; + Reference? on; @override ListBuilder types = ListBuilder(); @@ -76,5 +74,5 @@ abstract class ExtensionBuilder extends Object ListBuilder fields = ListBuilder(); /// Name of the extension - optional. - String name; + String? name; } diff --git a/pkgs/code_builder/lib/src/specs/extension.g.dart b/pkgs/code_builder/lib/src/specs/extension.g.dart index befd295f3..75ed39759 100644 --- a/pkgs/code_builder/lib/src/specs/extension.g.dart +++ b/pkgs/code_builder/lib/src/specs/extension.g.dart @@ -12,7 +12,7 @@ class _$Extension extends Extension { @override final BuiltList docs; @override - final Reference on; + final Reference? on; @override final BuiltList types; @override @@ -20,35 +20,26 @@ class _$Extension extends Extension { @override final BuiltList fields; @override - final String name; + final String? name; - factory _$Extension([void Function(ExtensionBuilder) updates]) => + factory _$Extension([void Function(ExtensionBuilder)? updates]) => (new ExtensionBuilder()..update(updates)).build() as _$Extension; _$Extension._( - {this.annotations, - this.docs, + {required this.annotations, + required this.docs, this.on, - this.types, - this.methods, - this.fields, + required this.types, + required this.methods, + required this.fields, this.name}) : super._() { - if (annotations == null) { - throw new BuiltValueNullFieldError('Extension', 'annotations'); - } - if (docs == null) { - throw new BuiltValueNullFieldError('Extension', 'docs'); - } - if (types == null) { - throw new BuiltValueNullFieldError('Extension', 'types'); - } - if (methods == null) { - throw new BuiltValueNullFieldError('Extension', 'methods'); - } - if (fields == null) { - throw new BuiltValueNullFieldError('Extension', 'fields'); - } + BuiltValueNullFieldError.checkNotNull( + annotations, 'Extension', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, 'Extension', 'docs'); + BuiltValueNullFieldError.checkNotNull(types, 'Extension', 'types'); + BuiltValueNullFieldError.checkNotNull(methods, 'Extension', 'methods'); + BuiltValueNullFieldError.checkNotNull(fields, 'Extension', 'fields'); } @override @@ -100,12 +91,12 @@ class _$Extension extends Extension { } class _$ExtensionBuilder extends ExtensionBuilder { - _$Extension _$v; + _$Extension? _$v; @override ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations; } @override @@ -117,7 +108,7 @@ class _$ExtensionBuilder extends ExtensionBuilder { @override ListBuilder get docs { _$this; - return super.docs ??= new ListBuilder(); + return super.docs; } @override @@ -127,13 +118,13 @@ class _$ExtensionBuilder extends ExtensionBuilder { } @override - Reference get on { + Reference? get on { _$this; return super.on; } @override - set on(Reference on) { + set on(Reference? on) { _$this; super.on = on; } @@ -141,7 +132,7 @@ class _$ExtensionBuilder extends ExtensionBuilder { @override ListBuilder get types { _$this; - return super.types ??= new ListBuilder(); + return super.types; } @override @@ -153,7 +144,7 @@ class _$ExtensionBuilder extends ExtensionBuilder { @override ListBuilder get methods { _$this; - return super.methods ??= new ListBuilder(); + return super.methods; } @override @@ -165,7 +156,7 @@ class _$ExtensionBuilder extends ExtensionBuilder { @override ListBuilder get fields { _$this; - return super.fields ??= new ListBuilder(); + return super.fields; } @override @@ -175,13 +166,13 @@ class _$ExtensionBuilder extends ExtensionBuilder { } @override - String get name { + String? get name { _$this; return super.name; } @override - set name(String name) { + set name(String? name) { _$this; super.name = name; } @@ -189,14 +180,15 @@ class _$ExtensionBuilder extends ExtensionBuilder { _$ExtensionBuilder() : super._(); ExtensionBuilder get _$this { - if (_$v != null) { - super.annotations = _$v.annotations?.toBuilder(); - super.docs = _$v.docs?.toBuilder(); - super.on = _$v.on; - super.types = _$v.types?.toBuilder(); - super.methods = _$v.methods?.toBuilder(); - super.fields = _$v.fields?.toBuilder(); - super.name = _$v.name; + final $v = _$v; + if ($v != null) { + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); + super.on = $v.on; + super.types = $v.types.toBuilder(); + super.methods = $v.methods.toBuilder(); + super.fields = $v.fields.toBuilder(); + super.name = $v.name; _$v = null; } return this; @@ -204,14 +196,12 @@ class _$ExtensionBuilder extends ExtensionBuilder { @override void replace(Extension other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$Extension; } @override - void update(void Function(ExtensionBuilder) updates) { + void update(void Function(ExtensionBuilder)? updates) { if (updates != null) updates(this); } @@ -229,7 +219,7 @@ class _$ExtensionBuilder extends ExtensionBuilder { fields: fields.build(), name: name); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'annotations'; annotations.build(); diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index ddb0d285e..97168343a 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -31,8 +31,7 @@ abstract class Field extends Object BuiltList get docs; /// Field assignment, if any. - @nullable - Code get assignment; + Code? get assignment; /// Whether this field should be prefixed with `static`. /// @@ -42,15 +41,14 @@ abstract class Field extends Object /// Name of the field. String get name; - @nullable - Reference get type; + Reference? get type; FieldModifier get modifier; @override R accept( SpecVisitor visitor, [ - R context, + R? context, ]) => visitor.visitField(this, context); } @@ -75,7 +73,7 @@ abstract class FieldBuilder extends Object ListBuilder docs = ListBuilder(); /// Field assignment, if any. - Code assignment; + Code? assignment; /// Whether this field should be prefixed with `static`. /// @@ -83,9 +81,9 @@ abstract class FieldBuilder extends Object bool static = false; /// Name of the field. - String name; + String? name; - Reference type; + Reference? type; FieldModifier modifier = FieldModifier.var$; } diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 5dfccd9bd..651a6a9fd 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -12,43 +12,33 @@ class _$Field extends Field { @override final BuiltList docs; @override - final Code assignment; + final Code? assignment; @override final bool static; @override final String name; @override - final Reference type; + final Reference? type; @override final FieldModifier modifier; - factory _$Field([void Function(FieldBuilder) updates]) => + factory _$Field([void Function(FieldBuilder)? updates]) => (new FieldBuilder()..update(updates)).build() as _$Field; _$Field._( - {this.annotations, - this.docs, + {required this.annotations, + required this.docs, this.assignment, - this.static, - this.name, + required this.static, + required this.name, this.type, - this.modifier}) + required this.modifier}) : super._() { - if (annotations == null) { - throw new BuiltValueNullFieldError('Field', 'annotations'); - } - if (docs == null) { - throw new BuiltValueNullFieldError('Field', 'docs'); - } - if (static == null) { - throw new BuiltValueNullFieldError('Field', 'static'); - } - if (name == null) { - throw new BuiltValueNullFieldError('Field', 'name'); - } - if (modifier == null) { - throw new BuiltValueNullFieldError('Field', 'modifier'); - } + BuiltValueNullFieldError.checkNotNull(annotations, 'Field', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, 'Field', 'docs'); + BuiltValueNullFieldError.checkNotNull(static, 'Field', 'static'); + BuiltValueNullFieldError.checkNotNull(name, 'Field', 'name'); + BuiltValueNullFieldError.checkNotNull(modifier, 'Field', 'modifier'); } @override @@ -100,12 +90,12 @@ class _$Field extends Field { } class _$FieldBuilder extends FieldBuilder { - _$Field _$v; + _$Field? _$v; @override ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations; } @override @@ -117,7 +107,7 @@ class _$FieldBuilder extends FieldBuilder { @override ListBuilder get docs { _$this; - return super.docs ??= new ListBuilder(); + return super.docs; } @override @@ -127,13 +117,13 @@ class _$FieldBuilder extends FieldBuilder { } @override - Code get assignment { + Code? get assignment { _$this; return super.assignment; } @override - set assignment(Code assignment) { + set assignment(Code? assignment) { _$this; super.assignment = assignment; } @@ -151,25 +141,25 @@ class _$FieldBuilder extends FieldBuilder { } @override - String get name { + String? get name { _$this; return super.name; } @override - set name(String name) { + set name(String? name) { _$this; super.name = name; } @override - Reference get type { + Reference? get type { _$this; return super.type; } @override - set type(Reference type) { + set type(Reference? type) { _$this; super.type = type; } @@ -189,14 +179,15 @@ class _$FieldBuilder extends FieldBuilder { _$FieldBuilder() : super._(); FieldBuilder get _$this { - if (_$v != null) { - super.annotations = _$v.annotations?.toBuilder(); - super.docs = _$v.docs?.toBuilder(); - super.assignment = _$v.assignment; - super.static = _$v.static; - super.name = _$v.name; - super.type = _$v.type; - super.modifier = _$v.modifier; + final $v = _$v; + if ($v != null) { + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); + super.assignment = $v.assignment; + super.static = $v.static; + super.name = $v.name; + super.type = $v.type; + super.modifier = $v.modifier; _$v = null; } return this; @@ -204,14 +195,12 @@ class _$FieldBuilder extends FieldBuilder { @override void replace(Field other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$Field; } @override - void update(void Function(FieldBuilder) updates) { + void update(void Function(FieldBuilder)? updates) { if (updates != null) updates(this); } @@ -224,12 +213,15 @@ class _$FieldBuilder extends FieldBuilder { annotations: annotations.build(), docs: docs.build(), assignment: assignment, - static: static, - name: name, + static: BuiltValueNullFieldError.checkNotNull( + static, 'Field', 'static'), + name: + BuiltValueNullFieldError.checkNotNull(name, 'Field', 'name'), type: type, - modifier: modifier); + modifier: BuiltValueNullFieldError.checkNotNull( + modifier, 'Field', 'modifier')); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'annotations'; annotations.build(); diff --git a/pkgs/code_builder/lib/src/specs/library.dart b/pkgs/code_builder/lib/src/specs/library.dart index d5722464d..d4ee59761 100644 --- a/pkgs/code_builder/lib/src/specs/library.dart +++ b/pkgs/code_builder/lib/src/specs/library.dart @@ -23,7 +23,7 @@ abstract class Library implements Built, Spec { @override R accept( SpecVisitor visitor, [ - R context, + R? context, ]) => visitor.visitLibrary(this, context); } diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index d302a94bc..b9178ec5c 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -12,16 +12,12 @@ class _$Library extends Library { @override final BuiltList body; - factory _$Library([void Function(LibraryBuilder) updates]) => + factory _$Library([void Function(LibraryBuilder)? updates]) => (new LibraryBuilder()..update(updates)).build() as _$Library; - _$Library._({this.directives, this.body}) : super._() { - if (directives == null) { - throw new BuiltValueNullFieldError('Library', 'directives'); - } - if (body == null) { - throw new BuiltValueNullFieldError('Library', 'body'); - } + _$Library._({required this.directives, required this.body}) : super._() { + BuiltValueNullFieldError.checkNotNull(directives, 'Library', 'directives'); + BuiltValueNullFieldError.checkNotNull(body, 'Library', 'body'); } @override @@ -54,12 +50,12 @@ class _$Library extends Library { } class _$LibraryBuilder extends LibraryBuilder { - _$Library _$v; + _$Library? _$v; @override ListBuilder get directives { _$this; - return super.directives ??= new ListBuilder(); + return super.directives; } @override @@ -71,7 +67,7 @@ class _$LibraryBuilder extends LibraryBuilder { @override ListBuilder get body { _$this; - return super.body ??= new ListBuilder(); + return super.body; } @override @@ -83,9 +79,10 @@ class _$LibraryBuilder extends LibraryBuilder { _$LibraryBuilder() : super._(); LibraryBuilder get _$this { - if (_$v != null) { - super.directives = _$v.directives?.toBuilder(); - super.body = _$v.body?.toBuilder(); + final $v = _$v; + if ($v != null) { + super.directives = $v.directives.toBuilder(); + super.body = $v.body.toBuilder(); _$v = null; } return this; @@ -93,14 +90,12 @@ class _$LibraryBuilder extends LibraryBuilder { @override void replace(Library other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$Library; } @override - void update(void Function(LibraryBuilder) updates) { + void update(void Function(LibraryBuilder)? updates) { if (updates != null) updates(this); } @@ -111,7 +106,7 @@ class _$LibraryBuilder extends LibraryBuilder { _$result = _$v ?? new _$Library._(directives: directives.build(), body: body.build()); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'directives'; directives.build(); diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 9be39296e..68b4049d6 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -25,7 +25,7 @@ abstract class Method extends Object implements Built, Spec { factory Method([void Function(MethodBuilder) updates]) = _$Method; - factory Method.returnsVoid([void Function(MethodBuilder) updates]) => + factory Method.returnsVoid([void Function(MethodBuilder)? updates]) => Method((b) { if (updates != null) { updates(b); @@ -51,8 +51,7 @@ abstract class Method extends Object BuiltList get requiredParameters; /// Body of the method. - @nullable - Code get body; + Code? get body; /// Whether the method should be prefixed with `external`. bool get external; @@ -60,8 +59,7 @@ abstract class Method extends Object /// Whether this method is a simple lambda expression. /// /// May be `null` to be inferred based on the value of [body]. - @nullable - bool get lambda; + bool? get lambda; /// Whether this method should be prefixed with `static`. /// @@ -71,24 +69,20 @@ abstract class Method extends Object /// Name of the method or function. /// /// May be `null` when being used as a [closure]. - @nullable - String get name; + String? get name; /// Whether this is a getter or setter. - @nullable - MethodType get type; + MethodType? get type; /// Whether this method is `async`, `async*`, or `sync*`. - @nullable - MethodModifier get modifier; + MethodModifier? get modifier; - @nullable - Reference get returns; + Reference? get returns; @override R accept( SpecVisitor visitor, [ - R context, + R? context, ]) => visitor.visitMethod(this, context); @@ -106,6 +100,11 @@ abstract class MethodBuilder extends Object MethodBuilder._(); + @override + void update(void Function(MethodBuilder)? updates) { + updates?.call(this); + } + @override ListBuilder annotations = ListBuilder(); @@ -122,7 +121,7 @@ abstract class MethodBuilder extends Object ListBuilder requiredParameters = ListBuilder(); /// Body of the method. - Code body; + Code? body; /// Whether the method should be prefixed with `external`. bool external = false; @@ -130,7 +129,7 @@ abstract class MethodBuilder extends Object /// Whether this method is a simple lambda expression. /// /// If not specified this is inferred from the [body]. - bool lambda; + bool? lambda; /// Whether this method should be prefixed with `static`. /// @@ -138,15 +137,15 @@ abstract class MethodBuilder extends Object bool static = false; /// Name of the method or function. - String name; + String? name; /// Whether this is a getter or setter. - MethodType type; + MethodType? type; /// Whether this method is `async`, `async*`, or `sync*`. - MethodModifier modifier; + MethodModifier? modifier; - Reference returns; + Reference? returns; } enum MethodType { @@ -168,8 +167,7 @@ abstract class Parameter extends Object Parameter._(); /// If not `null`, a default assignment if the parameter is optional. - @nullable - Code get defaultTo; + Code? get defaultTo; /// Name of the parameter. String get name; @@ -192,8 +190,7 @@ abstract class Parameter extends Object BuiltList get types; /// Type of the parameter; - @nullable - Reference get type; + Reference? get type; /// Whether this parameter should be annotated with the `required` keyword. /// @@ -216,11 +213,16 @@ abstract class ParameterBuilder extends Object ParameterBuilder._(); + @override + void update(void Function(ParameterBuilder)? updates) { + updates?.call(this); + } + /// If not `null`, a default assignment if the parameter is optional. - Code defaultTo; + Code? defaultTo; /// Name of the parameter. - String name; + late final String name; /// Whether this parameter should be named, if optional. bool named = false; @@ -240,7 +242,7 @@ abstract class ParameterBuilder extends Object ListBuilder types = ListBuilder(); /// Type of the parameter; - Reference type; + Reference? type; /// Whether this parameter should be annotated with the `required` keyword. /// diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index ba721b57f..c44d5f96f 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -18,61 +18,49 @@ class _$Method extends Method { @override final BuiltList requiredParameters; @override - final Code body; + final Code? body; @override final bool external; @override - final bool lambda; + final bool? lambda; @override final bool static; @override - final String name; + final String? name; @override - final MethodType type; + final MethodType? type; @override - final MethodModifier modifier; + final MethodModifier? modifier; @override - final Reference returns; + final Reference? returns; - factory _$Method([void Function(MethodBuilder) updates]) => + factory _$Method([void Function(MethodBuilder)? updates]) => (new MethodBuilder()..update(updates)).build() as _$Method; _$Method._( - {this.annotations, - this.docs, - this.types, - this.optionalParameters, - this.requiredParameters, + {required this.annotations, + required this.docs, + required this.types, + required this.optionalParameters, + required this.requiredParameters, this.body, - this.external, + required this.external, this.lambda, - this.static, + required this.static, this.name, this.type, this.modifier, this.returns}) : super._() { - if (annotations == null) { - throw new BuiltValueNullFieldError('Method', 'annotations'); - } - if (docs == null) { - throw new BuiltValueNullFieldError('Method', 'docs'); - } - if (types == null) { - throw new BuiltValueNullFieldError('Method', 'types'); - } - if (optionalParameters == null) { - throw new BuiltValueNullFieldError('Method', 'optionalParameters'); - } - if (requiredParameters == null) { - throw new BuiltValueNullFieldError('Method', 'requiredParameters'); - } - if (external == null) { - throw new BuiltValueNullFieldError('Method', 'external'); - } - if (static == null) { - throw new BuiltValueNullFieldError('Method', 'static'); - } + BuiltValueNullFieldError.checkNotNull(annotations, 'Method', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, 'Method', 'docs'); + BuiltValueNullFieldError.checkNotNull(types, 'Method', 'types'); + BuiltValueNullFieldError.checkNotNull( + optionalParameters, 'Method', 'optionalParameters'); + BuiltValueNullFieldError.checkNotNull( + requiredParameters, 'Method', 'requiredParameters'); + BuiltValueNullFieldError.checkNotNull(external, 'Method', 'external'); + BuiltValueNullFieldError.checkNotNull(static, 'Method', 'static'); } @override @@ -152,12 +140,12 @@ class _$Method extends Method { } class _$MethodBuilder extends MethodBuilder { - _$Method _$v; + _$Method? _$v; @override ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations; } @override @@ -169,7 +157,7 @@ class _$MethodBuilder extends MethodBuilder { @override ListBuilder get docs { _$this; - return super.docs ??= new ListBuilder(); + return super.docs; } @override @@ -181,7 +169,7 @@ class _$MethodBuilder extends MethodBuilder { @override ListBuilder get types { _$this; - return super.types ??= new ListBuilder(); + return super.types; } @override @@ -193,7 +181,7 @@ class _$MethodBuilder extends MethodBuilder { @override ListBuilder get optionalParameters { _$this; - return super.optionalParameters ??= new ListBuilder(); + return super.optionalParameters; } @override @@ -205,7 +193,7 @@ class _$MethodBuilder extends MethodBuilder { @override ListBuilder get requiredParameters { _$this; - return super.requiredParameters ??= new ListBuilder(); + return super.requiredParameters; } @override @@ -215,13 +203,13 @@ class _$MethodBuilder extends MethodBuilder { } @override - Code get body { + Code? get body { _$this; return super.body; } @override - set body(Code body) { + set body(Code? body) { _$this; super.body = body; } @@ -239,13 +227,13 @@ class _$MethodBuilder extends MethodBuilder { } @override - bool get lambda { + bool? get lambda { _$this; return super.lambda; } @override - set lambda(bool lambda) { + set lambda(bool? lambda) { _$this; super.lambda = lambda; } @@ -263,49 +251,49 @@ class _$MethodBuilder extends MethodBuilder { } @override - String get name { + String? get name { _$this; return super.name; } @override - set name(String name) { + set name(String? name) { _$this; super.name = name; } @override - MethodType get type { + MethodType? get type { _$this; return super.type; } @override - set type(MethodType type) { + set type(MethodType? type) { _$this; super.type = type; } @override - MethodModifier get modifier { + MethodModifier? get modifier { _$this; return super.modifier; } @override - set modifier(MethodModifier modifier) { + set modifier(MethodModifier? modifier) { _$this; super.modifier = modifier; } @override - Reference get returns { + Reference? get returns { _$this; return super.returns; } @override - set returns(Reference returns) { + set returns(Reference? returns) { _$this; super.returns = returns; } @@ -313,20 +301,21 @@ class _$MethodBuilder extends MethodBuilder { _$MethodBuilder() : super._(); MethodBuilder get _$this { - if (_$v != null) { - super.annotations = _$v.annotations?.toBuilder(); - super.docs = _$v.docs?.toBuilder(); - super.types = _$v.types?.toBuilder(); - super.optionalParameters = _$v.optionalParameters?.toBuilder(); - super.requiredParameters = _$v.requiredParameters?.toBuilder(); - super.body = _$v.body; - super.external = _$v.external; - super.lambda = _$v.lambda; - super.static = _$v.static; - super.name = _$v.name; - super.type = _$v.type; - super.modifier = _$v.modifier; - super.returns = _$v.returns; + final $v = _$v; + if ($v != null) { + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); + super.types = $v.types.toBuilder(); + super.optionalParameters = $v.optionalParameters.toBuilder(); + super.requiredParameters = $v.requiredParameters.toBuilder(); + super.body = $v.body; + super.external = $v.external; + super.lambda = $v.lambda; + super.static = $v.static; + super.name = $v.name; + super.type = $v.type; + super.modifier = $v.modifier; + super.returns = $v.returns; _$v = null; } return this; @@ -334,14 +323,12 @@ class _$MethodBuilder extends MethodBuilder { @override void replace(Method other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$Method; } @override - void update(void Function(MethodBuilder) updates) { + void update(void Function(MethodBuilder)? updates) { if (updates != null) updates(this); } @@ -357,15 +344,17 @@ class _$MethodBuilder extends MethodBuilder { optionalParameters: optionalParameters.build(), requiredParameters: requiredParameters.build(), body: body, - external: external, + external: BuiltValueNullFieldError.checkNotNull( + external, 'Method', 'external'), lambda: lambda, - static: static, + static: BuiltValueNullFieldError.checkNotNull( + static, 'Method', 'static'), name: name, type: type, modifier: modifier, returns: returns); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'annotations'; annotations.build(); @@ -390,7 +379,7 @@ class _$MethodBuilder extends MethodBuilder { class _$Parameter extends Parameter { @override - final Code defaultTo; + final Code? defaultTo; @override final String name; @override @@ -404,51 +393,36 @@ class _$Parameter extends Parameter { @override final BuiltList types; @override - final Reference type; + final Reference? type; @override final bool required; @override final bool covariant; - factory _$Parameter([void Function(ParameterBuilder) updates]) => + factory _$Parameter([void Function(ParameterBuilder)? updates]) => (new ParameterBuilder()..update(updates)).build() as _$Parameter; _$Parameter._( {this.defaultTo, - this.name, - this.named, - this.toThis, - this.annotations, - this.docs, - this.types, + required this.name, + required this.named, + required this.toThis, + required this.annotations, + required this.docs, + required this.types, this.type, - this.required, - this.covariant}) + required this.required, + required this.covariant}) : super._() { - if (name == null) { - throw new BuiltValueNullFieldError('Parameter', 'name'); - } - if (named == null) { - throw new BuiltValueNullFieldError('Parameter', 'named'); - } - if (toThis == null) { - throw new BuiltValueNullFieldError('Parameter', 'toThis'); - } - if (annotations == null) { - throw new BuiltValueNullFieldError('Parameter', 'annotations'); - } - if (docs == null) { - throw new BuiltValueNullFieldError('Parameter', 'docs'); - } - if (types == null) { - throw new BuiltValueNullFieldError('Parameter', 'types'); - } - if (required == null) { - throw new BuiltValueNullFieldError('Parameter', 'required'); - } - if (covariant == null) { - throw new BuiltValueNullFieldError('Parameter', 'covariant'); - } + BuiltValueNullFieldError.checkNotNull(name, 'Parameter', 'name'); + BuiltValueNullFieldError.checkNotNull(named, 'Parameter', 'named'); + BuiltValueNullFieldError.checkNotNull(toThis, 'Parameter', 'toThis'); + BuiltValueNullFieldError.checkNotNull( + annotations, 'Parameter', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, 'Parameter', 'docs'); + BuiltValueNullFieldError.checkNotNull(types, 'Parameter', 'types'); + BuiltValueNullFieldError.checkNotNull(required, 'Parameter', 'required'); + BuiltValueNullFieldError.checkNotNull(covariant, 'Parameter', 'covariant'); } @override @@ -514,16 +488,16 @@ class _$Parameter extends Parameter { } class _$ParameterBuilder extends ParameterBuilder { - _$Parameter _$v; + _$Parameter? _$v; @override - Code get defaultTo { + Code? get defaultTo { _$this; return super.defaultTo; } @override - set defaultTo(Code defaultTo) { + set defaultTo(Code? defaultTo) { _$this; super.defaultTo = defaultTo; } @@ -567,7 +541,7 @@ class _$ParameterBuilder extends ParameterBuilder { @override ListBuilder get annotations { _$this; - return super.annotations ??= new ListBuilder(); + return super.annotations; } @override @@ -579,7 +553,7 @@ class _$ParameterBuilder extends ParameterBuilder { @override ListBuilder get docs { _$this; - return super.docs ??= new ListBuilder(); + return super.docs; } @override @@ -591,7 +565,7 @@ class _$ParameterBuilder extends ParameterBuilder { @override ListBuilder get types { _$this; - return super.types ??= new ListBuilder(); + return super.types; } @override @@ -601,13 +575,13 @@ class _$ParameterBuilder extends ParameterBuilder { } @override - Reference get type { + Reference? get type { _$this; return super.type; } @override - set type(Reference type) { + set type(Reference? type) { _$this; super.type = type; } @@ -639,17 +613,18 @@ class _$ParameterBuilder extends ParameterBuilder { _$ParameterBuilder() : super._(); ParameterBuilder get _$this { - if (_$v != null) { - super.defaultTo = _$v.defaultTo; - super.name = _$v.name; - super.named = _$v.named; - super.toThis = _$v.toThis; - super.annotations = _$v.annotations?.toBuilder(); - super.docs = _$v.docs?.toBuilder(); - super.types = _$v.types?.toBuilder(); - super.type = _$v.type; - super.required = _$v.required; - super.covariant = _$v.covariant; + final $v = _$v; + if ($v != null) { + super.defaultTo = $v.defaultTo; + super.name = $v.name; + super.named = $v.named; + super.toThis = $v.toThis; + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); + super.types = $v.types.toBuilder(); + super.type = $v.type; + super.required = $v.required; + super.covariant = $v.covariant; _$v = null; } return this; @@ -657,14 +632,12 @@ class _$ParameterBuilder extends ParameterBuilder { @override void replace(Parameter other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$Parameter; } @override - void update(void Function(ParameterBuilder) updates) { + void update(void Function(ParameterBuilder)? updates) { if (updates != null) updates(this); } @@ -675,17 +648,22 @@ class _$ParameterBuilder extends ParameterBuilder { _$result = _$v ?? new _$Parameter._( defaultTo: defaultTo, - name: name, - named: named, - toThis: toThis, + name: BuiltValueNullFieldError.checkNotNull( + name, 'Parameter', 'name'), + named: BuiltValueNullFieldError.checkNotNull( + named, 'Parameter', 'named'), + toThis: BuiltValueNullFieldError.checkNotNull( + toThis, 'Parameter', 'toThis'), annotations: annotations.build(), docs: docs.build(), types: types.build(), type: type, - required: required, - covariant: covariant); + required: BuiltValueNullFieldError.checkNotNull( + required, 'Parameter', 'required'), + covariant: BuiltValueNullFieldError.checkNotNull( + covariant, 'Parameter', 'covariant')); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'annotations'; annotations.build(); diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 355d84c4a..d8850579d 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -14,7 +14,7 @@ import 'expression.dart'; import 'type_reference.dart'; /// Short-hand for `Reference(symbol, url)`. -Reference refer(String symbol, [String url]) => Reference(symbol, url); +Reference refer(String symbol, [String? url]) => Reference(symbol, url); /// A reference to [symbol], such as a class, or top-level method or field. /// @@ -25,7 +25,7 @@ class Reference extends Expression implements Spec { /// Relative, `package:` or `dart:` URL of the library. /// /// May be omitted (`null`) in order to express "same library". - final String url; + final String? url; /// Name of the class, method, or field. final String symbol; @@ -36,7 +36,7 @@ class Reference extends Expression implements Spec { @override R accept( SpecVisitor visitor, [ - R context, + R? context, ]) => visitor.visitReference(this, context); diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index c10ca5188..df3c4d1b7 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -28,13 +28,12 @@ abstract class FunctionType extends Expression @override R accept( SpecVisitor visitor, [ - R context, + R? context, ]) => visitor.visitFunctionType(this, context); /// Return type. - @nullable - Reference get returnType; + Reference? get returnType; @override BuiltList get types; @@ -49,10 +48,11 @@ abstract class FunctionType extends Expression BuiltMap get namedParameters; @override - String get url => null; + String? get url => null; @override - String get symbol => null; + String get symbol => throw UnsupportedError( + 'Getting the `symbol` of a function type is not supported'); @override Reference get type => this; @@ -61,8 +61,7 @@ abstract class FunctionType extends Expression /// /// An emitter may ignore this if the output is not targeting a Dart language /// version that supports null safety. - @nullable - bool get isNullable; + bool? get isNullable; @override Expression newInstance( @@ -109,7 +108,7 @@ abstract class FunctionTypeBuilder extends Object FunctionTypeBuilder._(); - Reference returnType; + Reference? returnType; @override ListBuilder types = ListBuilder(); @@ -121,5 +120,9 @@ abstract class FunctionTypeBuilder extends Object MapBuilder namedParameters = MapBuilder(); - bool isNullable; + bool? isNullable; + + String? url; + + String? symbol; } diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart index 2c9906c0d..c84f537a5 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -8,7 +8,7 @@ part of 'type_function.dart'; class _$FunctionType extends FunctionType { @override - final Reference returnType; + final Reference? returnType; @override final BuiltList types; @override @@ -18,31 +18,26 @@ class _$FunctionType extends FunctionType { @override final BuiltMap namedParameters; @override - final bool isNullable; + final bool? isNullable; - factory _$FunctionType([void Function(FunctionTypeBuilder) updates]) => + factory _$FunctionType([void Function(FunctionTypeBuilder)? updates]) => (new FunctionTypeBuilder()..update(updates)).build() as _$FunctionType; _$FunctionType._( {this.returnType, - this.types, - this.requiredParameters, - this.optionalParameters, - this.namedParameters, + required this.types, + required this.requiredParameters, + required this.optionalParameters, + required this.namedParameters, this.isNullable}) : super._() { - if (types == null) { - throw new BuiltValueNullFieldError('FunctionType', 'types'); - } - if (requiredParameters == null) { - throw new BuiltValueNullFieldError('FunctionType', 'requiredParameters'); - } - if (optionalParameters == null) { - throw new BuiltValueNullFieldError('FunctionType', 'optionalParameters'); - } - if (namedParameters == null) { - throw new BuiltValueNullFieldError('FunctionType', 'namedParameters'); - } + BuiltValueNullFieldError.checkNotNull(types, 'FunctionType', 'types'); + BuiltValueNullFieldError.checkNotNull( + requiredParameters, 'FunctionType', 'requiredParameters'); + BuiltValueNullFieldError.checkNotNull( + optionalParameters, 'FunctionType', 'optionalParameters'); + BuiltValueNullFieldError.checkNotNull( + namedParameters, 'FunctionType', 'namedParameters'); } @override @@ -91,16 +86,16 @@ class _$FunctionType extends FunctionType { } class _$FunctionTypeBuilder extends FunctionTypeBuilder { - _$FunctionType _$v; + _$FunctionType? _$v; @override - Reference get returnType { + Reference? get returnType { _$this; return super.returnType; } @override - set returnType(Reference returnType) { + set returnType(Reference? returnType) { _$this; super.returnType = returnType; } @@ -108,7 +103,7 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { @override ListBuilder get types { _$this; - return super.types ??= new ListBuilder(); + return super.types; } @override @@ -120,7 +115,7 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { @override ListBuilder get requiredParameters { _$this; - return super.requiredParameters ??= new ListBuilder(); + return super.requiredParameters; } @override @@ -132,7 +127,7 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { @override ListBuilder get optionalParameters { _$this; - return super.optionalParameters ??= new ListBuilder(); + return super.optionalParameters; } @override @@ -144,7 +139,7 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { @override MapBuilder get namedParameters { _$this; - return super.namedParameters ??= new MapBuilder(); + return super.namedParameters; } @override @@ -154,13 +149,13 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { } @override - bool get isNullable { + bool? get isNullable { _$this; return super.isNullable; } @override - set isNullable(bool isNullable) { + set isNullable(bool? isNullable) { _$this; super.isNullable = isNullable; } @@ -168,13 +163,14 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { _$FunctionTypeBuilder() : super._(); FunctionTypeBuilder get _$this { - if (_$v != null) { - super.returnType = _$v.returnType; - super.types = _$v.types?.toBuilder(); - super.requiredParameters = _$v.requiredParameters?.toBuilder(); - super.optionalParameters = _$v.optionalParameters?.toBuilder(); - super.namedParameters = _$v.namedParameters?.toBuilder(); - super.isNullable = _$v.isNullable; + final $v = _$v; + if ($v != null) { + super.returnType = $v.returnType; + super.types = $v.types.toBuilder(); + super.requiredParameters = $v.requiredParameters.toBuilder(); + super.optionalParameters = $v.optionalParameters.toBuilder(); + super.namedParameters = $v.namedParameters.toBuilder(); + super.isNullable = $v.isNullable; _$v = null; } return this; @@ -182,14 +178,12 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { @override void replace(FunctionType other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$FunctionType; } @override - void update(void Function(FunctionTypeBuilder) updates) { + void update(void Function(FunctionTypeBuilder)? updates) { if (updates != null) updates(this); } @@ -206,7 +200,7 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { namedParameters: namedParameters.build(), isNullable: isNullable); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'types'; types.build(); diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index 4424598f7..2dd75a554 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -29,12 +29,10 @@ abstract class TypeReference extends Expression String get symbol; @override - @nullable - String get url; + String? get url; /// Optional bound generic. - @nullable - Reference get bound; + Reference? get bound; @override BuiltList get types; @@ -43,13 +41,12 @@ abstract class TypeReference extends Expression /// /// An emitter may ignore this if the output is not targeting a Dart language /// version that supports null safety. - @nullable - bool get isNullable; + bool? get isNullable; @override R accept( SpecVisitor visitor, [ - R context, + R? context, ]) => visitor.visitType(this, context); @@ -123,12 +120,12 @@ abstract class TypeReferenceBuilder extends Object TypeReferenceBuilder._(); - String symbol; + String? symbol; - String url; + String? url; /// Optional bound generic. - Reference bound; + Reference? bound; @override ListBuilder types = ListBuilder(); @@ -137,5 +134,5 @@ abstract class TypeReferenceBuilder extends Object /// /// An emitter may ignore this if the output is not targeting a Dart language /// version that supports null safety. - bool isNullable; + bool? isNullable; } diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index 315f3e5dc..e62cbdc7a 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -10,26 +10,26 @@ class _$TypeReference extends TypeReference { @override final String symbol; @override - final String url; + final String? url; @override - final Reference bound; + final Reference? bound; @override final BuiltList types; @override - final bool isNullable; + final bool? isNullable; - factory _$TypeReference([void Function(TypeReferenceBuilder) updates]) => + factory _$TypeReference([void Function(TypeReferenceBuilder)? updates]) => (new TypeReferenceBuilder()..update(updates)).build() as _$TypeReference; _$TypeReference._( - {this.symbol, this.url, this.bound, this.types, this.isNullable}) + {required this.symbol, + this.url, + this.bound, + required this.types, + this.isNullable}) : super._() { - if (symbol == null) { - throw new BuiltValueNullFieldError('TypeReference', 'symbol'); - } - if (types == null) { - throw new BuiltValueNullFieldError('TypeReference', 'types'); - } + BuiltValueNullFieldError.checkNotNull(symbol, 'TypeReference', 'symbol'); + BuiltValueNullFieldError.checkNotNull(types, 'TypeReference', 'types'); } @override @@ -72,40 +72,40 @@ class _$TypeReference extends TypeReference { } class _$TypeReferenceBuilder extends TypeReferenceBuilder { - _$TypeReference _$v; + _$TypeReference? _$v; @override - String get symbol { + String? get symbol { _$this; return super.symbol; } @override - set symbol(String symbol) { + set symbol(String? symbol) { _$this; super.symbol = symbol; } @override - String get url { + String? get url { _$this; return super.url; } @override - set url(String url) { + set url(String? url) { _$this; super.url = url; } @override - Reference get bound { + Reference? get bound { _$this; return super.bound; } @override - set bound(Reference bound) { + set bound(Reference? bound) { _$this; super.bound = bound; } @@ -113,7 +113,7 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { @override ListBuilder get types { _$this; - return super.types ??= new ListBuilder(); + return super.types; } @override @@ -123,13 +123,13 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { } @override - bool get isNullable { + bool? get isNullable { _$this; return super.isNullable; } @override - set isNullable(bool isNullable) { + set isNullable(bool? isNullable) { _$this; super.isNullable = isNullable; } @@ -137,12 +137,13 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { _$TypeReferenceBuilder() : super._(); TypeReferenceBuilder get _$this { - if (_$v != null) { - super.symbol = _$v.symbol; - super.url = _$v.url; - super.bound = _$v.bound; - super.types = _$v.types?.toBuilder(); - super.isNullable = _$v.isNullable; + final $v = _$v; + if ($v != null) { + super.symbol = $v.symbol; + super.url = $v.url; + super.bound = $v.bound; + super.types = $v.types.toBuilder(); + super.isNullable = $v.isNullable; _$v = null; } return this; @@ -150,14 +151,12 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { @override void replace(TypeReference other) { - if (other == null) { - throw new ArgumentError.notNull('other'); - } + ArgumentError.checkNotNull(other, 'other'); _$v = other as _$TypeReference; } @override - void update(void Function(TypeReferenceBuilder) updates) { + void update(void Function(TypeReferenceBuilder)? updates) { if (updates != null) updates(this); } @@ -167,13 +166,14 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { try { _$result = _$v ?? new _$TypeReference._( - symbol: symbol, + symbol: BuiltValueNullFieldError.checkNotNull( + symbol, 'TypeReference', 'symbol'), url: url, bound: bound, types: types.build(), isNullable: isNullable); } catch (_) { - String _$failedField; + late String _$failedField; try { _$failedField = 'types'; types.build(); diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index ed2ab4d8d..64a4428a5 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -22,31 +22,31 @@ import 'specs/type_reference.dart'; abstract class SpecVisitor { const SpecVisitor._(); - T visitAnnotation(Expression spec, [T context]); + T visitAnnotation(Expression spec, [T? context]); - T visitClass(Class spec, [T context]); + T visitClass(Class spec, [T? context]); - T visitExtension(Extension spec, [T context]); + T visitExtension(Extension spec, [T? context]); - T visitEnum(Enum spec, [T context]); + T visitEnum(Enum spec, [T? context]); - T visitConstructor(Constructor spec, String clazz, [T context]); + T visitConstructor(Constructor spec, String clazz, [T? context]); - T visitDirective(Directive spec, [T context]); + T visitDirective(Directive spec, [T? context]); - T visitField(Field spec, [T context]); + T visitField(Field spec, [T? context]); - T visitLibrary(Library spec, [T context]); + T visitLibrary(Library spec, [T? context]); - T visitFunctionType(FunctionType spec, [T context]); + T visitFunctionType(FunctionType spec, [T? context]); - T visitMethod(Method spec, [T context]); + T visitMethod(Method spec, [T? context]); - T visitReference(Reference spec, [T context]); + T visitReference(Reference spec, [T? context]); - T visitSpec(Spec spec, [T context]); + T visitSpec(Spec spec, [T? context]); - T visitType(TypeReference spec, [T context]); + T visitType(TypeReference spec, [T? context]); - T visitTypeParameters(Iterable specs, [T context]); + T visitTypeParameters(Iterable specs, [T? context]); } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index ec8525b38..3e8df8fd2 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,25 +1,29 @@ name: code_builder -version: 3.7.0 +version: 4.0.0-dev description: >- A fluent, builder-based library for generating valid Dart code homepage: https://github.com/dart-lang/code_builder environment: - sdk: '>=2.7.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: - built_collection: '>=3.0.0 <6.0.0' - built_value: '>=7.0.0 <9.0.0' - collection: ^1.14.0 - matcher: ^0.12.0 - meta: ^1.0.5 + built_collection: ^5.0.0 + built_value: ^8.0.0 + collection: ^1.15.0 + matcher: ^0.12.10 + meta: ^1.3.0 dev_dependencies: - build: ^1.0.0 - build_runner: ^1.1.0 - built_value_generator: ^7.0.0 - dart_style: ^1.0.0 - pedantic: ^1.0.0 - source_gen: ^0.9.0 - test: ^1.3.0 + build: ^2.0.0 + build_runner: ^1.12.2 + built_value_generator: ^8.0.0 + dart_style: ^2.0.0 + pedantic: ^1.10.0 + source_gen: ^1.0.0 + test: ^1.16.0 + +dependency_overrides: + # Due to dependency cycle + build_runner: ^1.12.2 diff --git a/pkgs/code_builder/test/specs/type_reference_test.dart b/pkgs/code_builder/test/specs/type_reference_test.dart index d6715e5bd..35365cbf9 100644 --- a/pkgs/code_builder/test/specs/type_reference_test.dart +++ b/pkgs/code_builder/test/specs/type_reference_test.dart @@ -22,7 +22,7 @@ void main() { }); group('in a Null Safety library', () { - DartEmitter emitter; + late DartEmitter emitter; setUp(() => emitter = DartEmitter.scoped(useNullSafetySyntax: true)); diff --git a/pkgs/code_builder/tool/src/builder.dart b/pkgs/code_builder/tool/src/builder.dart index 3863325de..4934282ef 100644 --- a/pkgs/code_builder/tool/src/builder.dart +++ b/pkgs/code_builder/tool/src/builder.dart @@ -1,6 +1,8 @@ // 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. +// +// @dart=2.9 import 'package:build/build.dart'; import 'package:built_value_generator/built_value_generator.dart'; From b1f54922fa486ea447dc7070747e1bb80d40c119 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 7 Apr 2021 12:26:29 -0700 Subject: [PATCH 175/271] Make Reference.symbol nullable (dart-lang/code_builder#320) The throwing `symbol` getter in `FunctionType` makes it difficult to perform certain sensible operations, like checking whether a given reference is to a specific known type. Rather than impose `is` checks on the call sites who want to read the `symbol`, make it explicit that not all references have symbols. This does impose some `!` operators where we use references. This is not any less safe since an exception would happen either way and we are already relying on a `FunctionType` not flowing to those call sites. --- pkgs/code_builder/lib/src/allocator.dart | 6 +++--- pkgs/code_builder/lib/src/specs/code.dart | 2 +- pkgs/code_builder/lib/src/specs/reference.dart | 5 ++++- pkgs/code_builder/lib/src/specs/type_function.dart | 3 +-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pkgs/code_builder/lib/src/allocator.dart b/pkgs/code_builder/lib/src/allocator.dart index f2300f91e..b8b36f381 100644 --- a/pkgs/code_builder/lib/src/allocator.dart +++ b/pkgs/code_builder/lib/src/allocator.dart @@ -54,7 +54,7 @@ class _Allocator implements Allocator { if (url != null) { _imports.add(url); } - return reference.symbol; + return reference.symbol!; } @override @@ -65,7 +65,7 @@ class _NullAllocator implements Allocator { const _NullAllocator(); @override - String allocate(Reference reference) => reference.symbol; + String allocate(Reference reference) => reference.symbol!; @override Iterable get imports => const []; @@ -82,7 +82,7 @@ class _PrefixedAllocator implements Allocator { final symbol = reference.symbol; final url = reference.url; if (url == null || _doNotPrefix.contains(url)) { - return symbol; + return symbol!; } return '_i${_imports.putIfAbsent(url, _nextKey)}.$symbol'; } diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index c441852af..5cc52f5e7 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -161,5 +161,5 @@ class ScopedCode implements Code { visitor.visitScopedCode(this, context); @override - String toString() => code((ref) => ref.symbol); + String toString() => code((ref) => ref.symbol!); } diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index d8850579d..6668e8117 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -28,7 +28,10 @@ class Reference extends Expression implements Spec { final String? url; /// Name of the class, method, or field. - final String symbol; + /// + /// May be `null` for references without symbols, for instance a function type + /// has no symbol. + final String? symbol; /// Create a reference to [symbol] in [url]. const Reference(this.symbol, [this.url]); diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index df3c4d1b7..ecaa4cf0c 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -51,8 +51,7 @@ abstract class FunctionType extends Expression String? get url => null; @override - String get symbol => throw UnsupportedError( - 'Getting the `symbol` of a function type is not supported'); + String? get symbol => null; @override Reference get type => this; From 05978c72823bf17a5ca7230eb1439d0a5b7dc680 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 9 Apr 2021 10:38:20 -0700 Subject: [PATCH 176/271] change the DartEmitter constructor to use named parameters (dart-lang/code_builder#319) Also dropped the defensive code for opted out apps explicitly passing null --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/emitter.dart | 13 +++++++------ pkgs/code_builder/test/e2e/injection_test.dart | 2 +- .../test/specs/code/expression_test.dart | 3 ++- pkgs/code_builder/test/specs/library_test.dart | 4 ++-- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 2cf35f19f..e8b1ce188 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ ## 4.0.0-dev * Migrate to null safety. +* Changed the DartEmittor constructor to use named optional parameters. ## 3.7.0 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 9934bdaef..a3591449d 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -71,17 +71,18 @@ class DartEmitter extends Object /// /// May specify an [Allocator] to use for symbols, otherwise uses a no-op. DartEmitter( - [this.allocator = Allocator.none, - bool? orderDirectives = false, - bool? useNullSafetySyntax = false]) - : orderDirectives = orderDirectives ?? false, - _useNullSafetySyntax = useNullSafetySyntax ?? false; + {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.simplePrefixing(), orderDirectives, useNullSafetySyntax); + allocator: Allocator.simplePrefixing(), + orderDirectives: orderDirectives, + useNullSafetySyntax: useNullSafetySyntax); static bool _isLambdaBody(Code? code) => code is ToCodeExpression && !code.isStatement; diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index 741a69761..50346212e 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -61,7 +61,7 @@ void main() { @override _i3.Thing getThing() => _i3.Thing(_module.get1(), _module.get2()); } - ''', DartEmitter(Allocator.simplePrefixing())), + ''', DartEmitter(allocator: Allocator.simplePrefixing())), ); }); } diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 123506351..aa2def1ac 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -136,7 +136,8 @@ void main() { test('should emit a scoped type as an expression', () { expect( refer('Foo', 'package:foo/foo.dart'), - equalsDart('_i1.Foo', DartEmitter(Allocator.simplePrefixing())), + equalsDart( + '_i1.Foo', DartEmitter(allocator: Allocator.simplePrefixing())), ); }); diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index 9dcb3fa2b..63b080749 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -91,7 +91,7 @@ void main() { import 'dart:collection'; final test = LinkedHashMap(); - ''', DartEmitter(Allocator())), + ''', DartEmitter(allocator: Allocator())), ); }); @@ -106,7 +106,7 @@ void main() { import 'dart:collection' as _i1; final test = _i1.LinkedHashMap(); - ''', DartEmitter(Allocator.simplePrefixing())), + ''', DartEmitter(allocator: Allocator.simplePrefixing())), ); }); From 1794da4ebf5f9b4a1858dc1b3839bb5e75b2590f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 19 Apr 2021 12:13:20 -0700 Subject: [PATCH 177/271] Add a parenthesized expression (dart-lang/code_builder#322) Fixes dart-lang/code_builder#305 Add a `ParenthesizedExpression` with special handling for the output instead of using a `Block` to avoid influencing the behavior of other calls that vary based on whether an argument is an expression or a block. --- pkgs/code_builder/CHANGELOG.md | 2 ++ .../lib/src/specs/expression.dart | 30 +++++++++++++------ .../src/specs/expression/parenthesized.dart | 16 ++++++++++ .../test/specs/code/expression_test.dart | 2 +- pkgs/code_builder/test/specs/method_test.dart | 12 ++++++++ 5 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 pkgs/code_builder/lib/src/specs/expression/parenthesized.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index e8b1ce188..bb95109e8 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -2,6 +2,8 @@ * Migrate to null safety. * Changed the DartEmittor constructor to use named optional parameters. +* Add `ParenthesizedExpression` and + `ExpressionVisitor.visitParenthesizedExpression.` ## 3.7.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 21cc69178..947ddde1c 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -19,6 +19,7 @@ part 'expression/closure.dart'; part 'expression/code.dart'; part 'expression/invoke.dart'; part 'expression/literal.dart'; +part 'expression/parenthesized.dart'; /// Represents a [code] block that wraps an [Expression]. @@ -55,15 +56,12 @@ abstract class Expression implements Spec { BinaryExpression._(_empty, expression, '!', addSpace: false); /// Returns the result of `this` `as` [other]. - Expression asA(Expression other) => CodeExpression(Block.of([ - const Code('('), - BinaryExpression._( - expression, - other, - 'as', - ).code, - const Code(')') - ])); + Expression asA(Expression other) => + ParenthesizedExpression._(BinaryExpression._( + expression, + other, + 'as', + )); /// Returns accessing the index operator (`[]`) on `this`. Expression index(Expression index) => BinaryExpression._( @@ -333,6 +331,8 @@ abstract class ExpressionVisitor implements SpecVisitor { T visitLiteralListExpression(LiteralListExpression expression, [T? context]); T visitLiteralSetExpression(LiteralSetExpression expression, [T? context]); T visitLiteralMapExpression(LiteralMapExpression expression, [T? context]); + T visitParenthesizedExpression(ParenthesizedExpression expression, + [T? context]); } /// Knowledge of how to write valid Dart code from [ExpressionVisitor]. @@ -504,6 +504,18 @@ abstract class ExpressionEmitter implements ExpressionVisitor { }); } + @override + StringSink visitParenthesizedExpression( + ParenthesizedExpression expression, [ + StringSink? output, + ]) { + output ??= StringBuffer(); + output.write('('); + expression.inner.accept(this, output); + output.write(')'); + return output; + } + /// Executes [visit] within a context which may alter the output if [isConst] /// is `true`. /// diff --git a/pkgs/code_builder/lib/src/specs/expression/parenthesized.dart b/pkgs/code_builder/lib/src/specs/expression/parenthesized.dart new file mode 100644 index 000000000..cc4d468ab --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/expression/parenthesized.dart @@ -0,0 +1,16 @@ +// Copyright (c) 2021, 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. + +part of code_builder.src.specs.expression; + +/// An [Expression] wrapped with parenthesis. +class ParenthesizedExpression extends Expression { + final Expression inner; + + const ParenthesizedExpression._(this.inner); + + @override + R accept(ExpressionVisitor visitor, [R? context]) => + visitor.visitParenthesizedExpression(this, context); +} diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index aa2def1ac..bda1b4267 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -476,7 +476,7 @@ void main() { test('should emit an explicit cast', () { expect( refer('foo').asA(refer('String')).property('length'), - equalsDart('( foo as String ).length'), + equalsDart('(foo as String).length'), ); }); diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 852297e2f..caa29e2e8 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -67,6 +67,18 @@ void main() { ); }); + test('should create a lambda method if the value is cast', () { + expect( + Method((b) => b + ..name = 'returnsCastedValue' + ..returns = refer('Foo') + ..body = refer('bar').asA(refer('Foo')).code), + equalsDart(r''' + Foo returnsCastedValue() => (bar as Foo) + '''), + ); + }); + test('should create a normal method implicitly', () { expect( Method.returnsVoid((b) => b From dfdcf8f3df7371f366d4a9a0a86750f77f9b1367 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 19 Apr 2021 13:57:49 -0700 Subject: [PATCH 178/271] release 4.0.0 (dart-lang/code_builder#321) --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index bb95109e8..92584a7f7 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 4.0.0-dev +## 4.0.0 * Migrate to null safety. * Changed the DartEmittor constructor to use named optional parameters. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 3e8df8fd2..09d83f8e3 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,6 +1,5 @@ name: code_builder -version: 4.0.0-dev - +version: 4.0.0 description: >- A fluent, builder-based library for generating valid Dart code homepage: https://github.com/dart-lang/code_builder From ff871754b0d39430eb9b81e9273cac6e8f690976 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 20 Apr 2021 13:27:28 -0700 Subject: [PATCH 179/271] CI: use dart setup (dart-lang/code_builder#323) --- .../.github/workflows/test-package.yml | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 2db209de0..6207c3a9c 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -21,16 +21,11 @@ jobs: fail-fast: false matrix: sdk: [dev] - version: [latest] - include: - - sdk: stable - version: 2.12.0 steps: - uses: actions/checkout@v2 - - uses: cedx/setup-dart@v2 # TODO(dart-lang/setup-dart#3): use the official setup-dart action + - uses: dart-lang/setup-dart@v1.0 with: - release-channel: ${{ matrix.sdk }} - version: ${{ matrix.version }} + sdk: ${{ matrix.sdk }} - id: install name: Install dependencies run: pub get @@ -41,29 +36,19 @@ jobs: run: dartanalyzer --fatal-infos --fatal-warnings . if: always() && steps.install.outcome == 'success' - # Run tests on a matrix consisting of two dimensions: - # 1. OS: ubuntu-latest, (macos-latest, windows-latest) - # 2. release channel: dev, 2.12.0 test: needs: analyze runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] - version: [latest] - include: - - os: ubuntu-latest - sdk: stable - version: 2.12.0 + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: cedx/setup-dart@v2 # TODO(dart-lang/setup-dart#3): use the official setup-dart action + - uses: dart-lang/setup-dart@v1.0 with: - release-channel: ${{ matrix.sdk }} - version: ${{ matrix.version }} + sdk: ${{ matrix.sdk }} - id: install name: Install dependencies run: pub get From 88b61d3d8e771441612032077153ad6c62873c90 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 27 Apr 2021 16:36:10 -0700 Subject: [PATCH 180/271] Fix newly enforced lint (dart-lang/code_builder#324) --- pkgs/code_builder/lib/src/specs/class.dart | 2 +- pkgs/code_builder/lib/src/specs/constructor.dart | 2 +- pkgs/code_builder/lib/src/specs/extension.dart | 2 +- pkgs/code_builder/lib/src/specs/method.dart | 2 +- pkgs/code_builder/lib/src/specs/type_function.dart | 2 +- pkgs/code_builder/lib/src/specs/type_reference.dart | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart index 13e586f5a..bd847c428 100644 --- a/pkgs/code_builder/lib/src/specs/class.dart +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -2,8 +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:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; import '../base.dart'; diff --git a/pkgs/code_builder/lib/src/specs/constructor.dart b/pkgs/code_builder/lib/src/specs/constructor.dart index 381f3c568..1c98eb516 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.dart @@ -2,8 +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:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; import '../mixins/annotations.dart'; diff --git a/pkgs/code_builder/lib/src/specs/extension.dart b/pkgs/code_builder/lib/src/specs/extension.dart index bc4055def..8df5bfb44 100644 --- a/pkgs/code_builder/lib/src/specs/extension.dart +++ b/pkgs/code_builder/lib/src/specs/extension.dart @@ -2,8 +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:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; import '../../code_builder.dart'; diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index 68b4049d6..e5b62fca9 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -2,8 +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:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; import '../base.dart'; diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index ecaa4cf0c..a1dfeadad 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -2,8 +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:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; import '../base.dart'; diff --git a/pkgs/code_builder/lib/src/specs/type_reference.dart b/pkgs/code_builder/lib/src/specs/type_reference.dart index 2dd75a554..74c7840a3 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.dart @@ -2,8 +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:built_value/built_value.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; import '../base.dart'; From 39dbdcc759b8930a8a123e649ed03b58e288a6fd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 24 May 2021 10:17:56 -0700 Subject: [PATCH 181/271] unneeded imports (dart-lang/code_builder#327) * Fix dev_dependencies * Remove unneeded imports --- pkgs/code_builder/CHANGELOG.md | 2 ++ pkgs/code_builder/lib/src/specs/extension.dart | 2 +- pkgs/code_builder/pubspec.yaml | 8 ++------ pkgs/code_builder/test/specs/extension_test.dart | 1 - 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 92584a7f7..e5edc9496 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,5 @@ +## 4.0.1-dev + ## 4.0.0 * Migrate to null safety. diff --git a/pkgs/code_builder/lib/src/specs/extension.dart b/pkgs/code_builder/lib/src/specs/extension.dart index 8df5bfb44..395994fc7 100644 --- a/pkgs/code_builder/lib/src/specs/extension.dart +++ b/pkgs/code_builder/lib/src/specs/extension.dart @@ -6,7 +6,6 @@ import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; -import '../../code_builder.dart'; import '../base.dart'; import '../mixins/annotations.dart'; import '../mixins/dartdoc.dart'; @@ -39,6 +38,7 @@ abstract class Extension extends Object BuiltList get types; BuiltList get methods; + BuiltList get fields; /// Name of the extension - optional. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 09d83f8e3..0b1edf14c 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.0.0 +version: 4.0.1-dev description: >- A fluent, builder-based library for generating valid Dart code homepage: https://github.com/dart-lang/code_builder @@ -16,13 +16,9 @@ dependencies: dev_dependencies: build: ^2.0.0 - build_runner: ^1.12.2 + build_runner: ^2.0.3 built_value_generator: ^8.0.0 dart_style: ^2.0.0 pedantic: ^1.10.0 source_gen: ^1.0.0 test: ^1.16.0 - -dependency_overrides: - # Due to dependency cycle - build_runner: ^1.12.2 diff --git a/pkgs/code_builder/test/specs/extension_test.dart b/pkgs/code_builder/test/specs/extension_test.dart index fad908969..6c34ebea5 100644 --- a/pkgs/code_builder/test/specs/extension_test.dart +++ b/pkgs/code_builder/test/specs/extension_test.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/src/specs/extension.dart'; import 'package:test/test.dart'; import '../common.dart'; From d65fa7374de220bd09b72125105c8d5336cf5fc7 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 17 Jun 2021 10:15:15 -0700 Subject: [PATCH 182/271] Use latest Dart commands (dart-lang/code_builder#331) Co-authored-by: Nate Bosch --- pkgs/code_builder/.github/workflows/test-package.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 6207c3a9c..2dc0a515a 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -28,12 +28,12 @@ jobs: sdk: ${{ matrix.sdk }} - id: install name: Install dependencies - run: pub get + run: dart pub get - name: Check formatting - run: dartfmt --dry-run --set-exit-if-changed . + run: dart format --output=none --set-exit-if-changed . if: always() && steps.install.outcome == 'success' - name: Analyze code - run: dartanalyzer --fatal-infos --fatal-warnings . + run: dart analyze --fatal-infos . if: always() && steps.install.outcome == 'success' test: @@ -51,7 +51,7 @@ jobs: sdk: ${{ matrix.sdk }} - id: install name: Install dependencies - run: pub get + run: dart pub get - name: Run VM tests - run: pub run test --platform vm + run: dart test --platform vm if: always() && steps.install.outcome == 'success' From 373a4538cfd4e048d53788216a595bf428a5d767 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 24 Jun 2021 01:37:53 +0400 Subject: [PATCH 183/271] Add 'late' field modifier (dart-lang/code_builder#310) --- pkgs/code_builder/CHANGELOG.md | 4 ++- pkgs/code_builder/lib/src/emitter.dart | 3 ++ pkgs/code_builder/lib/src/specs/field.dart | 6 ++++ pkgs/code_builder/lib/src/specs/field.g.dart | 29 ++++++++++++++++++-- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/field_test.dart | 23 ++++++++++++++++ 6 files changed, 62 insertions(+), 5 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index e5edc9496..5dd8aaecc 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,6 @@ -## 4.0.1-dev +## 4.1.0-dev + +* Add support 'late' field modifier. ## 4.0.0 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index a3591449d..403f5494c 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -311,6 +311,9 @@ class DartEmitter extends Object if (spec.static) { output.write('static '); } + if (spec.late) { + output.write('late '); + } switch (spec.modifier) { case FieldModifier.var$: if (spec.type == null) { diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index 97168343a..9bdf01a1e 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -38,6 +38,9 @@ abstract class Field extends Object /// This is only valid within classes. bool get static; + /// Whether this field should be prefixed with `late`. + bool get late; + /// Name of the field. String get name; @@ -80,6 +83,9 @@ abstract class FieldBuilder extends Object /// This is only valid within classes. bool static = false; + /// Whether this field should be prefixed with `late`. + bool late = false; + /// Name of the field. String? name; diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 651a6a9fd..6d9049784 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -16,6 +16,8 @@ class _$Field extends Field { @override final bool static; @override + final bool late; + @override final String name; @override final Reference? type; @@ -30,6 +32,7 @@ class _$Field extends Field { required this.docs, this.assignment, required this.static, + required this.late, required this.name, this.type, required this.modifier}) @@ -37,6 +40,7 @@ class _$Field extends Field { BuiltValueNullFieldError.checkNotNull(annotations, 'Field', 'annotations'); BuiltValueNullFieldError.checkNotNull(docs, 'Field', 'docs'); BuiltValueNullFieldError.checkNotNull(static, 'Field', 'static'); + BuiltValueNullFieldError.checkNotNull(late, 'Field', 'late'); BuiltValueNullFieldError.checkNotNull(name, 'Field', 'name'); BuiltValueNullFieldError.checkNotNull(modifier, 'Field', 'modifier'); } @@ -56,6 +60,7 @@ class _$Field extends Field { docs == other.docs && assignment == other.assignment && static == other.static && + late == other.late && name == other.name && type == other.type && modifier == other.modifier; @@ -67,9 +72,11 @@ class _$Field extends Field { $jc( $jc( $jc( - $jc($jc($jc(0, annotations.hashCode), docs.hashCode), - assignment.hashCode), - static.hashCode), + $jc( + $jc($jc($jc(0, annotations.hashCode), docs.hashCode), + assignment.hashCode), + static.hashCode), + late.hashCode), name.hashCode), type.hashCode), modifier.hashCode)); @@ -82,6 +89,7 @@ class _$Field extends Field { ..add('docs', docs) ..add('assignment', assignment) ..add('static', static) + ..add('late', late) ..add('name', name) ..add('type', type) ..add('modifier', modifier)) @@ -140,6 +148,18 @@ class _$FieldBuilder extends FieldBuilder { super.static = static; } + @override + bool get late { + _$this; + return super.late; + } + + @override + set late(bool late) { + _$this; + super.late = late; + } + @override String? get name { _$this; @@ -185,6 +205,7 @@ class _$FieldBuilder extends FieldBuilder { super.docs = $v.docs.toBuilder(); super.assignment = $v.assignment; super.static = $v.static; + super.late = $v.late; super.name = $v.name; super.type = $v.type; super.modifier = $v.modifier; @@ -215,6 +236,8 @@ class _$FieldBuilder extends FieldBuilder { assignment: assignment, static: BuiltValueNullFieldError.checkNotNull( static, 'Field', 'static'), + late: + BuiltValueNullFieldError.checkNotNull(late, 'Field', 'late'), name: BuiltValueNullFieldError.checkNotNull(name, 'Field', 'name'), type: type, diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 0b1edf14c..76f5d4de9 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.0.1-dev +version: 4.1.0-dev description: >- A fluent, builder-based library for generating valid Dart code homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/field_test.dart b/pkgs/code_builder/test/specs/field_test.dart index 3a89d685c..54cdf0bfc 100644 --- a/pkgs/code_builder/test/specs/field_test.dart +++ b/pkgs/code_builder/test/specs/field_test.dart @@ -52,6 +52,29 @@ void main() { ); }); + test('should create a late field', () { + expect( + Field((b) => b + ..late = true + ..name = 'foo'), + equalsDart(r''' + late var foo; + '''), + ); + }); + + test('should create a static late field', () { + expect( + Field((b) => b + ..static = true + ..late = true + ..name = 'foo'), + equalsDart(r''' + static late var foo; + '''), + ); + }); + test('should create a field with an assignment', () { expect( Field((b) => b From e8827218d9246d877d03a94bdeee00c70d8e0fd1 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 23 Jun 2021 15:08:13 -0700 Subject: [PATCH 184/271] Fix scoped emitter example in README (dart-lang/code_builder#328) The current example of creating a scoped example is incorrect. This change fixes the example to use the correct constructor. --- pkgs/code_builder/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 89d973f37..f397042fe 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -55,7 +55,7 @@ void main() { ..name = 'doOther' ..returns = refer('Other', 'package:b/b.dart')), ])); - final emitter = DartEmitter(Allocator.simplePrefixing()); + final emitter = DartEmitter.scoped(); print(DartFormatter().format('${library.accept(emitter)}')); } ``` From 092d616482f11155a995d14f41a4f2e742a8dd13 Mon Sep 17 00:00:00 2001 From: Don Date: Wed, 23 Jun 2021 15:14:49 -0700 Subject: [PATCH 185/271] Introduce `Expression.spread` (dart-lang/code_builder#332) Add support for the spread operator `...` when using collections. --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/specs/expression.dart | 8 ++++++++ pkgs/code_builder/test/specs/code/expression_test.dart | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 5dd8aaecc..96e085d5a 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,6 @@ ## 4.1.0-dev +* Add `Expression.spread` for the spread operator `...`. * Add support 'late' field modifier. ## 4.0.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 947ddde1c..b40d20c12 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -284,6 +284,14 @@ abstract class Expression implements Spec { '', ); + /// This expression preceded by the spread operator `...`. + Expression get spread => BinaryExpression._( + const LiteralExpression._('...'), + this, + '', + addSpace: false, + ); + /// This expression preceded by `throw`. Expression get thrown => BinaryExpression._( const LiteralExpression._('throw'), diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index bda1b4267..91b4c4f89 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -466,6 +466,13 @@ void main() { ); }); + test('should emit spread', () { + expect( + refer('foo').spread, + equalsDart('...foo'), + ); + }); + test('should emit throw', () { expect( literalNull.thrown, From 1804d0b51f4dce09a54d4411c0a8576ae91275dc Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Thu, 24 Jun 2021 00:15:30 +0200 Subject: [PATCH 186/271] Add support for the postfix ! operator (dart-lang/code_builder#325) --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/specs/expression.dart | 11 +++++++++++ .../code_builder/test/specs/code/expression_test.dart | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 96e085d5a..d1ff1cdb4 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -2,6 +2,7 @@ * Add `Expression.spread` for the spread operator `...`. * Add support 'late' field modifier. +* Add support for `Expression.nullChecked` to add a null assertion operator. ## 4.0.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index b40d20c12..65e74d5a7 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -277,6 +277,17 @@ abstract class Expression implements Spec { addSpace: false, ); + /// Applies the null check operator on this expression, returning `this` `!`. + /// + /// Please note that this is only valid when emitting code with the null + /// safety syntax enabled. + Expression get nullChecked => BinaryExpression._( + this, + const LiteralExpression._('!'), + '', + addSpace: false, + ); + /// This expression preceded by `return`. Expression get returned => BinaryExpression._( const LiteralExpression._('return'), diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 91b4c4f89..8b06d3869 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -377,6 +377,10 @@ void main() { ); }); + test('should emit a null check', () { + expect(refer('foo').nullChecked, equalsDart('foo!')); + }); + test('should emit an if null index operator set', () { expect( refer('bar') From 4ec040054ab171b145a2efe801424d4aa12d8920 Mon Sep 17 00:00:00 2001 From: Don Date: Thu, 24 Jun 2021 11:46:08 -0700 Subject: [PATCH 187/271] Add support for creating `mixin`s (dart-lang/code_builder#334) --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/code_builder.dart | 1 + pkgs/code_builder/lib/src/emitter.dart | 35 +++ pkgs/code_builder/lib/src/specs/mixin.dart | 82 ++++++ pkgs/code_builder/lib/src/specs/mixin.g.dart | 271 +++++++++++++++++++ pkgs/code_builder/lib/src/visitors.dart | 3 + pkgs/code_builder/test/specs/mixin_test.dart | 139 ++++++++++ 7 files changed, 532 insertions(+) create mode 100644 pkgs/code_builder/lib/src/specs/mixin.dart create mode 100644 pkgs/code_builder/lib/src/specs/mixin.g.dart create mode 100644 pkgs/code_builder/test/specs/mixin_test.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index d1ff1cdb4..fa5bdb639 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -3,6 +3,7 @@ * Add `Expression.spread` for the spread operator `...`. * Add support 'late' field modifier. * Add support for `Expression.nullChecked` to add a null assertion operator. +* Add support for creating `mixin`s. ## 4.0.0 diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 60adee8d0..013cc5ddf 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -50,6 +50,7 @@ export 'src/specs/method.dart' MethodType, Parameter, ParameterBuilder; +export 'src/specs/mixin.dart' show Mixin, MixinBuilder; export 'src/specs/reference.dart' show refer, Reference; export 'src/specs/type_function.dart' show FunctionType, FunctionTypeBuilder; export 'src/specs/type_reference.dart' show TypeReference, TypeReferenceBuilder; diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 403f5494c..ca97f276e 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -14,6 +14,7 @@ import 'specs/extension.dart'; import 'specs/field.dart'; import 'specs/library.dart'; import 'specs/method.dart'; +import 'specs/mixin.dart'; import 'specs/reference.dart'; import 'specs/type_function.dart'; import 'specs/type_reference.dart'; @@ -150,6 +151,40 @@ class DartEmitter extends Object return out; } + @override + StringSink visitMixin(Mixin spec, [StringSink? output]) { + final out = output ??= StringBuffer(); + spec.docs.forEach(out.writeln); + spec.annotations.forEach((a) => visitAnnotation(a, out)); + + out.write('mixin ${spec.name}'); + visitTypeParameters(spec.types.map((r) => r.type), out); + if (spec.on != null) { + out.write(' on '); + spec.on!.type.accept(this, out); + } + if (spec.implements.isNotEmpty) { + out + ..write(' implements ') + ..writeAll( + spec.implements.map((m) => m.type.accept(this)), ','); + } + out.write(' {'); + spec.fields.forEach((f) { + visitField(f, out); + out.writeln(); + }); + spec.methods.forEach((m) { + visitMethod(m, out); + if (_isLambdaMethod(m)) { + out.write(';'); + } + out.writeln(); + }); + out.write(' }'); + return out; + } + @override StringSink visitConstructor(Constructor spec, String clazz, [StringSink? output]) { diff --git a/pkgs/code_builder/lib/src/specs/mixin.dart b/pkgs/code_builder/lib/src/specs/mixin.dart new file mode 100644 index 000000000..475f408b3 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/mixin.dart @@ -0,0 +1,82 @@ +// Copyright (c) 2021, 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:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../mixins/annotations.dart'; +import '../mixins/dartdoc.dart'; +import '../mixins/generics.dart'; +import '../visitors.dart'; +import 'expression.dart'; +import 'field.dart'; +import 'method.dart'; +import 'reference.dart'; + +part 'mixin.g.dart'; + +@immutable +abstract class Mixin extends Object + with HasAnnotations, HasDartDocs, HasGenerics + implements Built, Spec { + factory Mixin([void Function(MixinBuilder b) updates]) = _$Mixin; + + Mixin._(); + + @override + BuiltList get annotations; + + @override + BuiltList get docs; + + Reference? get on; + + BuiltList get implements; + + @override + BuiltList get types; + + BuiltList get methods; + BuiltList get fields; + + /// Name of the mixin. + String get name; + + @override + R accept( + SpecVisitor visitor, [ + R? context, + ]) => + visitor.visitMixin(this, context); +} + +abstract class MixinBuilder extends Object + with HasAnnotationsBuilder, HasDartDocsBuilder, HasGenericsBuilder + implements Builder { + factory MixinBuilder() = _$MixinBuilder; + + MixinBuilder._(); + + @override + ListBuilder annotations = ListBuilder(); + + @override + ListBuilder docs = ListBuilder(); + + Reference? on; + + ListBuilder implements = ListBuilder(); + + @override + ListBuilder types = ListBuilder(); + + ListBuilder methods = ListBuilder(); + + ListBuilder fields = ListBuilder(); + + /// Name of the mixin. + String? name; +} diff --git a/pkgs/code_builder/lib/src/specs/mixin.g.dart b/pkgs/code_builder/lib/src/specs/mixin.g.dart new file mode 100644 index 000000000..6147ee819 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/mixin.g.dart @@ -0,0 +1,271 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'mixin.dart'; + +// ************************************************************************** +// BuiltValueGenerator +// ************************************************************************** + +class _$Mixin extends Mixin { + @override + final BuiltList annotations; + @override + final BuiltList docs; + @override + final Reference? on; + @override + final BuiltList implements; + @override + final BuiltList types; + @override + final BuiltList methods; + @override + final BuiltList fields; + @override + final String name; + + factory _$Mixin([void Function(MixinBuilder)? updates]) => + (new MixinBuilder()..update(updates)).build() as _$Mixin; + + _$Mixin._( + {required this.annotations, + required this.docs, + this.on, + required this.implements, + required this.types, + required this.methods, + required this.fields, + required this.name}) + : super._() { + BuiltValueNullFieldError.checkNotNull(annotations, 'Mixin', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, 'Mixin', 'docs'); + BuiltValueNullFieldError.checkNotNull(implements, 'Mixin', 'implements'); + BuiltValueNullFieldError.checkNotNull(types, 'Mixin', 'types'); + BuiltValueNullFieldError.checkNotNull(methods, 'Mixin', 'methods'); + BuiltValueNullFieldError.checkNotNull(fields, 'Mixin', 'fields'); + BuiltValueNullFieldError.checkNotNull(name, 'Mixin', 'name'); + } + + @override + Mixin rebuild(void Function(MixinBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + _$MixinBuilder toBuilder() => new _$MixinBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Mixin && + annotations == other.annotations && + docs == other.docs && + on == other.on && + implements == other.implements && + types == other.types && + methods == other.methods && + fields == other.fields && + name == other.name; + } + + @override + int get hashCode { + return $jf($jc( + $jc( + $jc( + $jc( + $jc( + $jc($jc($jc(0, annotations.hashCode), docs.hashCode), + on.hashCode), + implements.hashCode), + types.hashCode), + methods.hashCode), + fields.hashCode), + name.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper('Mixin') + ..add('annotations', annotations) + ..add('docs', docs) + ..add('on', on) + ..add('implements', implements) + ..add('types', types) + ..add('methods', methods) + ..add('fields', fields) + ..add('name', name)) + .toString(); + } +} + +class _$MixinBuilder extends MixinBuilder { + _$Mixin? _$v; + + @override + ListBuilder get annotations { + _$this; + return super.annotations; + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs; + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + @override + Reference? get on { + _$this; + return super.on; + } + + @override + set on(Reference? on) { + _$this; + super.on = on; + } + + @override + ListBuilder get implements { + _$this; + return super.implements; + } + + @override + set implements(ListBuilder implements) { + _$this; + super.implements = implements; + } + + @override + ListBuilder get types { + _$this; + return super.types; + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + + @override + ListBuilder get methods { + _$this; + return super.methods; + } + + @override + set methods(ListBuilder methods) { + _$this; + super.methods = methods; + } + + @override + ListBuilder get fields { + _$this; + return super.fields; + } + + @override + set fields(ListBuilder fields) { + _$this; + super.fields = fields; + } + + @override + String? get name { + _$this; + return super.name; + } + + @override + set name(String? name) { + _$this; + super.name = name; + } + + _$MixinBuilder() : super._(); + + MixinBuilder get _$this { + final $v = _$v; + if ($v != null) { + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); + super.on = $v.on; + super.implements = $v.implements.toBuilder(); + super.types = $v.types.toBuilder(); + super.methods = $v.methods.toBuilder(); + super.fields = $v.fields.toBuilder(); + super.name = $v.name; + _$v = null; + } + return this; + } + + @override + void replace(Mixin other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$Mixin; + } + + @override + void update(void Function(MixinBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + _$Mixin build() { + _$Mixin _$result; + try { + _$result = _$v ?? + new _$Mixin._( + annotations: annotations.build(), + docs: docs.build(), + on: on, + implements: implements.build(), + types: types.build(), + methods: methods.build(), + fields: fields.build(), + name: + BuiltValueNullFieldError.checkNotNull(name, 'Mixin', 'name')); + } catch (_) { + late String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + + _$failedField = 'implements'; + implements.build(); + _$failedField = 'types'; + types.build(); + _$failedField = 'methods'; + methods.build(); + _$failedField = 'fields'; + fields.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + 'Mixin', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 64a4428a5..4d3ff3d04 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -14,6 +14,7 @@ import 'specs/extension.dart'; import 'specs/field.dart'; import 'specs/library.dart'; import 'specs/method.dart'; +import 'specs/mixin.dart'; import 'specs/reference.dart'; import 'specs/type_function.dart'; import 'specs/type_reference.dart'; @@ -26,6 +27,8 @@ abstract class SpecVisitor { T visitClass(Class spec, [T? context]); + T visitMixin(Mixin spec, [T? context]); + T visitExtension(Extension spec, [T? context]); T visitEnum(Enum spec, [T? context]); diff --git a/pkgs/code_builder/test/specs/mixin_test.dart b/pkgs/code_builder/test/specs/mixin_test.dart new file mode 100644 index 000000000..c03e75611 --- /dev/null +++ b/pkgs/code_builder/test/specs/mixin_test.dart @@ -0,0 +1,139 @@ +// Copyright (c) 2021, 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:test/test.dart'; + +import '../common.dart'; + +void main() { + useDartfmt(); + + test('should create a mixin', () { + expect( + Mixin((b) => b..name = 'Foo'), + equalsDart(r''' + mixin Foo {} + '''), + ); + }); + + test('should create a mixin with documentations', () { + expect( + Mixin( + (b) => b + ..name = 'Foo' + ..docs.addAll( + const [ + '/// My favorite mixin.', + ], + ), + ), + equalsDart(r''' + /// My favorite mixin. + mixin Foo {} + '''), + ); + }); + + test('should create a mixin with annotations', () { + expect( + Mixin( + (b) => b + ..name = 'Foo' + ..annotations.addAll([ + refer('deprecated'), + refer('Deprecated').call([literalString('This is an old mixin')]) + ]), + ), + equalsDart(r''' + @deprecated + @Deprecated('This is an old mixin') + mixin Foo {} + '''), + ); + }); + + test('should create a mixin with a generic type', () { + expect( + Mixin((b) => b + ..name = 'List' + ..types.add(refer('T'))), + equalsDart(r''' + mixin List {} + '''), + ); + }); + + test('should create a mixin with multiple generic types', () { + expect( + Mixin( + (b) => b + ..name = 'Map' + ..types.addAll([ + refer('K'), + refer('V'), + ]), + ), + equalsDart(r''' + mixin Map {} + '''), + ); + }); + + test('should create a mixin with a bound generic type', () { + expect( + Mixin((b) => b + ..name = 'Comparable' + ..types.add(TypeReference((b) => b + ..symbol = 'T' + ..bound = TypeReference((b) => b + ..symbol = 'Comparable' + ..types.add(refer('T').type))))), + equalsDart(r''' + mixin Comparable> {} + '''), + ); + }); + + test('should create a mixin on another mixin', () { + expect( + Mixin((b) => b + ..name = 'Foo' + ..on = TypeReference((b) => b.symbol = 'Bar')), + equalsDart(r''' + mixin Foo on Bar {} + '''), + ); + }); + + test('should create a mixin implementing another mixin', () { + expect( + Mixin((b) => b + ..name = 'Foo' + ..on = TypeReference((b) => b.symbol = 'Bar') + ..implements.add(TypeReference((b) => b.symbol = 'Foo'))), + equalsDart(r''' + mixin Foo on Bar implements Foo {} + '''), + ); + }); + + test('should create a mixin with a method', () { + expect( + Mixin((b) => b + ..name = 'Foo' + ..methods.add(Method((b) => b + ..name = 'foo' + ..body = const Code('return 1+ 2;')))), + equalsDart(r''' + mixin Foo { + foo() { + return 1 + 2; + } + } + '''), + ); + }); +} From a682cb760f37b20ea962ccce4dd082f4f641f39f Mon Sep 17 00:00:00 2001 From: Don Date: Thu, 24 Jun 2021 12:14:09 -0700 Subject: [PATCH 188/271] Introduce `Expression.nullSafeSpread` (dart-lang/code_builder#336) --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/specs/expression.dart | 8 ++++++++ pkgs/code_builder/test/specs/code/expression_test.dart | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index fa5bdb639..a5d8677df 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -4,6 +4,7 @@ * Add support 'late' field modifier. * Add support for `Expression.nullChecked` to add a null assertion operator. * Add support for creating `mixin`s. +* Add `Expression.nullSafeSpread` for the null aware spread operator `...?`. ## 4.0.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 65e74d5a7..8ee2bdfce 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -303,6 +303,14 @@ abstract class Expression implements Spec { addSpace: false, ); + /// This expression precenede by the null safe spread operator `?...`. + Expression get nullSafeSpread => BinaryExpression._( + const LiteralExpression._('...?'), + this, + '', + addSpace: false, + ); + /// This expression preceded by `throw`. Expression get thrown => BinaryExpression._( const LiteralExpression._('throw'), diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 8b06d3869..d19d9a38b 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -477,6 +477,13 @@ void main() { ); }); + test('should emit null safe spread', () { + expect( + refer('foo').nullSafeSpread, + equalsDart('...?foo'), + ); + }); + test('should emit throw', () { expect( literalNull.thrown, From d67b1ce6995e0ba46ba5a45c874bdf64cd443a80 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 14 Jul 2021 11:27:35 -0700 Subject: [PATCH 189/271] Dart format with latest SDK (dart-lang/code_builder#338) --- pkgs/code_builder/lib/src/emitter.dart | 16 ++++++++++++---- pkgs/code_builder/lib/src/specs/expression.dart | 8 ++++++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index ca97f276e..bf155a459 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -202,7 +202,9 @@ class DartEmitter extends Object } output.write(clazz); if (spec.name != null) { - output..write('.')..write(spec.name); + output + ..write('.') + ..write(spec.name); } output.write('('); if (spec.requiredParameters.isNotEmpty) { @@ -401,7 +403,9 @@ class DartEmitter extends Object // Note: dartfmt handles creating new lines between directives. // 2 lines are written here. The first one comes after the previous // directive `;`, the second is the empty line. - output..writeln()..writeln(); + output + ..writeln() + ..writeln(); } directive.accept(this, output); previous = directive; @@ -444,7 +448,9 @@ class DartEmitter extends Object out.write('{'); visitAll(spec.namedParameters.keys, out, (name) { spec.namedParameters[name]!.accept(this, out); - out..write(' ')..write(name); + out + ..write(' ') + ..write(name); }); out.write('}'); } @@ -471,7 +477,9 @@ class DartEmitter extends Object output.write(' '); } if (spec.type == MethodType.getter) { - output..write('get ')..write(spec.name); + output + ..write('get ') + ..write(spec.name); } else { if (spec.type == MethodType.setter) { output.write('set '); diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 8ee2bdfce..95b28461d 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -418,7 +418,9 @@ abstract class ExpressionEmitter implements ExpressionVisitor { out, expression.type == InvokeExpressionType.constInstance, () { expression.target.accept(this, out); if (expression.name != null) { - out..write('.')..write(expression.name); + out + ..write('.') + ..write(expression.name); } if (expression.typeArguments.isNotEmpty) { out.write('<'); @@ -436,7 +438,9 @@ abstract class ExpressionEmitter implements ExpressionVisitor { out.write(', '); } visitAll(expression.namedArguments.keys, out, (name) { - out..write(name)..write(': '); + out + ..write(name) + ..write(': '); expression.namedArguments[name]!.accept(this, out); }); return out..write(')'); From 75748e9a41c26f8c75a2c928fc3b1230b9d95bd3 Mon Sep 17 00:00:00 2001 From: Don Date: Tue, 20 Jul 2021 10:42:17 -0700 Subject: [PATCH 190/271] Add annotations to libraries (dart-lang/code_builder#335) --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/emitter.dart | 7 +++ pkgs/code_builder/lib/src/specs/library.dart | 23 ++++++- .../code_builder/lib/src/specs/library.g.dart | 60 +++++++++++++++++-- .../code_builder/test/specs/library_test.dart | 31 ++++++++++ 5 files changed, 115 insertions(+), 7 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index a5d8677df..cd378e7e3 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -5,6 +5,7 @@ * Add support for `Expression.nullChecked` to add a null assertion operator. * Add support for creating `mixin`s. * Add `Expression.nullSafeSpread` for the null aware spread operator `...?`. +* A `Library` can now be annotated. ## 4.0.0 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index bf155a459..96f9825ca 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -391,6 +391,13 @@ class DartEmitter extends Object } } + if (spec.name != null) { + spec.annotations.forEach((a) => visitAnnotation(a, output)); + output.write('library ${spec.name!};'); + } else if (spec.annotations.isNotEmpty) { + throw StateError('a library name is required for annotations'); + } + final directives = [...allocator.imports, ...spec.directives]; if (orderDirectives) { diff --git a/pkgs/code_builder/lib/src/specs/library.dart b/pkgs/code_builder/lib/src/specs/library.dart index d4ee59761..c007c49d4 100644 --- a/pkgs/code_builder/lib/src/specs/library.dart +++ b/pkgs/code_builder/lib/src/specs/library.dart @@ -7,19 +7,31 @@ import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; import '../base.dart'; +import '../mixins/annotations.dart'; import '../visitors.dart'; import 'directive.dart'; +import 'expression.dart'; part 'library.g.dart'; @immutable -abstract class Library implements Built, Spec { +abstract class Library + with HasAnnotations + implements Built, Spec { factory Library([void Function(LibraryBuilder) updates]) = _$Library; Library._(); + @override + BuiltList get annotations; + BuiltList get directives; BuiltList get body; + /// Name of the library. + /// + /// May be `null` when no [annotations] are specified. + String? get name; + @override R accept( SpecVisitor visitor, [ @@ -28,10 +40,17 @@ abstract class Library implements Built, Spec { visitor.visitLibrary(this, context); } -abstract class LibraryBuilder implements Builder { +abstract class LibraryBuilder + with HasAnnotationsBuilder + implements Builder { factory LibraryBuilder() = _$LibraryBuilder; LibraryBuilder._(); + @override + ListBuilder annotations = ListBuilder(); + ListBuilder body = ListBuilder(); ListBuilder directives = ListBuilder(); + + String? name; } diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index b9178ec5c..298779d9f 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -7,15 +7,26 @@ part of 'library.dart'; // ************************************************************************** class _$Library extends Library { + @override + final BuiltList annotations; @override final BuiltList directives; @override final BuiltList body; + @override + final String? name; factory _$Library([void Function(LibraryBuilder)? updates]) => (new LibraryBuilder()..update(updates)).build() as _$Library; - _$Library._({required this.directives, required this.body}) : super._() { + _$Library._( + {required this.annotations, + required this.directives, + required this.body, + this.name}) + : super._() { + BuiltValueNullFieldError.checkNotNull( + annotations, 'Library', 'annotations'); BuiltValueNullFieldError.checkNotNull(directives, 'Library', 'directives'); BuiltValueNullFieldError.checkNotNull(body, 'Library', 'body'); } @@ -31,20 +42,27 @@ class _$Library extends Library { bool operator ==(Object other) { if (identical(other, this)) return true; return other is Library && + annotations == other.annotations && directives == other.directives && - body == other.body; + body == other.body && + name == other.name; } @override int get hashCode { - return $jf($jc($jc(0, directives.hashCode), body.hashCode)); + return $jf($jc( + $jc($jc($jc(0, annotations.hashCode), directives.hashCode), + body.hashCode), + name.hashCode)); } @override String toString() { return (newBuiltValueToStringHelper('Library') + ..add('annotations', annotations) ..add('directives', directives) - ..add('body', body)) + ..add('body', body) + ..add('name', name)) .toString(); } } @@ -52,6 +70,18 @@ class _$Library extends Library { class _$LibraryBuilder extends LibraryBuilder { _$Library? _$v; + @override + ListBuilder get annotations { + _$this; + return super.annotations; + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + @override ListBuilder get directives { _$this; @@ -76,13 +106,27 @@ class _$LibraryBuilder extends LibraryBuilder { super.body = body; } + @override + String? get name { + _$this; + return super.name; + } + + @override + set name(String? name) { + _$this; + super.name = name; + } + _$LibraryBuilder() : super._(); LibraryBuilder get _$this { final $v = _$v; if ($v != null) { + super.annotations = $v.annotations.toBuilder(); super.directives = $v.directives.toBuilder(); super.body = $v.body.toBuilder(); + super.name = $v.name; _$v = null; } return this; @@ -104,10 +148,16 @@ class _$LibraryBuilder extends LibraryBuilder { _$Library _$result; try { _$result = _$v ?? - new _$Library._(directives: directives.build(), body: body.build()); + new _$Library._( + annotations: annotations.build(), + directives: directives.build(), + body: body.build(), + name: name); } catch (_) { late String _$failedField; try { + _$failedField = 'annotations'; + annotations.build(); _$failedField = 'directives'; directives.build(); _$failedField = 'body'; diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index 63b080749..e7391a91d 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -137,5 +137,36 @@ void main() { ''', DartEmitter()), ); }); + + test('should emit a source file with annotations', () { + expect( + Library( + (b) => b + ..name = 'js_interop' + ..annotations.add( + refer('JS', 'package:js/js.dart').call([]), + ), + ), + equalsDart(r''' + @JS() + library js_interop; + import 'package:js/js.dart'; + ''', DartEmitter(allocator: Allocator())), + ); + }); + + test('should error on unnamed library with annotations', () { + expect( + () { + Library( + (b) => b + ..annotations.add( + refer('JS', 'package:js/js.dart').call([]), + ), + ).accept(DartEmitter()); + }, + throwsStateError, + ); + }); }); } From f61034e6801b37cc11495d478378fc9bbb6bbf11 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 20 Jul 2021 13:01:05 -0700 Subject: [PATCH 191/271] Prepare to publish (dart-lang/code_builder#339) --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index cd378e7e3..bbdbad118 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 4.1.0-dev +## 4.1.0 * Add `Expression.spread` for the spread operator `...`. * Add support 'late' field modifier. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 76f5d4de9..20282b16b 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.1.0-dev +version: 4.1.0 description: >- A fluent, builder-based library for generating valid Dart code homepage: https://github.com/dart-lang/code_builder From c9d7d239897ec9d17cfce790ea6bf4cdb4b531b7 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 14 Oct 2021 07:25:20 -0700 Subject: [PATCH 192/271] Move to pkg:lints (dart-lang/code_builder#344) --- pkgs/code_builder/CHANGELOG.md | 2 + pkgs/code_builder/analysis_options.yaml | 2 +- pkgs/code_builder/lib/src/emitter.dart | 72 ++++++++++++++++--------- pkgs/code_builder/pubspec.yaml | 4 +- 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index bbdbad118..2e1abde98 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,5 @@ +## 4.1.1-dev + ## 4.1.0 * Add `Expression.spread` for the spread operator `...`. diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml index cceb9b380..388cd8776 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml analyzer: strong-mode: diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 96f9825ca..1c68605b5 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -109,7 +109,9 @@ class DartEmitter extends Object StringSink visitClass(Class spec, [StringSink? output]) { final out = output ??= StringBuffer(); spec.docs.forEach(out.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, out)); + for (var a in spec.annotations) { + visitAnnotation(a, out); + } if (spec.abstract) { out.write('abstract '); } @@ -132,21 +134,21 @@ class DartEmitter extends Object spec.implements.map((m) => m.type.accept(this)), ','); } out.write(' {'); - spec.constructors.forEach((c) { + for (var c in spec.constructors) { visitConstructor(c, spec.name, out); out.writeln(); - }); - spec.fields.forEach((f) { + } + for (var f in spec.fields) { visitField(f, out); out.writeln(); - }); - spec.methods.forEach((m) { + } + for (var m in spec.methods) { visitMethod(m, out); if (_isLambdaMethod(m)) { out.write(';'); } out.writeln(); - }); + } out.writeln(' }'); return out; } @@ -155,7 +157,9 @@ class DartEmitter extends Object StringSink visitMixin(Mixin spec, [StringSink? output]) { final out = output ??= StringBuffer(); spec.docs.forEach(out.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, out)); + for (var a in spec.annotations) { + visitAnnotation(a, out); + } out.write('mixin ${spec.name}'); visitTypeParameters(spec.types.map((r) => r.type), out); @@ -170,17 +174,17 @@ class DartEmitter extends Object spec.implements.map((m) => m.type.accept(this)), ','); } out.write(' {'); - spec.fields.forEach((f) { + for (var f in spec.fields) { visitField(f, out); out.writeln(); - }); - spec.methods.forEach((m) { + } + for (var m in spec.methods) { visitMethod(m, out); if (_isLambdaMethod(m)) { out.write(';'); } out.writeln(); - }); + } out.write(' }'); return out; } @@ -190,7 +194,9 @@ class DartEmitter extends Object [StringSink? output]) { output ??= StringBuffer(); spec.docs.forEach(output.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, output)); + for (var a in spec.annotations) { + visitAnnotation(a, output); + } if (spec.external) { output.write('external '); } @@ -276,7 +282,9 @@ class DartEmitter extends Object StringSink visitExtension(Extension spec, [StringSink? output]) { final out = output ??= StringBuffer(); spec.docs.forEach(out.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, out)); + for (var a in spec.annotations) { + visitAnnotation(a, out); + } out.write('extension'); if (spec.name != null) { @@ -288,17 +296,17 @@ class DartEmitter extends Object spec.on!.type.accept(this, out); } out.write(' {'); - spec.fields.forEach((f) { + for (var f in spec.fields) { visitField(f, out); out.writeln(); - }); - spec.methods.forEach((m) { + } + for (var m in spec.methods) { visitMethod(m, out); if (_isLambdaMethod(m)) { out.write(';'); } out.writeln(); - }); + } out.writeln(' }'); return out; } @@ -344,7 +352,9 @@ class DartEmitter extends Object StringSink visitField(Field spec, [StringSink? output]) { output ??= StringBuffer(); spec.docs.forEach(output.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, output)); + for (var a in spec.annotations) { + visitAnnotation(a, output); + } if (spec.static) { output.write('static '); } @@ -392,7 +402,9 @@ class DartEmitter extends Object } if (spec.name != null) { - spec.annotations.forEach((a) => visitAnnotation(a, output)); + for (var a in spec.annotations) { + visitAnnotation(a, output); + } output.write('library ${spec.name!};'); } else if (spec.annotations.isNotEmpty) { throw StateError('a library name is required for annotations'); @@ -472,7 +484,9 @@ class DartEmitter extends Object StringSink visitMethod(Method spec, [StringSink? output]) { output ??= StringBuffer(); spec.docs.forEach(output.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, output)); + for (var a in spec.annotations) { + visitAnnotation(a, output); + } if (spec.external) { output.write('external '); } @@ -567,7 +581,9 @@ class DartEmitter extends Object bool named = false, }) { spec.docs.forEach(output.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, output)); + for (var a in spec.annotations) { + visitAnnotation(a, output); + } // The `required` keyword must precede the `covariant` keyword. if (spec.required) { output.write('required '); @@ -630,16 +646,20 @@ class DartEmitter extends Object StringSink visitEnum(Enum spec, [StringSink? output]) { final out = output ??= StringBuffer(); spec.docs.forEach(out.writeln); - spec.annotations.forEach((a) => visitAnnotation(a, out)); + for (var a in spec.annotations) { + visitAnnotation(a, out); + } out.writeln('enum ${spec.name} {'); - spec.values.forEach((v) { + for (var v in spec.values) { v.docs.forEach(out.writeln); - v.annotations.forEach((a) => visitAnnotation(a, out)); + for (var a in v.annotations) { + visitAnnotation(a, out); + } out.write(v.name); if (v != spec.values.last) { out.writeln(','); } - }); + } out.writeln('}'); return out; } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 20282b16b..c4c751f9a 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.1.0 +version: 4.1.1-dev description: >- A fluent, builder-based library for generating valid Dart code homepage: https://github.com/dart-lang/code_builder @@ -19,6 +19,6 @@ dev_dependencies: build_runner: ^2.0.3 built_value_generator: ^8.0.0 dart_style: ^2.0.0 - pedantic: ^1.10.0 + lints: ^1.0.0 source_gen: ^1.0.0 test: ^1.16.0 From 8f8b6b604000d46c109b895380da3bd4f2bc741e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 24 Jan 2022 13:00:53 -0800 Subject: [PATCH 193/271] Remove unused ctor arg (dart-lang/code_builder#350) --- pkgs/code_builder/lib/src/specs/expression/invoke.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index 448ce3e39..6d24e4099 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -22,8 +22,8 @@ class InvokeExpression extends Expression { this.positionalArguments, [ this.namedArguments = const {}, this.typeArguments = const [], - this.name, - ]) : type = null; + ]) : name = null, + type = null; const InvokeExpression.newOf( this.target, From 22c8973aa98b1322d8d73945e13b176319b67ed2 Mon Sep 17 00:00:00 2001 From: Eli Cohn <36641584+ejcohn@users.noreply.github.com> Date: Thu, 27 Jan 2022 12:49:09 -0500 Subject: [PATCH 194/271] Update README (dart-lang/code_builder#351) Make example code consistent with output. --- pkgs/code_builder/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index f397042fe..0114b1fe8 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -22,7 +22,7 @@ void main() { ..extend = refer('Organism') ..methods.add(Method.returnsVoid((b) => b ..name = 'eat' - ..body = const Code("print('Yum');")))); + ..body = const Code("print('Yum!');")))); final emitter = DartEmitter(); print(DartFormatter().format('${animal.accept(emitter)}')); } From 0986a89637d9af3a1eba8c9b672eea6b5785d3e3 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 31 Mar 2022 12:17:39 -0700 Subject: [PATCH 195/271] Fix built_value code generation (dart-lang/code_builder#354) Remove the `build.disabled.yaml` and `build.dart` files. Update the instructions to run from a snapshot manually instead of running through `build_runner`. Regenerating files with the latest `built_value`. --- pkgs/code_builder/README.md | 15 ++++++++------- pkgs/code_builder/build.disabled.yaml | 14 -------------- pkgs/code_builder/lib/src/specs/class.g.dart | 2 +- pkgs/code_builder/lib/src/specs/code.g.dart | 2 +- .../code_builder/lib/src/specs/constructor.g.dart | 2 +- pkgs/code_builder/lib/src/specs/directive.g.dart | 2 +- pkgs/code_builder/lib/src/specs/enum.g.dart | 2 +- pkgs/code_builder/lib/src/specs/extension.g.dart | 2 +- pkgs/code_builder/lib/src/specs/field.g.dart | 2 +- pkgs/code_builder/lib/src/specs/library.g.dart | 2 +- pkgs/code_builder/lib/src/specs/method.g.dart | 2 +- pkgs/code_builder/lib/src/specs/mixin.g.dart | 2 +- .../lib/src/specs/type_function.g.dart | 2 +- .../lib/src/specs/type_reference.g.dart | 2 +- pkgs/code_builder/tool/src/builder.dart | 14 -------------- 15 files changed, 20 insertions(+), 47 deletions(-) delete mode 100644 pkgs/code_builder/build.disabled.yaml delete mode 100644 pkgs/code_builder/tool/src/builder.dart diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 0114b1fe8..98a217745 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -94,16 +94,17 @@ will be on a best-effort basis. ### Updating generated (`.g.dart`) files > **NOTE**: There is currently a limitation in `build_runner` that requires a -> workaround for developing this package. We expect this to be unnecessary in -> the future. +> workaround for developing this package since it is a dependency of the build +> system. -Use [`build_runner`][build_runner]: +Make a snapshot of the generated [`build_runner`][build_runner] build script and +run from the snapshot instead of source to avoid problems with deleted files. +These steps must be run without deleting the source files. ```bash -$ pub global activate build_runner -$ mv build.disabled.yaml build.yaml -$ pub global run build_runner build --delete-conflicting-outputs -$ mv build.yaml build.disabled.yaml +$ dart run build_runner generate-build-script +$ dart compile kernel .dart_tool/build/entrypoint/build.dart +$ dart .dart_tool/build/entrypoint/build.dill build --delete_conflicting-outputs ``` [build_runner]: https://pub.dev/packages/build_runner diff --git a/pkgs/code_builder/build.disabled.yaml b/pkgs/code_builder/build.disabled.yaml deleted file mode 100644 index 31e5817d0..000000000 --- a/pkgs/code_builder/build.disabled.yaml +++ /dev/null @@ -1,14 +0,0 @@ -targets: - $default: - builders: - "|_built_value": - -builders: - _built_value: - target: ":code_builder" - import: "tool/src/builder.dart" - builder_factories: - - "builtValueBuilder" - build_extensions: - ".dart": [".g.dart"] - build_to: "source" diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index f007824d8..589ecd924 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -342,4 +342,4 @@ class _$ClassBuilder extends ClassBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart index db4911918..0f238df34 100644 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -100,4 +100,4 @@ class _$BlockBuilder extends BlockBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index 5a6c4d733..12ba8b0fd 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -358,4 +358,4 @@ class _$ConstructorBuilder extends ConstructorBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart index 500f5cda2..fde564c51 100644 --- a/pkgs/code_builder/lib/src/specs/directive.g.dart +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -201,4 +201,4 @@ class _$DirectiveBuilder extends DirectiveBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/enum.g.dart b/pkgs/code_builder/lib/src/specs/enum.g.dart index 4e82863e9..b87e1c48c 100644 --- a/pkgs/code_builder/lib/src/specs/enum.g.dart +++ b/pkgs/code_builder/lib/src/specs/enum.g.dart @@ -315,4 +315,4 @@ class _$EnumValueBuilder extends EnumValueBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/extension.g.dart b/pkgs/code_builder/lib/src/specs/extension.g.dart index 75ed39759..cf90d889d 100644 --- a/pkgs/code_builder/lib/src/specs/extension.g.dart +++ b/pkgs/code_builder/lib/src/specs/extension.g.dart @@ -243,4 +243,4 @@ class _$ExtensionBuilder extends ExtensionBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 6d9049784..9c89724aa 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -261,4 +261,4 @@ class _$FieldBuilder extends FieldBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index 298779d9f..9cbf72040 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -173,4 +173,4 @@ class _$LibraryBuilder extends LibraryBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index c44d5f96f..2e2144984 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -682,4 +682,4 @@ class _$ParameterBuilder extends ParameterBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/mixin.g.dart b/pkgs/code_builder/lib/src/specs/mixin.g.dart index 6147ee819..280208754 100644 --- a/pkgs/code_builder/lib/src/specs/mixin.g.dart +++ b/pkgs/code_builder/lib/src/specs/mixin.g.dart @@ -268,4 +268,4 @@ class _$MixinBuilder extends MixinBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart index c84f537a5..3f1fa26f1 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -221,4 +221,4 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index e62cbdc7a..27d98da95 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -188,4 +188,4 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new diff --git a/pkgs/code_builder/tool/src/builder.dart b/pkgs/code_builder/tool/src/builder.dart deleted file mode 100644 index 4934282ef..000000000 --- a/pkgs/code_builder/tool/src/builder.dart +++ /dev/null @@ -1,14 +0,0 @@ -// 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. -// -// @dart=2.9 - -import 'package:build/build.dart'; -import 'package:built_value_generator/built_value_generator.dart'; -import 'package:source_gen/source_gen.dart'; - -/// Returns a [Builder] to generate `.g.dart` files for `built_value`. -Builder builtValueBuilder(BuilderOptions _) => PartBuilder([ - const BuiltValueGenerator(), - ], '.g.dart'); From 94aaa2959c6e621044b35565c3977158506c383c Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 31 Mar 2022 13:51:50 -0700 Subject: [PATCH 196/271] Add a namedRequiredParameters field to FunctionType (dart-lang/code_builder#353) Co-authored-by: Nate Bosch --- pkgs/code_builder/lib/src/emitter.dart | 18 ++++++++-- .../lib/src/specs/type_function.dart | 12 +++++-- .../lib/src/specs/type_function.g.dart | 34 ++++++++++++++++--- .../test/specs/code/expression_test.dart | 26 ++++++++++++++ pkgs/code_builder/test/specs/method_test.dart | 25 ++++++++++++++ 5 files changed, 105 insertions(+), 10 deletions(-) diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 1c68605b5..0d2ad8004 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -452,9 +452,10 @@ class DartEmitter extends Object visitAll(spec.requiredParameters, out, (spec) { spec.accept(this, out); }); + final hasNamedParameters = spec.namedRequiredParameters.isNotEmpty || + spec.namedParameters.isNotEmpty; if (spec.requiredParameters.isNotEmpty && - (spec.optionalParameters.isNotEmpty || - spec.namedParameters.isNotEmpty)) { + (spec.optionalParameters.isNotEmpty || hasNamedParameters)) { out.write(', '); } if (spec.optionalParameters.isNotEmpty) { @@ -463,8 +464,19 @@ class DartEmitter extends Object spec.accept(this, out); }); out.write(']'); - } else if (spec.namedParameters.isNotEmpty) { + } else if (hasNamedParameters) { out.write('{'); + visitAll(spec.namedRequiredParameters.keys, out, (name) { + out.write('required '); + spec.namedRequiredParameters[name]!.accept(this, out); + out + ..write(' ') + ..write(name); + }); + if (spec.namedRequiredParameters.isNotEmpty && + spec.namedParameters.isNotEmpty) { + out.write(', '); + } visitAll(spec.namedParameters.keys, out, (name) { spec.namedParameters[name]!.accept(this, out); out diff --git a/pkgs/code_builder/lib/src/specs/type_function.dart b/pkgs/code_builder/lib/src/specs/type_function.dart index a1dfeadad..be7c3eacc 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.dart @@ -38,15 +38,18 @@ abstract class FunctionType extends Expression @override BuiltList get types; - /// Required positional arguments to this function type. + /// Required positional parameters of this function type. BuiltList get requiredParameters; - /// Optional positional arguments to this function type. + /// Optional positional parameters of this function type. BuiltList get optionalParameters; - /// Named optional arguments to this function type. + /// Named optional parameters of this function type. BuiltMap get namedParameters; + /// Named required parameters of this function type. + BuiltMap get namedRequiredParameters; + @override String? get url => null; @@ -119,6 +122,9 @@ abstract class FunctionTypeBuilder extends Object MapBuilder namedParameters = MapBuilder(); + MapBuilder namedRequiredParameters = + MapBuilder(); + bool? isNullable; String? url; diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart index 3f1fa26f1..5778c4b11 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -18,6 +18,8 @@ class _$FunctionType extends FunctionType { @override final BuiltMap namedParameters; @override + final BuiltMap namedRequiredParameters; + @override final bool? isNullable; factory _$FunctionType([void Function(FunctionTypeBuilder)? updates]) => @@ -29,6 +31,7 @@ class _$FunctionType extends FunctionType { required this.requiredParameters, required this.optionalParameters, required this.namedParameters, + required this.namedRequiredParameters, this.isNullable}) : super._() { BuiltValueNullFieldError.checkNotNull(types, 'FunctionType', 'types'); @@ -38,6 +41,8 @@ class _$FunctionType extends FunctionType { optionalParameters, 'FunctionType', 'optionalParameters'); BuiltValueNullFieldError.checkNotNull( namedParameters, 'FunctionType', 'namedParameters'); + BuiltValueNullFieldError.checkNotNull( + namedRequiredParameters, 'FunctionType', 'namedRequiredParameters'); } @override @@ -57,6 +62,7 @@ class _$FunctionType extends FunctionType { requiredParameters == other.requiredParameters && optionalParameters == other.optionalParameters && namedParameters == other.namedParameters && + namedRequiredParameters == other.namedRequiredParameters && isNullable == other.isNullable; } @@ -65,10 +71,12 @@ class _$FunctionType extends FunctionType { return $jf($jc( $jc( $jc( - $jc($jc($jc(0, returnType.hashCode), types.hashCode), - requiredParameters.hashCode), - optionalParameters.hashCode), - namedParameters.hashCode), + $jc( + $jc($jc($jc(0, returnType.hashCode), types.hashCode), + requiredParameters.hashCode), + optionalParameters.hashCode), + namedParameters.hashCode), + namedRequiredParameters.hashCode), isNullable.hashCode)); } @@ -80,6 +88,7 @@ class _$FunctionType extends FunctionType { ..add('requiredParameters', requiredParameters) ..add('optionalParameters', optionalParameters) ..add('namedParameters', namedParameters) + ..add('namedRequiredParameters', namedRequiredParameters) ..add('isNullable', isNullable)) .toString(); } @@ -148,6 +157,19 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { super.namedParameters = namedParameters; } + @override + MapBuilder get namedRequiredParameters { + _$this; + return super.namedRequiredParameters; + } + + @override + set namedRequiredParameters( + MapBuilder namedRequiredParameters) { + _$this; + super.namedRequiredParameters = namedRequiredParameters; + } + @override bool? get isNullable { _$this; @@ -170,6 +192,7 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { super.requiredParameters = $v.requiredParameters.toBuilder(); super.optionalParameters = $v.optionalParameters.toBuilder(); super.namedParameters = $v.namedParameters.toBuilder(); + super.namedRequiredParameters = $v.namedRequiredParameters.toBuilder(); super.isNullable = $v.isNullable; _$v = null; } @@ -198,6 +221,7 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { requiredParameters: requiredParameters.build(), optionalParameters: optionalParameters.build(), namedParameters: namedParameters.build(), + namedRequiredParameters: namedRequiredParameters.build(), isNullable: isNullable); } catch (_) { late String _$failedField; @@ -210,6 +234,8 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { optionalParameters.build(); _$failedField = 'namedParameters'; namedParameters.build(); + _$failedField = 'namedRequiredParameters'; + namedRequiredParameters.build(); } catch (e) { throw new BuiltValueNestedFieldError( 'FunctionType', _$failedField, e.toString()); diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index d19d9a38b..8519124cb 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -302,6 +302,32 @@ void main() { ); }); + test( + 'should emit a function type with named required and optional parameters', + () { + expect( + FunctionType((b) => b + ..namedRequiredParameters.addAll({ + 'x': refer('int'), + }) + ..namedParameters.addAll({ + 'y': refer('int'), + })), + equalsDart('Function({required int x, int y})'), + ); + }); + + test('should emit a function type with named required parameters', () { + expect( + FunctionType((b) => b + ..namedRequiredParameters.addAll({ + 'x': refer('int'), + 'y': refer('int'), + })), + equalsDart('Function({required int x, required int y})'), + ); + }); + test('should emit a nullable function type in a Null Safety library', () { final emitter = DartEmitter.scoped(useNullSafetySyntax: true); expect( diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index caa29e2e8..f1d4ef724 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -212,6 +212,31 @@ void main() { ); }); + test('should create a function type with a required named parameter', () { + expect( + FunctionType((b) => b + ..returnType = refer('String') + ..namedRequiredParameters['named'] = refer('int')), + equalsDart(r''' + String Function({required int named}) + '''), + ); + }); + + test( + 'should create a function type with a required named and an optional ' + 'named parameter', () { + expect( + FunctionType((b) => b + ..returnType = refer('String') + ..namedRequiredParameters['named'] = refer('int') + ..namedParameters['optional'] = refer('int')), + equalsDart(r''' + String Function({required int named, int optional}) + '''), + ); + }); + test('should create a method with a nested function type return type', () { expect( Method((b) => b From 02c878945ee75b541b73c270acc8716560fb4027 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 5 Apr 2022 14:46:42 -0700 Subject: [PATCH 197/271] Ignore lint about private import prefixes (dart-lang/code_builder#352) In generated code is is more important to avoid potential name conflicts, even unlikely ones, than to satisfy style lints since the code is rarely seen. Ignore `no_leading_underscores_for_library_prefixes` since this lint is in the recommended set in `package:lints`. --- pkgs/code_builder/CHANGELOG.md | 7 ++++++- pkgs/code_builder/lib/src/emitter.dart | 4 ++++ pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/directive_test.dart | 2 ++ pkgs/code_builder/test/specs/library_test.dart | 1 + 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 2e1abde98..9350a7548 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,9 @@ -## 4.1.1-dev +## 4.2.0-dev + +* Add an ignore for a lint from the `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 which is already not visible + outside the library is confusing. ## 4.1.0 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 0d2ad8004..0fa7410d5 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -417,6 +417,10 @@ 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'); + } for (final directive in directives) { if (_newLineBetween(orderDirectives, previous, directive)) { // Note: dartfmt handles creating new lines between directives. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index c4c751f9a..f1c55b06d 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.1.1-dev +version: 4.2.0-dev description: >- A fluent, builder-based library for generating valid Dart code homepage: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/directive_test.dart b/pkgs/code_builder/test/directive_test.dart index d99922267..11b862373 100644 --- a/pkgs/code_builder/test/directive_test.dart +++ b/pkgs/code_builder/test/directive_test.dart @@ -38,6 +38,7 @@ void main() { expect( library, equalsDart(r''' + // ignore_for_file: no_leading_underscores_for_library_prefixes import '../relative.dart' as _i1; import 'package:foo/foo.dart' as _i2; import 'package:foo/bar.dart' as _i3; @@ -57,6 +58,7 @@ void main() { expect( library, equalsDart(r''' + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:collection' as _i4; import 'package:foo/bar.dart' as _i3; diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index e7391a91d..dd74a158c 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -103,6 +103,7 @@ void main() { ..modifier = FieldModifier.final$ ..assignment = Code.scope((a) => '${a($LinkedHashMap)}()')))), equalsDart(r''' + // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:collection' as _i1; final test = _i1.LinkedHashMap(); From 7cba9ec091df56d7f534552ae1543f0e7931da18 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 18 Apr 2022 16:24:33 -0700 Subject: [PATCH 198/271] Update pubspec.yaml (dart-lang/code_builder#356) --- pkgs/code_builder/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index f1c55b06d..494dcc586 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -2,7 +2,7 @@ name: code_builder version: 4.2.0-dev description: >- A fluent, builder-based library for generating valid Dart code -homepage: https://github.com/dart-lang/code_builder +repository: https://github.com/dart-lang/code_builder environment: sdk: '>=2.12.0 <3.0.0' From 8c543d83e8c76b932e77dd62c42261cb14534ebf Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 27 Apr 2022 14:38:12 -0700 Subject: [PATCH 199/271] Fix docs for Expression.assign, assignNullAware, and ifNullThen (dart-lang/code_builder#357) Towards dart-lang/code_builder#343 The docs showed the argument and the receiver flipped in the output. --- pkgs/code_builder/CHANGELOG.md | 2 ++ pkgs/code_builder/lib/src/specs/expression.dart | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 9350a7548..47cf826f6 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -4,6 +4,8 @@ `no_leading_underscores_for_library_prefixes` is most useful for hand edited code where the appearance of a private name which is already not visible outside the library is confusing. +* Fix the docs for `Expression.assign`, `ifNullThen`, and `assignNullAware` + which had the argument and receiver flipped. ## 4.1.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 95b28461d..9b130c832 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -179,21 +179,21 @@ abstract class Expression implements Spec { 'await', ); - /// Return `{other} = {this}`. + /// Return `{this} = {other}`. Expression assign(Expression other) => BinaryExpression._( this, other, '=', ); - /// Return `{other} ?? {this}`. + /// Return `{this} ?? {other}`. Expression ifNullThen(Expression other) => BinaryExpression._( this, other, '??', ); - /// Return `{other} ??= {this}`. + /// Return `{this} ??= {other}`. Expression assignNullAware(Expression other) => BinaryExpression._( this, other, From 7fa9559576522a13b045d4e85d7e2cbf4b7409c7 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 8 Jun 2022 09:33:11 -0700 Subject: [PATCH 200/271] Add declareVar/Final/Const (dart-lang/code_builder#363) Towards dart-lang/code_builder#343 These utilities serve as a replacement for `assignVar/Final/Const` which have an inverted responsibility - the variable is told about it's assignment, rather than an assignment being told about the variable it is assigned to. Unifies the interaction with `Expression.assign`. Use named instead of positional optional arguments. Add an optional argument for a `late` prefix for the final and var declarations. Const variables may not be `late`. Will deprecate the `assign*` methods in a followup after doing some cleanup of internal usage. --- pkgs/code_builder/CHANGELOG.md | 3 ++ pkgs/code_builder/lib/code_builder.dart | 3 ++ .../lib/src/specs/expression.dart | 40 ++++++++++++++ .../test/specs/code/expression_test.dart | 53 +++++++++++++++++++ 4 files changed, 99 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 47cf826f6..42142f1cc 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -6,6 +6,9 @@ outside the library is confusing. * Fix the docs for `Expression.assign`, `ifNullThen`, and `assignNullAware` which had the argument and receiver flipped. +* Add `declareConst`, `declareFinal`, and `declareVar` to replace + `Expression.assignConst`, `assignFinal`, and `assignVar`. Add support for late + variables with the `declare*` utilities. ## 4.1.0 diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 013cc5ddf..b3ccb326c 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -26,6 +26,9 @@ export 'src/specs/expression.dart' InvokeExpressionType, LiteralExpression, LiteralListExpression, + declareConst, + declareFinal, + declareVar, literal, literalNull, literalNum, diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 9b130c832..c7c3136b8 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -323,6 +323,46 @@ abstract class Expression implements Spec { Expression get expression => this; } +/// Declare a const variable named [variableName]. +/// +/// Returns `const {variableName}`, or `const {type} {variableName}`. +Expression declareConst(String variableName, {Reference? type}) => type == null + ? LiteralExpression._('const $variableName') + : BinaryExpression._( + const LiteralExpression._('const'), _typedVar(variableName, type), ''); + +/// Declare a final variable named [variableName]. +/// +/// Returns `final {variableName}`, or `final {type} {variableName}`. +/// If [late] is true the declaration is prefixed with `late`. +Expression declareFinal(String variableName, + {Reference? type, bool late = false}) => + _late( + late, + type == null + ? LiteralExpression._('final $variableName') + : BinaryExpression._(const LiteralExpression._('final'), + _typedVar(variableName, type), '')); + +/// Declare a variable named [variableName]. +/// +/// Returns `var {variableName}`, or `{type} {variableName}`. +/// If [late] is true the declaration is prefixed with `late`. +Expression declareVar(String variableName, + {Reference? type, bool late = false}) => + _late( + late, + type == null + ? LiteralExpression._('var $variableName') + : _typedVar(variableName, type)); + +Expression _typedVar(String variableName, Reference type) => + BinaryExpression._(type.expression, LiteralExpression._(variableName), ''); + +Expression _late(bool late, Expression expression) => late + ? BinaryExpression._(const LiteralExpression._('late'), expression, '') + : expression; + /// Creates `typedef {name} =`. Code createTypeDef(String name, FunctionType type) => BinaryExpression._( LiteralExpression._('typedef $name'), type.expression, '=') diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 8519124cb..99663c656 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -610,4 +610,57 @@ void main() { expect(refer('foo').operatorEuclideanModulo(refer('foo2')), equalsDart('foo % foo2')); }); + + test('should emit a const variable declaration', () { + expect(declareConst('foo').assign(refer('bar')), + equalsDart('const foo = bar')); + }); + + test('should emit a typed const variable declaration', () { + expect(declareConst('foo', type: refer('String')).assign(refer('bar')), + equalsDart('const String foo = bar')); + }); + + test('should emit a final variable declaration', () { + expect(declareFinal('foo').assign(refer('bar')), + equalsDart('final foo = bar')); + }); + + test('should emit a typed final variable declaration', () { + expect(declareFinal('foo', type: refer('String')).assign(refer('bar')), + equalsDart('final String foo = bar')); + }); + + test('should emit a late final variable declaration', () { + expect(declareFinal('foo', late: true).assign(refer('bar')), + equalsDart('late final foo = bar')); + }); + + test('should emit a late typed final variable declaration', () { + expect( + declareFinal('foo', type: refer('String'), late: true) + .assign(refer('bar')), + equalsDart('late final String foo = bar')); + }); + + test('should emit a variable declaration', () { + expect(declareVar('foo').assign(refer('bar')), equalsDart('var foo = bar')); + }); + + test('should emit a typed variable declaration', () { + expect(declareVar('foo', type: refer('String')).assign(refer('bar')), + equalsDart('String foo = bar')); + }); + + test('should emit a late variable declaration', () { + expect(declareVar('foo', late: true).assign(refer('bar')), + equalsDart('late var foo = bar')); + }); + + test('should emit a late typed variable declaration', () { + expect( + declareVar('foo', type: refer('String'), late: true) + .assign(refer('bar')), + equalsDart('late String foo = bar')); + }); } From b58f8e0fe0f8cd93c4fac5a5a521c71d3766f89b Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Tue, 26 Jul 2022 16:36:42 +0200 Subject: [PATCH 201/271] Fix the typo in the argument name (dart-lang/code_builder#367) --- pkgs/code_builder/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 98a217745..19241e3f2 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -104,7 +104,7 @@ These steps must be run without deleting the source files. ```bash $ dart run build_runner generate-build-script $ dart compile kernel .dart_tool/build/entrypoint/build.dart -$ dart .dart_tool/build/entrypoint/build.dill build --delete_conflicting-outputs +$ dart .dart_tool/build/entrypoint/build.dill build --delete-conflicting-outputs ``` [build_runner]: https://pub.dev/packages/build_runner From 51cc9ac3fa210578ca9f2c87275698425f0ed88c Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Wed, 27 Jul 2022 16:21:49 +0200 Subject: [PATCH 202/271] Add support for super initializer constructor arguments (dart-lang/code_builder#368) Add `ParameterBuilder.toSuper` so suport super formal parameters language feature. --- .../.github/workflows/test-package.yml | 2 +- pkgs/code_builder/CHANGELOG.md | 2 + pkgs/code_builder/analysis_options.yaml | 1 - pkgs/code_builder/lib/src/allocator.dart | 2 +- pkgs/code_builder/lib/src/emitter.dart | 3 + pkgs/code_builder/lib/src/specs/class.g.dart | 36 +++---- pkgs/code_builder/lib/src/specs/code.g.dart | 13 ++- .../lib/src/specs/constructor.g.dart | 32 ++++--- .../lib/src/specs/directive.g.dart | 29 +++--- pkgs/code_builder/lib/src/specs/enum.g.dart | 37 ++++---- .../lib/src/specs/extension.g.dart | 20 ++-- pkgs/code_builder/lib/src/specs/field.g.dart | 30 +++--- .../code_builder/lib/src/specs/library.g.dart | 16 ++-- pkgs/code_builder/lib/src/specs/method.dart | 12 +++ pkgs/code_builder/lib/src/specs/method.g.dart | 94 ++++++++++++------- pkgs/code_builder/lib/src/specs/mixin.g.dart | 28 +++--- .../lib/src/specs/type_function.g.dart | 20 ++-- .../lib/src/specs/type_reference.g.dart | 16 ++-- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/class_test.dart | 27 ++++++ 20 files changed, 260 insertions(+), 162 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 2dc0a515a..52cb01c7f 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.17.0, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1.0 diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 42142f1cc..89557f43f 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -9,6 +9,8 @@ * Add `declareConst`, `declareFinal`, and `declareVar` to replace `Expression.assignConst`, `assignFinal`, and `assignVar`. Add support for late variables with the `declare*` utilities. +* Add `ParameterBuilder.toSuper` so suport super formal parameters language + feature. ## 4.1.0 diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml index 388cd8776..bf0f0b696 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/analysis_options.yaml @@ -12,7 +12,6 @@ linter: - control_flow_in_finally - empty_statements - hash_and_equals - - invariant_booleans - iterable_contains_unrelated_type - list_remove_unrelated_type - no_adjacent_strings_in_list diff --git a/pkgs/code_builder/lib/src/allocator.dart b/pkgs/code_builder/lib/src/allocator.dart index b8b36f381..18d2d8c0d 100644 --- a/pkgs/code_builder/lib/src/allocator.dart +++ b/pkgs/code_builder/lib/src/allocator.dart @@ -58,7 +58,7 @@ class _Allocator implements Allocator { } @override - Iterable get imports => _imports.map((u) => Directive.import(u)); + Iterable get imports => _imports.map(Directive.import); } class _NullAllocator implements Allocator { diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 0fa7410d5..ce7b2bb21 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -614,6 +614,9 @@ class DartEmitter extends Object if (spec.toThis) { output.write('this.'); } + if (spec.toSuper) { + output.write('super.'); + } output.write(spec.name); if (optional && spec.defaultTo != null) { output.write(' = '); diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index 589ecd924..81854a2a8 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -46,17 +46,17 @@ class _$Class extends Class { required this.fields, required this.name}) : super._() { - BuiltValueNullFieldError.checkNotNull(abstract, 'Class', 'abstract'); - BuiltValueNullFieldError.checkNotNull(annotations, 'Class', 'annotations'); - BuiltValueNullFieldError.checkNotNull(docs, 'Class', 'docs'); - BuiltValueNullFieldError.checkNotNull(implements, 'Class', 'implements'); - BuiltValueNullFieldError.checkNotNull(mixins, 'Class', 'mixins'); - BuiltValueNullFieldError.checkNotNull(types, 'Class', 'types'); + BuiltValueNullFieldError.checkNotNull(abstract, r'Class', 'abstract'); + BuiltValueNullFieldError.checkNotNull(annotations, r'Class', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'Class', 'docs'); + BuiltValueNullFieldError.checkNotNull(implements, r'Class', 'implements'); + BuiltValueNullFieldError.checkNotNull(mixins, r'Class', 'mixins'); + BuiltValueNullFieldError.checkNotNull(types, r'Class', 'types'); BuiltValueNullFieldError.checkNotNull( - constructors, 'Class', 'constructors'); - BuiltValueNullFieldError.checkNotNull(methods, 'Class', 'methods'); - BuiltValueNullFieldError.checkNotNull(fields, 'Class', 'fields'); - BuiltValueNullFieldError.checkNotNull(name, 'Class', 'name'); + constructors, r'Class', 'constructors'); + BuiltValueNullFieldError.checkNotNull(methods, r'Class', 'methods'); + BuiltValueNullFieldError.checkNotNull(fields, r'Class', 'fields'); + BuiltValueNullFieldError.checkNotNull(name, r'Class', 'name'); } @override @@ -109,7 +109,7 @@ class _$Class extends Class { @override String toString() { - return (newBuiltValueToStringHelper('Class') + return (newBuiltValueToStringHelper(r'Class') ..add('abstract', abstract) ..add('annotations', annotations) ..add('docs', docs) @@ -293,13 +293,15 @@ class _$ClassBuilder extends ClassBuilder { } @override - _$Class build() { + Class build() => _build(); + + _$Class _build() { _$Class _$result; try { _$result = _$v ?? new _$Class._( abstract: BuiltValueNullFieldError.checkNotNull( - abstract, 'Class', 'abstract'), + abstract, r'Class', 'abstract'), annotations: annotations.build(), docs: docs.build(), extend: extend, @@ -309,8 +311,8 @@ class _$ClassBuilder extends ClassBuilder { constructors: constructors.build(), methods: methods.build(), fields: fields.build(), - name: - BuiltValueNullFieldError.checkNotNull(name, 'Class', 'name')); + name: BuiltValueNullFieldError.checkNotNull( + name, r'Class', 'name')); } catch (_) { late String _$failedField; try { @@ -333,7 +335,7 @@ class _$ClassBuilder extends ClassBuilder { fields.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'Class', _$failedField, e.toString()); + r'Class', _$failedField, e.toString()); } rethrow; } @@ -342,4 +344,4 @@ class _$ClassBuilder extends ClassBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart index 0f238df34..beb7e5c3f 100644 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -14,7 +14,7 @@ class _$Block extends Block { (new BlockBuilder()..update(updates)).build() as _$Block; _$Block._({required this.statements}) : super._() { - BuiltValueNullFieldError.checkNotNull(statements, 'Block', 'statements'); + BuiltValueNullFieldError.checkNotNull(statements, r'Block', 'statements'); } @override @@ -37,7 +37,8 @@ class _$Block extends Block { @override String toString() { - return (newBuiltValueToStringHelper('Block')..add('statements', statements)) + return (newBuiltValueToStringHelper(r'Block') + ..add('statements', statements)) .toString(); } } @@ -80,7 +81,9 @@ class _$BlockBuilder extends BlockBuilder { } @override - _$Block build() { + Block build() => _build(); + + _$Block _build() { _$Block _$result; try { _$result = _$v ?? new _$Block._(statements: statements.build()); @@ -91,7 +94,7 @@ class _$BlockBuilder extends BlockBuilder { statements.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'Block', _$failedField, e.toString()); + r'Block', _$failedField, e.toString()); } rethrow; } @@ -100,4 +103,4 @@ class _$BlockBuilder extends BlockBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index 12ba8b0fd..071329928 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -50,17 +50,17 @@ class _$Constructor extends Constructor { this.redirect}) : super._() { BuiltValueNullFieldError.checkNotNull( - annotations, 'Constructor', 'annotations'); - BuiltValueNullFieldError.checkNotNull(docs, 'Constructor', 'docs'); + annotations, r'Constructor', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'Constructor', 'docs'); BuiltValueNullFieldError.checkNotNull( - optionalParameters, 'Constructor', 'optionalParameters'); + optionalParameters, r'Constructor', 'optionalParameters'); BuiltValueNullFieldError.checkNotNull( - requiredParameters, 'Constructor', 'requiredParameters'); + requiredParameters, r'Constructor', 'requiredParameters'); BuiltValueNullFieldError.checkNotNull( - initializers, 'Constructor', 'initializers'); - BuiltValueNullFieldError.checkNotNull(external, 'Constructor', 'external'); - BuiltValueNullFieldError.checkNotNull(constant, 'Constructor', 'constant'); - BuiltValueNullFieldError.checkNotNull(factory, 'Constructor', 'factory'); + initializers, r'Constructor', 'initializers'); + BuiltValueNullFieldError.checkNotNull(external, r'Constructor', 'external'); + BuiltValueNullFieldError.checkNotNull(constant, r'Constructor', 'constant'); + BuiltValueNullFieldError.checkNotNull(factory, r'Constructor', 'factory'); } @override @@ -116,7 +116,7 @@ class _$Constructor extends Constructor { @override String toString() { - return (newBuiltValueToStringHelper('Constructor') + return (newBuiltValueToStringHelper(r'Constructor') ..add('annotations', annotations) ..add('docs', docs) ..add('optionalParameters', optionalParameters) @@ -314,7 +314,9 @@ class _$ConstructorBuilder extends ConstructorBuilder { } @override - _$Constructor build() { + Constructor build() => _build(); + + _$Constructor _build() { _$Constructor _$result; try { _$result = _$v ?? @@ -326,11 +328,11 @@ class _$ConstructorBuilder extends ConstructorBuilder { initializers: initializers.build(), body: body, external: BuiltValueNullFieldError.checkNotNull( - external, 'Constructor', 'external'), + external, r'Constructor', 'external'), constant: BuiltValueNullFieldError.checkNotNull( - constant, 'Constructor', 'constant'), + constant, r'Constructor', 'constant'), factory: BuiltValueNullFieldError.checkNotNull( - factory, 'Constructor', 'factory'), + factory, r'Constructor', 'factory'), lambda: lambda, name: name, redirect: redirect); @@ -349,7 +351,7 @@ class _$ConstructorBuilder extends ConstructorBuilder { initializers.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'Constructor', _$failedField, e.toString()); + r'Constructor', _$failedField, e.toString()); } rethrow; } @@ -358,4 +360,4 @@ class _$ConstructorBuilder extends ConstructorBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart index fde564c51..598ef1667 100644 --- a/pkgs/code_builder/lib/src/specs/directive.g.dart +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -31,11 +31,11 @@ class _$Directive extends Directive { required this.hide, required this.deferred}) : super._() { - BuiltValueNullFieldError.checkNotNull(url, 'Directive', 'url'); - BuiltValueNullFieldError.checkNotNull(type, 'Directive', 'type'); - BuiltValueNullFieldError.checkNotNull(show, 'Directive', 'show'); - BuiltValueNullFieldError.checkNotNull(hide, 'Directive', 'hide'); - BuiltValueNullFieldError.checkNotNull(deferred, 'Directive', 'deferred'); + BuiltValueNullFieldError.checkNotNull(url, r'Directive', 'url'); + BuiltValueNullFieldError.checkNotNull(type, r'Directive', 'type'); + BuiltValueNullFieldError.checkNotNull(show, r'Directive', 'show'); + BuiltValueNullFieldError.checkNotNull(hide, r'Directive', 'hide'); + BuiltValueNullFieldError.checkNotNull(deferred, r'Directive', 'deferred'); } @override @@ -69,7 +69,7 @@ class _$Directive extends Directive { @override String toString() { - return (newBuiltValueToStringHelper('Directive') + return (newBuiltValueToStringHelper(r'Directive') ..add('as', as) ..add('url', url) ..add('type', type) @@ -183,22 +183,25 @@ class _$DirectiveBuilder extends DirectiveBuilder { } @override - _$Directive build() { + Directive build() => _build(); + + _$Directive _build() { final _$result = _$v ?? new _$Directive._( as: as, - url: BuiltValueNullFieldError.checkNotNull(url, 'Directive', 'url'), + url: + BuiltValueNullFieldError.checkNotNull(url, r'Directive', 'url'), type: BuiltValueNullFieldError.checkNotNull( - type, 'Directive', 'type'), + type, r'Directive', 'type'), show: BuiltValueNullFieldError.checkNotNull( - show, 'Directive', 'show'), + show, r'Directive', 'show'), hide: BuiltValueNullFieldError.checkNotNull( - hide, 'Directive', 'hide'), + hide, r'Directive', 'hide'), deferred: BuiltValueNullFieldError.checkNotNull( - deferred, 'Directive', 'deferred')); + deferred, r'Directive', 'deferred')); replace(_$result); return _$result; } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/enum.g.dart b/pkgs/code_builder/lib/src/specs/enum.g.dart index b87e1c48c..478f08657 100644 --- a/pkgs/code_builder/lib/src/specs/enum.g.dart +++ b/pkgs/code_builder/lib/src/specs/enum.g.dart @@ -25,10 +25,10 @@ class _$Enum extends Enum { required this.annotations, required this.docs}) : super._() { - BuiltValueNullFieldError.checkNotNull(name, 'Enum', 'name'); - BuiltValueNullFieldError.checkNotNull(values, 'Enum', 'values'); - BuiltValueNullFieldError.checkNotNull(annotations, 'Enum', 'annotations'); - BuiltValueNullFieldError.checkNotNull(docs, 'Enum', 'docs'); + BuiltValueNullFieldError.checkNotNull(name, r'Enum', 'name'); + BuiltValueNullFieldError.checkNotNull(values, r'Enum', 'values'); + BuiltValueNullFieldError.checkNotNull(annotations, r'Enum', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'Enum', 'docs'); } @override @@ -57,7 +57,7 @@ class _$Enum extends Enum { @override String toString() { - return (newBuiltValueToStringHelper('Enum') + return (newBuiltValueToStringHelper(r'Enum') ..add('name', name) ..add('values', values) ..add('annotations', annotations) @@ -143,12 +143,15 @@ class _$EnumBuilder extends EnumBuilder { } @override - _$Enum build() { + Enum build() => _build(); + + _$Enum _build() { _$Enum _$result; try { _$result = _$v ?? new _$Enum._( - name: BuiltValueNullFieldError.checkNotNull(name, 'Enum', 'name'), + name: + BuiltValueNullFieldError.checkNotNull(name, r'Enum', 'name'), values: values.build(), annotations: annotations.build(), docs: docs.build()); @@ -163,7 +166,7 @@ class _$EnumBuilder extends EnumBuilder { docs.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'Enum', _$failedField, e.toString()); + r'Enum', _$failedField, e.toString()); } rethrow; } @@ -186,10 +189,10 @@ class _$EnumValue extends EnumValue { _$EnumValue._( {required this.name, required this.annotations, required this.docs}) : super._() { - BuiltValueNullFieldError.checkNotNull(name, 'EnumValue', 'name'); + BuiltValueNullFieldError.checkNotNull(name, r'EnumValue', 'name'); BuiltValueNullFieldError.checkNotNull( - annotations, 'EnumValue', 'annotations'); - BuiltValueNullFieldError.checkNotNull(docs, 'EnumValue', 'docs'); + annotations, r'EnumValue', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'EnumValue', 'docs'); } @override @@ -216,7 +219,7 @@ class _$EnumValue extends EnumValue { @override String toString() { - return (newBuiltValueToStringHelper('EnumValue') + return (newBuiltValueToStringHelper(r'EnumValue') ..add('name', name) ..add('annotations', annotations) ..add('docs', docs)) @@ -288,13 +291,15 @@ class _$EnumValueBuilder extends EnumValueBuilder { } @override - _$EnumValue build() { + EnumValue build() => _build(); + + _$EnumValue _build() { _$EnumValue _$result; try { _$result = _$v ?? new _$EnumValue._( name: BuiltValueNullFieldError.checkNotNull( - name, 'EnumValue', 'name'), + name, r'EnumValue', 'name'), annotations: annotations.build(), docs: docs.build()); } catch (_) { @@ -306,7 +311,7 @@ class _$EnumValueBuilder extends EnumValueBuilder { docs.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'EnumValue', _$failedField, e.toString()); + r'EnumValue', _$failedField, e.toString()); } rethrow; } @@ -315,4 +320,4 @@ class _$EnumValueBuilder extends EnumValueBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/extension.g.dart b/pkgs/code_builder/lib/src/specs/extension.g.dart index cf90d889d..7d4afce7c 100644 --- a/pkgs/code_builder/lib/src/specs/extension.g.dart +++ b/pkgs/code_builder/lib/src/specs/extension.g.dart @@ -35,11 +35,11 @@ class _$Extension extends Extension { this.name}) : super._() { BuiltValueNullFieldError.checkNotNull( - annotations, 'Extension', 'annotations'); - BuiltValueNullFieldError.checkNotNull(docs, 'Extension', 'docs'); - BuiltValueNullFieldError.checkNotNull(types, 'Extension', 'types'); - BuiltValueNullFieldError.checkNotNull(methods, 'Extension', 'methods'); - BuiltValueNullFieldError.checkNotNull(fields, 'Extension', 'fields'); + annotations, r'Extension', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'Extension', 'docs'); + BuiltValueNullFieldError.checkNotNull(types, r'Extension', 'types'); + BuiltValueNullFieldError.checkNotNull(methods, r'Extension', 'methods'); + BuiltValueNullFieldError.checkNotNull(fields, r'Extension', 'fields'); } @override @@ -78,7 +78,7 @@ class _$Extension extends Extension { @override String toString() { - return (newBuiltValueToStringHelper('Extension') + return (newBuiltValueToStringHelper(r'Extension') ..add('annotations', annotations) ..add('docs', docs) ..add('on', on) @@ -206,7 +206,9 @@ class _$ExtensionBuilder extends ExtensionBuilder { } @override - _$Extension build() { + Extension build() => _build(); + + _$Extension _build() { _$Extension _$result; try { _$result = _$v ?? @@ -234,7 +236,7 @@ class _$ExtensionBuilder extends ExtensionBuilder { fields.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'Extension', _$failedField, e.toString()); + r'Extension', _$failedField, e.toString()); } rethrow; } @@ -243,4 +245,4 @@ class _$ExtensionBuilder extends ExtensionBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 9c89724aa..543a053df 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -37,12 +37,12 @@ class _$Field extends Field { this.type, required this.modifier}) : super._() { - BuiltValueNullFieldError.checkNotNull(annotations, 'Field', 'annotations'); - BuiltValueNullFieldError.checkNotNull(docs, 'Field', 'docs'); - BuiltValueNullFieldError.checkNotNull(static, 'Field', 'static'); - BuiltValueNullFieldError.checkNotNull(late, 'Field', 'late'); - BuiltValueNullFieldError.checkNotNull(name, 'Field', 'name'); - BuiltValueNullFieldError.checkNotNull(modifier, 'Field', 'modifier'); + BuiltValueNullFieldError.checkNotNull(annotations, r'Field', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'Field', 'docs'); + BuiltValueNullFieldError.checkNotNull(static, r'Field', 'static'); + BuiltValueNullFieldError.checkNotNull(late, r'Field', 'late'); + BuiltValueNullFieldError.checkNotNull(name, r'Field', 'name'); + BuiltValueNullFieldError.checkNotNull(modifier, r'Field', 'modifier'); } @override @@ -84,7 +84,7 @@ class _$Field extends Field { @override String toString() { - return (newBuiltValueToStringHelper('Field') + return (newBuiltValueToStringHelper(r'Field') ..add('annotations', annotations) ..add('docs', docs) ..add('assignment', assignment) @@ -226,7 +226,9 @@ class _$FieldBuilder extends FieldBuilder { } @override - _$Field build() { + Field build() => _build(); + + _$Field _build() { _$Field _$result; try { _$result = _$v ?? @@ -235,14 +237,14 @@ class _$FieldBuilder extends FieldBuilder { docs: docs.build(), assignment: assignment, static: BuiltValueNullFieldError.checkNotNull( - static, 'Field', 'static'), + static, r'Field', 'static'), late: - BuiltValueNullFieldError.checkNotNull(late, 'Field', 'late'), + BuiltValueNullFieldError.checkNotNull(late, r'Field', 'late'), name: - BuiltValueNullFieldError.checkNotNull(name, 'Field', 'name'), + BuiltValueNullFieldError.checkNotNull(name, r'Field', 'name'), type: type, modifier: BuiltValueNullFieldError.checkNotNull( - modifier, 'Field', 'modifier')); + modifier, r'Field', 'modifier')); } catch (_) { late String _$failedField; try { @@ -252,7 +254,7 @@ class _$FieldBuilder extends FieldBuilder { docs.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'Field', _$failedField, e.toString()); + r'Field', _$failedField, e.toString()); } rethrow; } @@ -261,4 +263,4 @@ class _$FieldBuilder extends FieldBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index 9cbf72040..ec67eaea2 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -26,9 +26,9 @@ class _$Library extends Library { this.name}) : super._() { BuiltValueNullFieldError.checkNotNull( - annotations, 'Library', 'annotations'); - BuiltValueNullFieldError.checkNotNull(directives, 'Library', 'directives'); - BuiltValueNullFieldError.checkNotNull(body, 'Library', 'body'); + annotations, r'Library', 'annotations'); + BuiltValueNullFieldError.checkNotNull(directives, r'Library', 'directives'); + BuiltValueNullFieldError.checkNotNull(body, r'Library', 'body'); } @override @@ -58,7 +58,7 @@ class _$Library extends Library { @override String toString() { - return (newBuiltValueToStringHelper('Library') + return (newBuiltValueToStringHelper(r'Library') ..add('annotations', annotations) ..add('directives', directives) ..add('body', body) @@ -144,7 +144,9 @@ class _$LibraryBuilder extends LibraryBuilder { } @override - _$Library build() { + Library build() => _build(); + + _$Library _build() { _$Library _$result; try { _$result = _$v ?? @@ -164,7 +166,7 @@ class _$LibraryBuilder extends LibraryBuilder { body.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'Library', _$failedField, e.toString()); + r'Library', _$failedField, e.toString()); } rethrow; } @@ -173,4 +175,4 @@ class _$LibraryBuilder extends LibraryBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/method.dart b/pkgs/code_builder/lib/src/specs/method.dart index e5b62fca9..2c0a645dc 100644 --- a/pkgs/code_builder/lib/src/specs/method.dart +++ b/pkgs/code_builder/lib/src/specs/method.dart @@ -180,6 +180,12 @@ abstract class Parameter extends Object /// This is only valid on constructors; bool get toThis; + /// Whether this parameter should be passed to super\ + /// constructor (i.e. `super.`). + /// + /// This is only valid on constructors; + bool get toSuper; + @override BuiltList get annotations; @@ -232,6 +238,12 @@ abstract class ParameterBuilder extends Object /// This is only valid on constructors; bool toThis = false; + /// Whether this parameter should be passed to super\ + /// constructor (i.e. `super.`). + /// + /// This is only valid on constructors; + bool toSuper = false; + @override ListBuilder annotations = ListBuilder(); diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index 2e2144984..f503da88f 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -52,15 +52,16 @@ class _$Method extends Method { this.modifier, this.returns}) : super._() { - BuiltValueNullFieldError.checkNotNull(annotations, 'Method', 'annotations'); - BuiltValueNullFieldError.checkNotNull(docs, 'Method', 'docs'); - BuiltValueNullFieldError.checkNotNull(types, 'Method', 'types'); BuiltValueNullFieldError.checkNotNull( - optionalParameters, 'Method', 'optionalParameters'); + annotations, r'Method', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'Method', 'docs'); + BuiltValueNullFieldError.checkNotNull(types, r'Method', 'types'); BuiltValueNullFieldError.checkNotNull( - requiredParameters, 'Method', 'requiredParameters'); - BuiltValueNullFieldError.checkNotNull(external, 'Method', 'external'); - BuiltValueNullFieldError.checkNotNull(static, 'Method', 'static'); + optionalParameters, r'Method', 'optionalParameters'); + BuiltValueNullFieldError.checkNotNull( + requiredParameters, r'Method', 'requiredParameters'); + BuiltValueNullFieldError.checkNotNull(external, r'Method', 'external'); + BuiltValueNullFieldError.checkNotNull(static, r'Method', 'static'); } @override @@ -121,7 +122,7 @@ class _$Method extends Method { @override String toString() { - return (newBuiltValueToStringHelper('Method') + return (newBuiltValueToStringHelper(r'Method') ..add('annotations', annotations) ..add('docs', docs) ..add('types', types) @@ -333,7 +334,9 @@ class _$MethodBuilder extends MethodBuilder { } @override - _$Method build() { + Method build() => _build(); + + _$Method _build() { _$Method _$result; try { _$result = _$v ?? @@ -345,10 +348,10 @@ class _$MethodBuilder extends MethodBuilder { requiredParameters: requiredParameters.build(), body: body, external: BuiltValueNullFieldError.checkNotNull( - external, 'Method', 'external'), + external, r'Method', 'external'), lambda: lambda, static: BuiltValueNullFieldError.checkNotNull( - static, 'Method', 'static'), + static, r'Method', 'static'), name: name, type: type, modifier: modifier, @@ -368,7 +371,7 @@ class _$MethodBuilder extends MethodBuilder { requiredParameters.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'Method', _$failedField, e.toString()); + r'Method', _$failedField, e.toString()); } rethrow; } @@ -387,6 +390,8 @@ class _$Parameter extends Parameter { @override final bool toThis; @override + final bool toSuper; + @override final BuiltList annotations; @override final BuiltList docs; @@ -407,6 +412,7 @@ class _$Parameter extends Parameter { required this.name, required this.named, required this.toThis, + required this.toSuper, required this.annotations, required this.docs, required this.types, @@ -414,15 +420,16 @@ class _$Parameter extends Parameter { required this.required, required this.covariant}) : super._() { - BuiltValueNullFieldError.checkNotNull(name, 'Parameter', 'name'); - BuiltValueNullFieldError.checkNotNull(named, 'Parameter', 'named'); - BuiltValueNullFieldError.checkNotNull(toThis, 'Parameter', 'toThis'); + BuiltValueNullFieldError.checkNotNull(name, r'Parameter', 'name'); + BuiltValueNullFieldError.checkNotNull(named, r'Parameter', 'named'); + BuiltValueNullFieldError.checkNotNull(toThis, r'Parameter', 'toThis'); + BuiltValueNullFieldError.checkNotNull(toSuper, r'Parameter', 'toSuper'); BuiltValueNullFieldError.checkNotNull( - annotations, 'Parameter', 'annotations'); - BuiltValueNullFieldError.checkNotNull(docs, 'Parameter', 'docs'); - BuiltValueNullFieldError.checkNotNull(types, 'Parameter', 'types'); - BuiltValueNullFieldError.checkNotNull(required, 'Parameter', 'required'); - BuiltValueNullFieldError.checkNotNull(covariant, 'Parameter', 'covariant'); + annotations, r'Parameter', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'Parameter', 'docs'); + BuiltValueNullFieldError.checkNotNull(types, r'Parameter', 'types'); + BuiltValueNullFieldError.checkNotNull(required, r'Parameter', 'required'); + BuiltValueNullFieldError.checkNotNull(covariant, r'Parameter', 'covariant'); } @override @@ -440,6 +447,7 @@ class _$Parameter extends Parameter { name == other.name && named == other.named && toThis == other.toThis && + toSuper == other.toSuper && annotations == other.annotations && docs == other.docs && types == other.types && @@ -458,10 +466,12 @@ class _$Parameter extends Parameter { $jc( $jc( $jc( - $jc($jc(0, defaultTo.hashCode), - name.hashCode), - named.hashCode), - toThis.hashCode), + $jc( + $jc($jc(0, defaultTo.hashCode), + name.hashCode), + named.hashCode), + toThis.hashCode), + toSuper.hashCode), annotations.hashCode), docs.hashCode), types.hashCode), @@ -472,11 +482,12 @@ class _$Parameter extends Parameter { @override String toString() { - return (newBuiltValueToStringHelper('Parameter') + return (newBuiltValueToStringHelper(r'Parameter') ..add('defaultTo', defaultTo) ..add('name', name) ..add('named', named) ..add('toThis', toThis) + ..add('toSuper', toSuper) ..add('annotations', annotations) ..add('docs', docs) ..add('types', types) @@ -538,6 +549,18 @@ class _$ParameterBuilder extends ParameterBuilder { super.toThis = toThis; } + @override + bool get toSuper { + _$this; + return super.toSuper; + } + + @override + set toSuper(bool toSuper) { + _$this; + super.toSuper = toSuper; + } + @override ListBuilder get annotations { _$this; @@ -619,6 +642,7 @@ class _$ParameterBuilder extends ParameterBuilder { super.name = $v.name; super.named = $v.named; super.toThis = $v.toThis; + super.toSuper = $v.toSuper; super.annotations = $v.annotations.toBuilder(); super.docs = $v.docs.toBuilder(); super.types = $v.types.toBuilder(); @@ -642,26 +666,30 @@ class _$ParameterBuilder extends ParameterBuilder { } @override - _$Parameter build() { + Parameter build() => _build(); + + _$Parameter _build() { _$Parameter _$result; try { _$result = _$v ?? new _$Parameter._( defaultTo: defaultTo, name: BuiltValueNullFieldError.checkNotNull( - name, 'Parameter', 'name'), + name, r'Parameter', 'name'), named: BuiltValueNullFieldError.checkNotNull( - named, 'Parameter', 'named'), + named, r'Parameter', 'named'), toThis: BuiltValueNullFieldError.checkNotNull( - toThis, 'Parameter', 'toThis'), + toThis, r'Parameter', 'toThis'), + toSuper: BuiltValueNullFieldError.checkNotNull( + toSuper, r'Parameter', 'toSuper'), annotations: annotations.build(), docs: docs.build(), types: types.build(), type: type, required: BuiltValueNullFieldError.checkNotNull( - required, 'Parameter', 'required'), + required, r'Parameter', 'required'), covariant: BuiltValueNullFieldError.checkNotNull( - covariant, 'Parameter', 'covariant')); + covariant, r'Parameter', 'covariant')); } catch (_) { late String _$failedField; try { @@ -673,7 +701,7 @@ class _$ParameterBuilder extends ParameterBuilder { types.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'Parameter', _$failedField, e.toString()); + r'Parameter', _$failedField, e.toString()); } rethrow; } @@ -682,4 +710,4 @@ class _$ParameterBuilder extends ParameterBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/mixin.g.dart b/pkgs/code_builder/lib/src/specs/mixin.g.dart index 280208754..ea9700e60 100644 --- a/pkgs/code_builder/lib/src/specs/mixin.g.dart +++ b/pkgs/code_builder/lib/src/specs/mixin.g.dart @@ -37,13 +37,13 @@ class _$Mixin extends Mixin { required this.fields, required this.name}) : super._() { - BuiltValueNullFieldError.checkNotNull(annotations, 'Mixin', 'annotations'); - BuiltValueNullFieldError.checkNotNull(docs, 'Mixin', 'docs'); - BuiltValueNullFieldError.checkNotNull(implements, 'Mixin', 'implements'); - BuiltValueNullFieldError.checkNotNull(types, 'Mixin', 'types'); - BuiltValueNullFieldError.checkNotNull(methods, 'Mixin', 'methods'); - BuiltValueNullFieldError.checkNotNull(fields, 'Mixin', 'fields'); - BuiltValueNullFieldError.checkNotNull(name, 'Mixin', 'name'); + BuiltValueNullFieldError.checkNotNull(annotations, r'Mixin', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'Mixin', 'docs'); + BuiltValueNullFieldError.checkNotNull(implements, r'Mixin', 'implements'); + BuiltValueNullFieldError.checkNotNull(types, r'Mixin', 'types'); + BuiltValueNullFieldError.checkNotNull(methods, r'Mixin', 'methods'); + BuiltValueNullFieldError.checkNotNull(fields, r'Mixin', 'fields'); + BuiltValueNullFieldError.checkNotNull(name, r'Mixin', 'name'); } @override @@ -85,7 +85,7 @@ class _$Mixin extends Mixin { @override String toString() { - return (newBuiltValueToStringHelper('Mixin') + return (newBuiltValueToStringHelper(r'Mixin') ..add('annotations', annotations) ..add('docs', docs) ..add('on', on) @@ -227,7 +227,9 @@ class _$MixinBuilder extends MixinBuilder { } @override - _$Mixin build() { + Mixin build() => _build(); + + _$Mixin _build() { _$Mixin _$result; try { _$result = _$v ?? @@ -239,8 +241,8 @@ class _$MixinBuilder extends MixinBuilder { types: types.build(), methods: methods.build(), fields: fields.build(), - name: - BuiltValueNullFieldError.checkNotNull(name, 'Mixin', 'name')); + name: BuiltValueNullFieldError.checkNotNull( + name, r'Mixin', 'name')); } catch (_) { late String _$failedField; try { @@ -259,7 +261,7 @@ class _$MixinBuilder extends MixinBuilder { fields.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'Mixin', _$failedField, e.toString()); + r'Mixin', _$failedField, e.toString()); } rethrow; } @@ -268,4 +270,4 @@ class _$MixinBuilder extends MixinBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart index 5778c4b11..f9fe0d678 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -34,15 +34,15 @@ class _$FunctionType extends FunctionType { required this.namedRequiredParameters, this.isNullable}) : super._() { - BuiltValueNullFieldError.checkNotNull(types, 'FunctionType', 'types'); + BuiltValueNullFieldError.checkNotNull(types, r'FunctionType', 'types'); BuiltValueNullFieldError.checkNotNull( - requiredParameters, 'FunctionType', 'requiredParameters'); + requiredParameters, r'FunctionType', 'requiredParameters'); BuiltValueNullFieldError.checkNotNull( - optionalParameters, 'FunctionType', 'optionalParameters'); + optionalParameters, r'FunctionType', 'optionalParameters'); BuiltValueNullFieldError.checkNotNull( - namedParameters, 'FunctionType', 'namedParameters'); + namedParameters, r'FunctionType', 'namedParameters'); BuiltValueNullFieldError.checkNotNull( - namedRequiredParameters, 'FunctionType', 'namedRequiredParameters'); + namedRequiredParameters, r'FunctionType', 'namedRequiredParameters'); } @override @@ -82,7 +82,7 @@ class _$FunctionType extends FunctionType { @override String toString() { - return (newBuiltValueToStringHelper('FunctionType') + return (newBuiltValueToStringHelper(r'FunctionType') ..add('returnType', returnType) ..add('types', types) ..add('requiredParameters', requiredParameters) @@ -211,7 +211,9 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { } @override - _$FunctionType build() { + FunctionType build() => _build(); + + _$FunctionType _build() { _$FunctionType _$result; try { _$result = _$v ?? @@ -238,7 +240,7 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { namedRequiredParameters.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'FunctionType', _$failedField, e.toString()); + r'FunctionType', _$failedField, e.toString()); } rethrow; } @@ -247,4 +249,4 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index 27d98da95..b0f5f0d12 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -28,8 +28,8 @@ class _$TypeReference extends TypeReference { required this.types, this.isNullable}) : super._() { - BuiltValueNullFieldError.checkNotNull(symbol, 'TypeReference', 'symbol'); - BuiltValueNullFieldError.checkNotNull(types, 'TypeReference', 'types'); + BuiltValueNullFieldError.checkNotNull(symbol, r'TypeReference', 'symbol'); + BuiltValueNullFieldError.checkNotNull(types, r'TypeReference', 'types'); } @override @@ -61,7 +61,7 @@ class _$TypeReference extends TypeReference { @override String toString() { - return (newBuiltValueToStringHelper('TypeReference') + return (newBuiltValueToStringHelper(r'TypeReference') ..add('symbol', symbol) ..add('url', url) ..add('bound', bound) @@ -161,13 +161,15 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { } @override - _$TypeReference build() { + TypeReference build() => _build(); + + _$TypeReference _build() { _$TypeReference _$result; try { _$result = _$v ?? new _$TypeReference._( symbol: BuiltValueNullFieldError.checkNotNull( - symbol, 'TypeReference', 'symbol'), + symbol, r'TypeReference', 'symbol'), url: url, bound: bound, types: types.build(), @@ -179,7 +181,7 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { types.build(); } catch (e) { throw new BuiltValueNestedFieldError( - 'TypeReference', _$failedField, e.toString()); + r'TypeReference', _$failedField, e.toString()); } rethrow; } @@ -188,4 +190,4 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 494dcc586..6461c6f79 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -5,7 +5,7 @@ description: >- repository: https://github.com/dart-lang/code_builder environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.17.0 <3.0.0' dependencies: built_collection: ^5.0.0 diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index ebf67779c..0320b9a0e 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -360,4 +360,31 @@ void main() { '''), ); }); + + test('should create a class with a constructor+super-formal parameters', () { + expect( + Class((b) => b + ..name = 'Foo' + ..constructors.add(Constructor((b) => b + ..requiredParameters.addAll([ + Parameter((b) => b + ..name = 'a' + ..toSuper = true), + Parameter((b) => b + ..name = 'b' + ..toSuper = true), + ]) + ..optionalParameters.addAll([ + Parameter((b) => b + ..name = 'c' + ..named = true + ..toSuper = true), + ])))), + equalsDart(r''' + class Foo { + Foo(super.a, super.b, {super.c}); + } + '''), + ); + }); } From d3cbbc572d4117aa737a15fd5e23b80c395d3378 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 27 Jul 2022 08:21:46 -0700 Subject: [PATCH 203/271] Release 4.2.0 (dart-lang/code_builder#369) --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 89557f43f..52e558d32 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 4.2.0-dev +## 4.2.0 * Add an ignore for a lint from the `package:lints` recommended set. The lint, `no_leading_underscores_for_library_prefixes` is most useful for hand edited diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 6461c6f79..8d0322743 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.2.0-dev +version: 4.2.0 description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder From 9be9f0af17719724ce477f8ea6a8ad6d01afa2f4 Mon Sep 17 00:00:00 2001 From: Conner Kasten Date: Tue, 2 Aug 2022 18:24:35 -0700 Subject: [PATCH 204/271] Only emit 'late' when using null-safety syntax. (dart-lang/code_builder#371) Fixes dart-lang/code_builder#370 --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/lib/src/emitter.dart | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/field_test.dart | 15 +++++++++++++-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 52e558d32..36479b95f 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.2.1-dev + +* Only emit `late` keyword when using null safety syntax. + ## 4.2.0 * Add an ignore for a lint from the `package:lints` recommended set. The lint, diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index ce7b2bb21..66ddff1e0 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -358,7 +358,7 @@ class DartEmitter extends Object if (spec.static) { output.write('static '); } - if (spec.late) { + if (spec.late && _useNullSafetySyntax) { output.write('late '); } switch (spec.modifier) { diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 8d0322743..c3aeba1ea 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.2.0 +version: 4.2.1-dev description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/field_test.dart b/pkgs/code_builder/test/specs/field_test.dart index 54cdf0bfc..90cc65aa0 100644 --- a/pkgs/code_builder/test/specs/field_test.dart +++ b/pkgs/code_builder/test/specs/field_test.dart @@ -52,13 +52,24 @@ void main() { ); }); - test('should create a late field', () { + test('should create a late field if using null-safety', () { expect( Field((b) => b ..late = true ..name = 'foo'), equalsDart(r''' late var foo; + ''', DartEmitter(useNullSafetySyntax: true)), + ); + }); + + test('should not create a late field if not using null-safety', () { + expect( + Field((b) => b + ..late = true + ..name = 'foo'), + equalsDart(r''' + var foo; '''), ); }); @@ -71,7 +82,7 @@ void main() { ..name = 'foo'), equalsDart(r''' static late var foo; - '''), + ''', DartEmitter(useNullSafetySyntax: true)), ); }); From 19f004c4a2c65d83ac287e969b1997d9e22b4c31 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 4 Aug 2022 08:13:17 -0700 Subject: [PATCH 205/271] Fix some missing implicit const contexts (dart-lang/code_builder#372) There are some expressions where an `isConst` field implies that sub expressions can omit the `const` keyword. This is manually handled in the appropriate visit methods for the expressions where a const context is sensible. In `InvokeExpression` a `type` field expressed the same intent. Using `declareConst` and `assign` did not carry the const context, so an expression would have an omittable `const` keyword. - Add an `isConst` getter on `Expression`. Default to false since the expressions which already can imply const already have definitions with correct usage, except for `InvokeExpression` which had a different API. This is only necessary to allow forwarding in `assign` without overriding in each subclass which can imply a const context. - In assignments, forward `isConst` to the `BinaryExpression`. A const left hand side implies const for the right hand side. - Deprecate the `type` field for `InvokeExpression` in favor of a new override for `isConst`. There is no need for a null unknown-const state. Expressions are by default assumed to not imply a const context and only relevant expression types are checked for `isConst` by the relevant visitors. Update the invoke expression visitor to use `isConst` over checking the type. No methods may be invoked in a const expression and the private constructor is used for invoking methods, so assume `false`. - Always use a `BinaryExpression` for `declareConst`, and mark it as const. This allows the assignment to carry the context through to the other expressions. - Add tests that assigning to a `declareConst` uses an implicit `const` on the right hand side, while assigning to a non-const var uses an explicit `const`. --- pkgs/code_builder/CHANGELOG.md | 1 + .../lib/src/specs/expression.dart | 33 ++++++++++++------- .../lib/src/specs/expression/binary.dart | 1 + .../lib/src/specs/expression/invoke.dart | 23 +++++++++---- .../lib/src/specs/expression/literal.dart | 3 ++ pkgs/code_builder/test/const_test.dart | 17 ++++++++++ 6 files changed, 60 insertions(+), 18 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 36479b95f..07b9d1ca6 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ ## 4.2.1-dev * Only emit `late` keyword when using null safety syntax. +* Use implicit `const` when assigning to a `declareConst` variable. ## 4.2.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index c7c3136b8..58d1befd5 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -32,6 +32,17 @@ abstract class Expression implements Spec { /// An empty expression. static const _empty = CodeExpression(Code('')); + /// Whether this expression implies a const context for sub expressions. + /// + /// Collection literals that are const imply const for all values. + /// Assignment to a const variable implies a const value. + /// Invoking a const constructor implies const for all arguments. + /// + /// The implied const context is used to omit redundant `const` keywords. + /// A value of `false` does not imply that the expression cannot be used in a + /// const context. + bool get isConst => false; + @override R accept(covariant ExpressionVisitor visitor, [R? context]); @@ -180,11 +191,8 @@ abstract class Expression implements Spec { ); /// Return `{this} = {other}`. - Expression assign(Expression other) => BinaryExpression._( - this, - other, - '=', - ); + Expression assign(Expression other) => + BinaryExpression._(this, other, '=', isConst: isConst); /// Return `{this} ?? {other}`. Expression ifNullThen(Expression other) => BinaryExpression._( @@ -326,10 +334,14 @@ abstract class Expression implements Spec { /// Declare a const variable named [variableName]. /// /// Returns `const {variableName}`, or `const {type} {variableName}`. -Expression declareConst(String variableName, {Reference? type}) => type == null - ? LiteralExpression._('const $variableName') - : BinaryExpression._( - const LiteralExpression._('const'), _typedVar(variableName, type), ''); +Expression declareConst(String variableName, {Reference? type}) => + BinaryExpression._( + const LiteralExpression._('const'), + type == null + ? LiteralExpression._(variableName) + : _typedVar(variableName, type), + '', + isConst: true); /// Declare a final variable named [variableName]. /// @@ -454,8 +466,7 @@ abstract class ExpressionEmitter implements ExpressionVisitor { StringSink visitInvokeExpression(InvokeExpression expression, [StringSink? output]) { final out = output ??= StringBuffer(); - return _writeConstExpression( - out, expression.type == InvokeExpressionType.constInstance, () { + return _writeConstExpression(out, expression.isConst, () { expression.target.accept(this, out); if (expression.name != null) { out diff --git a/pkgs/code_builder/lib/src/specs/expression/binary.dart b/pkgs/code_builder/lib/src/specs/expression/binary.dart index 4672a26d0..35e530589 100644 --- a/pkgs/code_builder/lib/src/specs/expression/binary.dart +++ b/pkgs/code_builder/lib/src/specs/expression/binary.dart @@ -10,6 +10,7 @@ class BinaryExpression extends Expression { final Expression right; final String operator; final bool addSpace; + @override final bool isConst; const BinaryExpression._( diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index 6d24e4099..198ad1025 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -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. +// ignore_for_file: deprecated_member_use_from_same_package + part of code_builder.src.specs.expression; /// Represents invoking [target] as a method with arguments. @@ -10,8 +12,12 @@ class InvokeExpression extends Expression { final Expression target; /// Optional; type of invocation. + @Deprecated('Use isConst instead') final InvokeExpressionType? type; + @override + final bool isConst; + final List positionalArguments; final Map namedArguments; final List typeArguments; @@ -19,11 +25,12 @@ class InvokeExpression extends Expression { const InvokeExpression._( this.target, - this.positionalArguments, [ - this.namedArguments = const {}, - this.typeArguments = const [], - ]) : name = null, - type = null; + this.positionalArguments, + this.namedArguments, + this.typeArguments, + ) : name = null, + type = null, + isConst = false; const InvokeExpression.newOf( this.target, @@ -31,7 +38,8 @@ class InvokeExpression extends Expression { this.namedArguments = const {}, this.typeArguments = const [], this.name, - ]) : type = InvokeExpressionType.newInstance; + ]) : type = InvokeExpressionType.newInstance, + isConst = false; const InvokeExpression.constOf( this.target, @@ -39,7 +47,8 @@ class InvokeExpression extends Expression { this.namedArguments = const {}, this.typeArguments = const [], this.name, - ]) : type = InvokeExpressionType.constInstance; + ]) : type = InvokeExpressionType.constInstance, + isConst = true; @override R accept(ExpressionVisitor visitor, [R? context]) => diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 4c896d7e0..2d301f5e6 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -123,6 +123,7 @@ class LiteralExpression extends Expression { } class LiteralListExpression extends Expression { + @override final bool isConst; final List values; final Reference? type; @@ -138,6 +139,7 @@ class LiteralListExpression extends Expression { } class LiteralSetExpression extends Expression { + @override final bool isConst; final Set values; final Reference? type; @@ -153,6 +155,7 @@ class LiteralSetExpression extends Expression { } class LiteralMapExpression extends Expression { + @override final bool isConst; final Map values; final Reference? keyType; diff --git a/pkgs/code_builder/test/const_test.dart b/pkgs/code_builder/test/const_test.dart index b10cea0ef..df21fd3e4 100644 --- a/pkgs/code_builder/test/const_test.dart +++ b/pkgs/code_builder/test/const_test.dart @@ -29,6 +29,23 @@ void main() { ); }); + test('assign to declared constant', () { + expect( + declareConst('constField').assign(constMap), + equalsDart(r''' + const constField = {'list': [], 'duration': Duration()}''', + DartEmitter.scoped()), + ); + }); + + test('assign to declared non-constant', () { + expect( + declareVar('varField').assign(constMap), + equalsDart(r''' + var varField = const {'list': [], 'duration': Duration()}''', + DartEmitter.scoped())); + }); + final library = Library((b) => b ..body.add(Field((b) => b ..name = 'val1' From 1834be85ca9c0e419829cc56ae8206a1ca5987e4 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 10 Aug 2022 12:57:33 -0700 Subject: [PATCH 206/271] Deprecate assignVar, assignFinal, assignConst (dart-lang/code_builder#373) Point to the relevant `declare*` API which replaces them. --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/specs/expression.dart | 3 +++ pkgs/code_builder/test/const_test.dart | 1 + pkgs/code_builder/test/specs/code/expression_test.dart | 8 ++++++++ 4 files changed, 13 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 07b9d1ca6..5cadb416c 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -2,6 +2,7 @@ * Only emit `late` keyword when using null safety syntax. * Use implicit `const` when assigning to a `declareConst` variable. +* Deprecate `assignVar`, `assignConst`, and `assignFinal`. ## 4.2.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 58d1befd5..f2383b138 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -209,6 +209,7 @@ abstract class Expression implements Spec { ); /// Return `var {name} = {this}`. + @Deprecated('Use `declareVar(name).assign(expression)`') Expression assignVar(String name, [Reference? type]) => BinaryExpression._( type == null ? LiteralExpression._('var $name') @@ -222,6 +223,7 @@ abstract class Expression implements Spec { ); /// Return `final {name} = {this}`. + @Deprecated('Use `declareFinal(name).assign(expression)`') Expression assignFinal(String name, [Reference? type]) => BinaryExpression._( type == null ? const LiteralExpression._('final') @@ -235,6 +237,7 @@ abstract class Expression implements Spec { ); /// Return `const {name} = {this}`. + @Deprecated('Use `declareConst(name).assign(expression)`') Expression assignConst(String name, [Reference? type]) => BinaryExpression._( type == null ? const LiteralExpression._('const') diff --git a/pkgs/code_builder/test/const_test.dart b/pkgs/code_builder/test/const_test.dart index df21fd3e4..7487b001b 100644 --- a/pkgs/code_builder/test/const_test.dart +++ b/pkgs/code_builder/test/const_test.dart @@ -22,6 +22,7 @@ void main() { test('assignConst', () { expect( + // ignore: deprecated_member_use_from_same_package constMap.assignConst('constField'), equalsDart(r''' const constField = {'list': [], 'duration': Duration()}''', diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 99663c656..648ca6de2 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -412,6 +412,7 @@ void main() { refer('bar') .index(literalTrue) .ifNullThen(literalFalse) + // ignore: deprecated_member_use_from_same_package .assignVar('foo') .statement, equalsDart('var foo = bar[true] ?? false;'), @@ -427,6 +428,7 @@ void main() { test('should emit an index operator', () { expect( + // ignore: deprecated_member_use_from_same_package refer('bar').index(literalString('key')).assignVar('foo').statement, equalsDart("var foo = bar['key'];"), ); @@ -437,6 +439,7 @@ void main() { refer('bar') .index(literalString('key')) .assign(literalFalse) + // ignore: deprecated_member_use_from_same_package .assignVar('foo') .statement, equalsDart("var foo = bar['key'] = false;"), @@ -448,6 +451,7 @@ void main() { refer('bar') .index(literalTrue) .assignNullAware(literalFalse) + // ignore: deprecated_member_use_from_same_package .assignVar('foo') .statement, equalsDart('var foo = bar[true] ??= false;'), @@ -456,6 +460,7 @@ void main() { test('should emit assigning to a var', () { expect( + // ignore: deprecated_member_use_from_same_package literalTrue.assignVar('foo'), equalsDart('var foo = true'), ); @@ -463,6 +468,7 @@ void main() { test('should emit assigning to a type', () { expect( + // ignore: deprecated_member_use_from_same_package literalTrue.assignVar('foo', refer('bool')), equalsDart('bool foo = true'), ); @@ -470,6 +476,7 @@ void main() { test('should emit assigning to a final', () { expect( + // ignore: deprecated_member_use_from_same_package literalTrue.assignFinal('foo'), equalsDart('final foo = true'), ); @@ -477,6 +484,7 @@ void main() { test('should emit assigning to a const', () { expect( + // ignore: deprecated_member_use_from_same_package literalTrue.assignConst('foo'), equalsDart('const foo = true'), ); From 73399e7f0e6b83ee7314d37392bc00c7187f67f4 Mon Sep 17 00:00:00 2001 From: Saint Gabriel <53136855+chineduG@users.noreply.github.com> Date: Thu, 18 Aug 2022 00:13:35 +0100 Subject: [PATCH 207/271] Fix spelling in CHANGELOG.md (dart-lang/code_builder#361) Co-authored-by: Nate Bosch --- pkgs/code_builder/CHANGELOG.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 5cadb416c..760842308 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -8,7 +8,7 @@ * Add an ignore for a lint from the `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 which is already not visible + code where the appearance of a private name that is already not visible outside the library is confusing. * Fix the docs for `Expression.assign`, `ifNullThen`, and `assignNullAware` which had the argument and receiver flipped. @@ -361,11 +361,12 @@ class Animal extends Organism { **Major changes**: * Builders now use `built_value`, and have a more consistent, friendly API. -* Builders are now consistent - they don't any work until code is emitted. +* Builders are now consistent - they don't perform work work until code is + emitted. * It's possible to overwrite the built-in code emitting, formatting, etc by providing your own visitors. See `DartEmitter` as an example of the built-in visitor/emitter. -* Most of the expression and statement level helpers were removed; in practice +* Most of the expression and statement-level helpers were removed; in practice, they were difficult to write and maintain, and many users commonly asked for opt-out type APIs. See the `Code` example below: @@ -495,7 +496,7 @@ expect( ## 1.0.0 -First full release. At this point all changes until `2.0.0` will be backwards +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. @@ -632,7 +633,7 @@ literal(true).asAssign(reference('flag')) ## 1.0.0-alpha+7 -- Make use of new analyzer API in preparation for analyzer version 0.30. +- Make use of the new analyzer APIs in preparation for analyzer version 0.30. ## 1.0.0-alpha+6 @@ -658,13 +659,13 @@ method('main') ## 1.0.0-alpha+4 -- Add support for latest `pkg/analyzer`. +- Add support for the latest `pkg/analyzer`. ## 1.0.0-alpha+3 - BREAKING CHANGE: Added generics support to `TypeBuilder`: -`importFrom` becomes a _named_, not positional argument, and the named +`importFrom` becomes a _named_, not a positional argument, and the named argument `genericTypes` is added (`Iterable`). ```dart @@ -748,7 +749,7 @@ reference('foo').property('bar'); ## 0.1.1 -- Add concept of `Scope` and change `toAst` to support it +- Add the concept of `Scope` and change `toAst` to support it Now your entire AST tree can be scoped and import directives automatically added to a `LibraryBuilder` for you if you use From c84d641809cb831a84e6be46145b7aba76294c4b Mon Sep 17 00:00:00 2001 From: Saint Gabriel <53136855+chineduG@users.noreply.github.com> Date: Thu, 18 Aug 2022 00:13:59 +0100 Subject: [PATCH 208/271] Fix spelling in README.md (dart-lang/code_builder#360) Co-authored-by: Nate Bosch --- pkgs/code_builder/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 19241e3f2..aba672b37 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -77,7 +77,7 @@ _i2.Other doOther() {} If a feature is missing (the Dart language is always evolving) or you'd like an easier or better way to do something, consider [opening a pull request][pull]. -You can always [file an issue][issue], but generally speaking feature requests +You can always [file an issue][issue], but generally speaking, feature requests will be on a best-effort basis. > **NOTE**: Due to the evolving Dart SDK the local `dartfmt` must be used to @@ -98,8 +98,8 @@ will be on a best-effort basis. > system. Make a snapshot of the generated [`build_runner`][build_runner] build script and -run from the snapshot instead of source to avoid problems with deleted files. -These steps must be run without deleting the source files. +run from the snapshot instead of from source to avoid problems with deleted +files. These steps must be run without deleting the source files. ```bash $ dart run build_runner generate-build-script From 533ad219c28895021b8e9ed9db280fff602d3f71 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 18 Aug 2022 14:32:50 -0700 Subject: [PATCH 209/271] Add support for trailing commas in Emitter (dart-lang/code_builder#376) --- pkgs/code_builder/CHANGELOG.md | 2 ++ pkgs/code_builder/lib/src/emitter.dart | 30 +++++++++++++++---- .../lib/src/specs/expression.dart | 14 +++++++++ pkgs/code_builder/test/const_test.dart | 8 ++--- .../code_builder/test/e2e/injection_test.dart | 4 +-- pkgs/code_builder/test/specs/class_test.dart | 8 ++--- .../test/specs/code/expression_test.dart | 24 +++++++-------- pkgs/code_builder/test/specs/method_test.dart | 14 ++++----- 8 files changed, 70 insertions(+), 34 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 760842308..088e05d69 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -3,6 +3,8 @@ * Only emit `late` keyword when using null safety syntax. * Use implicit `const` when assigning to a `declareConst` variable. * Deprecate `assignVar`, `assignConst`, and `assignFinal`. +* Add trailing commas to any parameter list, argument list, or collection + literal which has more than one element. ## 4.2.0 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 66ddff1e0..078250778 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -213,12 +213,15 @@ class DartEmitter extends Object ..write(spec.name); } output.write('('); + final hasMultipleParameters = + spec.requiredParameters.length + spec.optionalParameters.length > 1; if (spec.requiredParameters.isNotEmpty) { var count = 0; for (final p in spec.requiredParameters) { count++; _visitParameter(p, output); - if (spec.requiredParameters.length != count || + if (hasMultipleParameters || + spec.requiredParameters.length != count || spec.optionalParameters.isNotEmpty) { output.write(', '); } @@ -235,7 +238,7 @@ class DartEmitter extends Object for (final p in spec.optionalParameters) { count++; _visitParameter(p, output, optional: true, named: named); - if (spec.optionalParameters.length != count) { + if (hasMultipleParameters || spec.optionalParameters.length != count) { output.write(', '); } } @@ -453,13 +456,20 @@ class DartEmitter extends Object out.write('>'); } out.write('('); + final needsTrailingComma = spec.requiredParameters.length + + spec.optionalParameters.length + + spec.namedRequiredParameters.length + + spec.namedParameters.length > + 1; visitAll(spec.requiredParameters, out, (spec) { spec.accept(this, out); }); final hasNamedParameters = spec.namedRequiredParameters.isNotEmpty || spec.namedParameters.isNotEmpty; if (spec.requiredParameters.isNotEmpty && - (spec.optionalParameters.isNotEmpty || hasNamedParameters)) { + (needsTrailingComma || + spec.optionalParameters.isNotEmpty || + hasNamedParameters)) { out.write(', '); } if (spec.optionalParameters.isNotEmpty) { @@ -467,6 +477,9 @@ class DartEmitter extends Object visitAll(spec.optionalParameters, out, (spec) { spec.accept(this, out); }); + if (needsTrailingComma) { + out.write(', '); + } out.write(']'); } else if (hasNamedParameters) { out.write('{'); @@ -487,6 +500,9 @@ class DartEmitter extends Object ..write(' ') ..write(name); }); + if (needsTrailingComma) { + out.write(', '); + } out.write('}'); } out.write(')'); @@ -526,12 +542,15 @@ class DartEmitter extends Object } visitTypeParameters(spec.types.map((r) => r.type), output); output.write('('); + final hasMultipleParameters = + spec.requiredParameters.length + spec.optionalParameters.length > 1; if (spec.requiredParameters.isNotEmpty) { var count = 0; for (final p in spec.requiredParameters) { count++; _visitParameter(p, output); - if (spec.requiredParameters.length != count || + if (hasMultipleParameters || + spec.requiredParameters.length != count || spec.optionalParameters.isNotEmpty) { output.write(', '); } @@ -548,7 +567,8 @@ class DartEmitter extends Object for (final p in spec.optionalParameters) { count++; _visitParameter(p, output, optional: true, named: named); - if (spec.optionalParameters.length != count) { + if (hasMultipleParameters || + spec.optionalParameters.length != count) { output.write(', '); } } diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index f2383b138..5400b388b 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -497,6 +497,11 @@ abstract class ExpressionEmitter implements ExpressionVisitor { ..write(': '); expression.namedArguments[name]!.accept(this, out); }); + final argumentCount = expression.positionalArguments.length + + expression.namedArguments.length; + if (argumentCount > 1) { + out.write(', '); + } return out..write(')'); }); } @@ -535,6 +540,9 @@ abstract class ExpressionEmitter implements ExpressionVisitor { visitAll(expression.values, out, (value) { _acceptLiteral(value, out); }); + if (expression.values.length > 1) { + out.write(', '); + } return out..write(']'); }); } @@ -556,6 +564,9 @@ abstract class ExpressionEmitter implements ExpressionVisitor { visitAll(expression.values, out, (value) { _acceptLiteral(value, out); }); + if (expression.values.length > 1) { + out.write(', '); + } return out..write('}'); }); } @@ -585,6 +596,9 @@ abstract class ExpressionEmitter implements ExpressionVisitor { out.write(': '); _acceptLiteral(value, out); }); + if (expression.values.length > 1) { + out.write(', '); + } return out..write('}'); }); } diff --git a/pkgs/code_builder/test/const_test.dart b/pkgs/code_builder/test/const_test.dart index 7487b001b..c4d69c61b 100644 --- a/pkgs/code_builder/test/const_test.dart +++ b/pkgs/code_builder/test/const_test.dart @@ -17,7 +17,7 @@ void main() { test('expression', () { expect(constMap, equalsDart(r''' - const {'list': [], 'duration': Duration()}''')); + const {'list': [], 'duration': Duration(), }''')); }); test('assignConst', () { @@ -25,7 +25,7 @@ void main() { // ignore: deprecated_member_use_from_same_package constMap.assignConst('constField'), equalsDart(r''' - const constField = {'list': [], 'duration': Duration()}''', + const constField = {'list': [], 'duration': Duration(), }''', DartEmitter.scoped()), ); }); @@ -34,7 +34,7 @@ void main() { expect( declareConst('constField').assign(constMap), equalsDart(r''' - const constField = {'list': [], 'duration': Duration()}''', + const constField = {'list': [], 'duration': Duration(), }''', DartEmitter.scoped()), ); }); @@ -43,7 +43,7 @@ void main() { expect( declareVar('varField').assign(constMap), equalsDart(r''' - var varField = const {'list': [], 'duration': Duration()}''', + var varField = const {'list': [], 'duration': Duration(), }''', DartEmitter.scoped())); }); diff --git a/pkgs/code_builder/test/e2e/injection_test.dart b/pkgs/code_builder/test/e2e/injection_test.dart index 50346212e..129f02cd1 100644 --- a/pkgs/code_builder/test/e2e/injection_test.dart +++ b/pkgs/code_builder/test/e2e/injection_test.dart @@ -45,7 +45,7 @@ void main() { final Module _module; @override - Thing getThing() => Thing(_module.get1(), _module.get2()); + Thing getThing() => Thing(_module.get1(), _module.get2(), ); } '''), ); @@ -59,7 +59,7 @@ void main() { final _i2.Module _module; @override - _i3.Thing getThing() => _i3.Thing(_module.get1(), _module.get2()); + _i3.Thing getThing() => _i3.Thing(_module.get1(), _module.get2(), ); } ''', DartEmitter(allocator: Allocator.simplePrefixing())), ); diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 0320b9a0e..915c7744c 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -312,7 +312,7 @@ void main() { ); }); - test('should create a class with method parameters', () { + test('should create a class with a constructor with parameters', () { expect( Class((b) => b ..name = 'Foo' @@ -328,7 +328,7 @@ void main() { ])))), equalsDart(r''' class Foo { - Foo(a, b, {c}); + Foo(a, b, {c, }); } '''), ); @@ -355,7 +355,7 @@ void main() { ])))), equalsDart(r''' class Foo { - Foo(this.a, this.b, {this.c}); + Foo(this.a, this.b, {this.c, }); } '''), ); @@ -382,7 +382,7 @@ void main() { ])))), equalsDart(r''' class Foo { - Foo(super.a, super.b, {super.c}); + Foo(super.a, super.b, {super.c, }); } '''), ); diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 648ca6de2..08e00852f 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -96,7 +96,7 @@ void main() { refer('three'): 3, refer('Map').newInstance([]): null, }), - equalsDart(r"{1: 'one', 2: two, three: 3, Map(): null}"), + equalsDart(r"{1: 'one', 2: two, three: 3, Map(): null, }"), ); }); @@ -110,7 +110,7 @@ void main() { null, refer('Map').newInstance([]) ]), - equalsDart('[[], {}, true, null, Map()]'), + equalsDart('[[], {}, true, null, Map(), ]'), ); }); @@ -125,7 +125,7 @@ void main() { null, refer('Map').newInstance([]) ]), - equalsDart('{[], {}, true, null, Map()}'), + equalsDart('{[], {}, true, null, Map(), }'), ); }); @@ -190,7 +190,7 @@ void main() { literal(2), literal(3), ]), - equalsDart('foo(1, 2, 3)'), + equalsDart('foo(1, 2, 3, )'), ); }); @@ -209,7 +209,7 @@ void main() { 'bar': literal(1), 'baz': literal(2), }), - equalsDart('foo(bar: 1, baz: 2)'), + equalsDart('foo(bar: 1, baz: 2, )'), ); }); @@ -221,7 +221,7 @@ void main() { 'bar': literal(2), 'baz': literal(3), }), - equalsDart('foo(1, bar: 2, baz: 3)'), + equalsDart('foo(1, bar: 2, baz: 3, )'), ); }); @@ -287,7 +287,7 @@ void main() { FunctionType((b) => b ..requiredParameters.add(refer('String')) ..optionalParameters.add(refer('int'))), - equalsDart('Function(String, [int])'), + equalsDart('Function(String, [int, ])'), ); }); @@ -298,7 +298,7 @@ void main() { 'x': refer('int'), 'y': refer('int'), })), - equalsDart('Function({int x, int y})'), + equalsDart('Function({int x, int y, })'), ); }); @@ -313,7 +313,7 @@ void main() { ..namedParameters.addAll({ 'y': refer('int'), })), - equalsDart('Function({required int x, int y})'), + equalsDart('Function({required int x, int y, })'), ); }); @@ -324,7 +324,7 @@ void main() { 'x': refer('int'), 'y': refer('int'), })), - equalsDart('Function({required int x, required int y})'), + equalsDart('Function({required int x, required int y, })'), ); }); @@ -373,7 +373,7 @@ void main() { literalString('foo'), Method((b) => b..body = literalTrue.code).closure, ]), - equalsDart("map.putIfAbsent('foo', () => true)"), + equalsDart("map.putIfAbsent('foo', () => true, )"), ); }); @@ -385,7 +385,7 @@ void main() { ..types.add(refer('T')) ..body = literalTrue.code).genericClosure, ]), - equalsDart("map.putIfAbsent('foo', () => true)"), + equalsDart("map.putIfAbsent('foo', () => true, )"), ); }); diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index f1d4ef724..0f2e093cc 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -173,7 +173,7 @@ void main() { ..requiredParameters.add(refer('int')) ..optionalParameters.add(refer('int'))), equalsDart(r''' - String Function(int, [int]) + String Function(int, [int, ]) '''), ); }); @@ -207,7 +207,7 @@ void main() { ..requiredParameters.add(refer('int')) ..namedParameters['named'] = refer('int')), equalsDart(r''' - String Function(int, {int named}) + String Function(int, {int named, }) '''), ); }); @@ -232,7 +232,7 @@ void main() { ..namedRequiredParameters['named'] = refer('int') ..namedParameters['optional'] = refer('int')), equalsDart(r''' - String Function({required int named, int optional}) + String Function({required int named, int optional, }) '''), ); }); @@ -347,7 +347,7 @@ void main() { ); }); - test('should create a method with a paremter', () { + test('should create a method with a parameter', () { expect( Method( (b) => b @@ -440,7 +440,7 @@ void main() { ]), ), equalsDart(r''' - foo(T t, X x); + foo(T t, X x, ); '''), ); }); @@ -471,7 +471,7 @@ void main() { ]), ), equalsDart(r''' - foo([a, b]); + foo([a, b, ]); '''), ); }); @@ -586,7 +586,7 @@ void main() { ), ), equalsDart(r''' - foo(a, {b}); + foo(a, {b, }); '''), ); }); From 37d3ff8d29604dcc966f164bbc431c4c5834eeff Mon Sep 17 00:00:00 2001 From: Dillon Nys <24740863+dnys1@users.noreply.github.com> Date: Thu, 1 Sep 2022 12:23:06 -0700 Subject: [PATCH 210/271] Add enhanced enums support (dart-lang/code_builder#358) Add support for more detailed signature and adding members in the definition of an enum. --- pkgs/code_builder/CHANGELOG.md | 3 +- pkgs/code_builder/lib/src/emitter.dart | 53 +++- pkgs/code_builder/lib/src/specs/enum.dart | 50 +++- pkgs/code_builder/lib/src/specs/enum.g.dart | 242 ++++++++++++++- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/enum_test.dart | 308 ++++++++++++++++++++ 6 files changed, 638 insertions(+), 20 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 088e05d69..6ad887996 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,6 @@ -## 4.2.1-dev +## 4.3.0-dev +* Add support for adding more implementation in `enum` classes. * Only emit `late` keyword when using null safety syntax. * Use implicit `const` when assigning to a `declareConst` variable. * Deprecate `assignVar`, `assignConst`, and `assignFinal`. diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 078250778..97d2285fe 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -688,18 +688,67 @@ class DartEmitter extends Object for (var a in spec.annotations) { visitAnnotation(a, out); } - out.writeln('enum ${spec.name} {'); + out.write('enum ${spec.name}'); + visitTypeParameters(spec.types.map((r) => r.type), out); + if (spec.mixins.isNotEmpty) { + out + ..write(' with ') + ..writeAll( + spec.mixins.map((m) => m.type.accept(this)), ', '); + } + if (spec.implements.isNotEmpty) { + out + ..write(' implements ') + ..writeAll( + spec.implements.map((m) => m.type.accept(this)), ', '); + } + out.write(' { '); for (var v in spec.values) { v.docs.forEach(out.writeln); for (var a in v.annotations) { visitAnnotation(a, out); } out.write(v.name); + if (v.constructorName != null) { + out.write('.${v.constructorName}'); + } + visitTypeParameters(v.types.map((r) => r.type), out); + final takesArguments = + v.constructorName != null || v.arguments.isNotEmpty; + if (takesArguments) { + out.write('('); + } + if (v.arguments.isNotEmpty) { + out.writeAll( + v.arguments.map((arg) => arg.accept(this)), ', '); + } + if (takesArguments) { + out.write(')'); + } if (v != spec.values.last) { out.writeln(','); + } else if (spec.constructors.isNotEmpty || + spec.fields.isNotEmpty || + spec.methods.isNotEmpty) { + out.writeln(';'); } } - out.writeln('}'); + for (var c in spec.constructors) { + visitConstructor(c, spec.name, out); + out.writeln(); + } + for (var f in spec.fields) { + visitField(f, out); + out.writeln(); + } + for (var m in spec.methods) { + visitMethod(m, out); + if (_isLambdaMethod(m)) { + out.write(';'); + } + out.writeln(); + } + out.writeln(' }'); return out; } } diff --git a/pkgs/code_builder/lib/src/specs/enum.dart b/pkgs/code_builder/lib/src/specs/enum.dart index c299f2105..632eb8fb7 100644 --- a/pkgs/code_builder/lib/src/specs/enum.dart +++ b/pkgs/code_builder/lib/src/specs/enum.dart @@ -9,13 +9,14 @@ import 'package:meta/meta.dart'; import '../../code_builder.dart'; import '../mixins/annotations.dart'; import '../mixins/dartdoc.dart'; +import '../mixins/generics.dart'; import '../visitors.dart'; part 'enum.g.dart'; @immutable abstract class Enum extends Object - with HasAnnotations, HasDartDocs + with HasAnnotations, HasDartDocs, HasGenerics implements Built, Spec { factory Enum([void Function(EnumBuilder) updates]) = _$Enum; @@ -31,6 +32,17 @@ abstract class Enum extends Object @override BuiltList get docs; + BuiltList get implements; + + BuiltList get mixins; + + @override + BuiltList get types; + + BuiltList get constructors; + BuiltList get methods; + BuiltList get fields; + @override R accept( SpecVisitor visitor, [ @@ -40,7 +52,7 @@ abstract class Enum extends Object } abstract class EnumBuilder extends Object - with HasAnnotationsBuilder, HasDartDocsBuilder + with HasAnnotationsBuilder, HasDartDocsBuilder, HasGenericsBuilder implements Builder { factory EnumBuilder() = _$EnumBuilder; @@ -55,11 +67,21 @@ abstract class EnumBuilder extends Object @override ListBuilder docs = ListBuilder(); + + ListBuilder implements = ListBuilder(); + ListBuilder mixins = ListBuilder(); + + @override + ListBuilder types = ListBuilder(); + + ListBuilder constructors = ListBuilder(); + ListBuilder methods = ListBuilder(); + ListBuilder fields = ListBuilder(); } @immutable abstract class EnumValue extends Object - with HasAnnotations, HasDartDocs + with HasAnnotations, HasDartDocs, HasGenerics implements Built { factory EnumValue([void Function(EnumValueBuilder) updates]) = _$EnumValue; @@ -72,10 +94,21 @@ abstract class EnumValue extends Object @override BuiltList get docs; + + /// The name of the constructor to target. + /// + /// If `null` uses the unnamed constructor. + String? get constructorName; + + @override + BuiltList get types; + + /// Arguments to the constructor. + BuiltList get arguments; } abstract class EnumValueBuilder extends Object - with HasAnnotationsBuilder, HasDartDocsBuilder + with HasAnnotationsBuilder, HasDartDocsBuilder, HasGenericsBuilder implements Builder { factory EnumValueBuilder() = _$EnumValueBuilder; @@ -88,4 +121,13 @@ abstract class EnumValueBuilder extends Object @override ListBuilder docs = ListBuilder(); + + /// The name of the constructor to target. + String? constructorName; + + @override + ListBuilder types = ListBuilder(); + + /// Arguments to the constructor. + ListBuilder arguments = ListBuilder(); } diff --git a/pkgs/code_builder/lib/src/specs/enum.g.dart b/pkgs/code_builder/lib/src/specs/enum.g.dart index 478f08657..5ed4e5037 100644 --- a/pkgs/code_builder/lib/src/specs/enum.g.dart +++ b/pkgs/code_builder/lib/src/specs/enum.g.dart @@ -15,6 +15,18 @@ class _$Enum extends Enum { final BuiltList annotations; @override final BuiltList docs; + @override + final BuiltList implements; + @override + final BuiltList mixins; + @override + final BuiltList types; + @override + final BuiltList constructors; + @override + final BuiltList methods; + @override + final BuiltList fields; factory _$Enum([void Function(EnumBuilder)? updates]) => (new EnumBuilder()..update(updates)).build() as _$Enum; @@ -23,12 +35,25 @@ class _$Enum extends Enum { {required this.name, required this.values, required this.annotations, - required this.docs}) + required this.docs, + required this.implements, + required this.mixins, + required this.types, + required this.constructors, + required this.methods, + required this.fields}) : super._() { BuiltValueNullFieldError.checkNotNull(name, r'Enum', 'name'); BuiltValueNullFieldError.checkNotNull(values, r'Enum', 'values'); BuiltValueNullFieldError.checkNotNull(annotations, r'Enum', 'annotations'); BuiltValueNullFieldError.checkNotNull(docs, r'Enum', 'docs'); + BuiltValueNullFieldError.checkNotNull(implements, r'Enum', 'implements'); + BuiltValueNullFieldError.checkNotNull(mixins, r'Enum', 'mixins'); + BuiltValueNullFieldError.checkNotNull(types, r'Enum', 'types'); + BuiltValueNullFieldError.checkNotNull( + constructors, r'Enum', 'constructors'); + BuiltValueNullFieldError.checkNotNull(methods, r'Enum', 'methods'); + BuiltValueNullFieldError.checkNotNull(fields, r'Enum', 'fields'); } @override @@ -45,14 +70,33 @@ class _$Enum extends Enum { name == other.name && values == other.values && annotations == other.annotations && - docs == other.docs; + docs == other.docs && + implements == other.implements && + mixins == other.mixins && + types == other.types && + constructors == other.constructors && + methods == other.methods && + fields == other.fields; } @override int get hashCode { return $jf($jc( - $jc($jc($jc(0, name.hashCode), values.hashCode), annotations.hashCode), - docs.hashCode)); + $jc( + $jc( + $jc( + $jc( + $jc( + $jc( + $jc($jc($jc(0, name.hashCode), values.hashCode), + annotations.hashCode), + docs.hashCode), + implements.hashCode), + mixins.hashCode), + types.hashCode), + constructors.hashCode), + methods.hashCode), + fields.hashCode)); } @override @@ -61,7 +105,13 @@ class _$Enum extends Enum { ..add('name', name) ..add('values', values) ..add('annotations', annotations) - ..add('docs', docs)) + ..add('docs', docs) + ..add('implements', implements) + ..add('mixins', mixins) + ..add('types', types) + ..add('constructors', constructors) + ..add('methods', methods) + ..add('fields', fields)) .toString(); } } @@ -117,6 +167,78 @@ class _$EnumBuilder extends EnumBuilder { super.docs = docs; } + @override + ListBuilder get implements { + _$this; + return super.implements; + } + + @override + set implements(ListBuilder implements) { + _$this; + super.implements = implements; + } + + @override + ListBuilder get mixins { + _$this; + return super.mixins; + } + + @override + set mixins(ListBuilder mixins) { + _$this; + super.mixins = mixins; + } + + @override + ListBuilder get types { + _$this; + return super.types; + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + + @override + ListBuilder get constructors { + _$this; + return super.constructors; + } + + @override + set constructors(ListBuilder constructors) { + _$this; + super.constructors = constructors; + } + + @override + ListBuilder get methods { + _$this; + return super.methods; + } + + @override + set methods(ListBuilder methods) { + _$this; + super.methods = methods; + } + + @override + ListBuilder get fields { + _$this; + return super.fields; + } + + @override + set fields(ListBuilder fields) { + _$this; + super.fields = fields; + } + _$EnumBuilder() : super._(); EnumBuilder get _$this { @@ -126,6 +248,12 @@ class _$EnumBuilder extends EnumBuilder { super.values = $v.values.toBuilder(); super.annotations = $v.annotations.toBuilder(); super.docs = $v.docs.toBuilder(); + super.implements = $v.implements.toBuilder(); + super.mixins = $v.mixins.toBuilder(); + super.types = $v.types.toBuilder(); + super.constructors = $v.constructors.toBuilder(); + super.methods = $v.methods.toBuilder(); + super.fields = $v.fields.toBuilder(); _$v = null; } return this; @@ -154,7 +282,13 @@ class _$EnumBuilder extends EnumBuilder { BuiltValueNullFieldError.checkNotNull(name, r'Enum', 'name'), values: values.build(), annotations: annotations.build(), - docs: docs.build()); + docs: docs.build(), + implements: implements.build(), + mixins: mixins.build(), + types: types.build(), + constructors: constructors.build(), + methods: methods.build(), + fields: fields.build()); } catch (_) { late String _$failedField; try { @@ -164,6 +298,18 @@ class _$EnumBuilder extends EnumBuilder { annotations.build(); _$failedField = 'docs'; docs.build(); + _$failedField = 'implements'; + implements.build(); + _$failedField = 'mixins'; + mixins.build(); + _$failedField = 'types'; + types.build(); + _$failedField = 'constructors'; + constructors.build(); + _$failedField = 'methods'; + methods.build(); + _$failedField = 'fields'; + fields.build(); } catch (e) { throw new BuiltValueNestedFieldError( r'Enum', _$failedField, e.toString()); @@ -182,17 +328,30 @@ class _$EnumValue extends EnumValue { final BuiltList annotations; @override final BuiltList docs; + @override + final String? constructorName; + @override + final BuiltList types; + @override + final BuiltList arguments; factory _$EnumValue([void Function(EnumValueBuilder)? updates]) => (new EnumValueBuilder()..update(updates)).build() as _$EnumValue; _$EnumValue._( - {required this.name, required this.annotations, required this.docs}) + {required this.name, + required this.annotations, + required this.docs, + this.constructorName, + required this.types, + required this.arguments}) : super._() { BuiltValueNullFieldError.checkNotNull(name, r'EnumValue', 'name'); BuiltValueNullFieldError.checkNotNull( annotations, r'EnumValue', 'annotations'); BuiltValueNullFieldError.checkNotNull(docs, r'EnumValue', 'docs'); + BuiltValueNullFieldError.checkNotNull(types, r'EnumValue', 'types'); + BuiltValueNullFieldError.checkNotNull(arguments, r'EnumValue', 'arguments'); } @override @@ -208,13 +367,22 @@ class _$EnumValue extends EnumValue { return other is EnumValue && name == other.name && annotations == other.annotations && - docs == other.docs; + docs == other.docs && + constructorName == other.constructorName && + types == other.types && + arguments == other.arguments; } @override int get hashCode { - return $jf( - $jc($jc($jc(0, name.hashCode), annotations.hashCode), docs.hashCode)); + return $jf($jc( + $jc( + $jc( + $jc($jc($jc(0, name.hashCode), annotations.hashCode), + docs.hashCode), + constructorName.hashCode), + types.hashCode), + arguments.hashCode)); } @override @@ -222,7 +390,10 @@ class _$EnumValue extends EnumValue { return (newBuiltValueToStringHelper(r'EnumValue') ..add('name', name) ..add('annotations', annotations) - ..add('docs', docs)) + ..add('docs', docs) + ..add('constructorName', constructorName) + ..add('types', types) + ..add('arguments', arguments)) .toString(); } } @@ -266,6 +437,42 @@ class _$EnumValueBuilder extends EnumValueBuilder { super.docs = docs; } + @override + String? get constructorName { + _$this; + return super.constructorName; + } + + @override + set constructorName(String? constructorName) { + _$this; + super.constructorName = constructorName; + } + + @override + ListBuilder get types { + _$this; + return super.types; + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + + @override + ListBuilder get arguments { + _$this; + return super.arguments; + } + + @override + set arguments(ListBuilder arguments) { + _$this; + super.arguments = arguments; + } + _$EnumValueBuilder() : super._(); EnumValueBuilder get _$this { @@ -274,6 +481,9 @@ class _$EnumValueBuilder extends EnumValueBuilder { super.name = $v.name; super.annotations = $v.annotations.toBuilder(); super.docs = $v.docs.toBuilder(); + super.constructorName = $v.constructorName; + super.types = $v.types.toBuilder(); + super.arguments = $v.arguments.toBuilder(); _$v = null; } return this; @@ -301,7 +511,10 @@ class _$EnumValueBuilder extends EnumValueBuilder { name: BuiltValueNullFieldError.checkNotNull( name, r'EnumValue', 'name'), annotations: annotations.build(), - docs: docs.build()); + docs: docs.build(), + constructorName: constructorName, + types: types.build(), + arguments: arguments.build()); } catch (_) { late String _$failedField; try { @@ -309,6 +522,11 @@ class _$EnumValueBuilder extends EnumValueBuilder { annotations.build(); _$failedField = 'docs'; docs.build(); + + _$failedField = 'types'; + types.build(); + _$failedField = 'arguments'; + arguments.build(); } catch (e) { throw new BuiltValueNestedFieldError( r'EnumValue', _$failedField, e.toString()); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index c3aeba1ea..0f686812f 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.2.1-dev +version: 4.3.0-dev description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/enum_test.dart b/pkgs/code_builder/test/specs/enum_test.dart index d9ee402bd..420f994fe 100644 --- a/pkgs/code_builder/test/specs/enum_test.dart +++ b/pkgs/code_builder/test/specs/enum_test.dart @@ -73,4 +73,312 @@ void main() { } ''')); }); + + test('should create an enum which mixes in and implements specs', () { + final myEnum = Enum((b) => b + ..name = 'MyEnum' + ..implements.addAll(const [ + Reference('InterfaceA'), + Reference('InterfaceB'), + ]) + ..mixins.addAll(const [ + Reference('Mixin1'), + Reference('Mixin2'), + ]) + ..values.addAll([ + EnumValue((v) => v..name = 'a'), + EnumValue((v) => v..name = 'b'), + EnumValue((v) => v..name = 'c'), + ])); + expect(myEnum, equalsDart(''' + enum MyEnum with Mixin1, Mixin2 implements InterfaceA, InterfaceB { + a, + b, + c + } + ''')); + }); + + test('should create an enum which targets a named constructor', () { + final myEnum = Enum((b) => b + ..name = 'MyEnum' + ..constructors.addAll([ + Constructor((c) => c..constant = true), + Constructor((c) => c + ..constant = true + ..name = 'named'), + ]) + ..values.addAll([ + EnumValue((v) => v..name = 'a'), + EnumValue((v) => v + ..name = 'b' + ..constructorName = 'named'), + EnumValue((v) => v..name = 'c'), + ])); + expect(myEnum, equalsDart(''' + enum MyEnum { + a, + b.named(), + c; + + const MyEnum(); + + const MyEnum.named(); + } + ''')); + }); + + test('should create an enum which targets a redirecting constructor', () { + final myEnum = Enum((b) => b + ..name = 'MyEnum' + ..constructors.addAll([ + Constructor((c) => c..constant = true), + Constructor((c) => c + ..constant = true + ..name = 'redirect' + ..initializers.add( + refer('this').call([]).code, + )), + ]) + ..values.addAll([ + EnumValue((v) => v..name = 'a'), + EnumValue((v) => v + ..name = 'b' + ..constructorName = 'redirect'), + EnumValue((v) => v..name = 'c'), + ])); + expect(myEnum, equalsDart(''' + enum MyEnum { + a, + b.redirect(), + c; + + const MyEnum(); + + const MyEnum.redirect() : this(); + } + ''')); + }); + + test('should create an enum which targets a redirecting factory constructor', + () { + final myEnum = Enum((b) => b + ..name = 'MyEnum' + ..constructors.addAll([ + Constructor((c) => c..constant = true), + Constructor((c) => c + ..constant = true + ..factory = true + ..name = 'redirect' + ..redirect = refer('MyOtherEnum.named') + ..optionalParameters.addAll([ + Parameter((p) => p + ..type = refer('int?') + ..name = 'myInt'), + Parameter((p) => p + ..type = refer('String?') + ..name = 'myString') + ])) + ]) + ..values.addAll([ + EnumValue((v) => v..name = 'a'), + EnumValue((v) => v + ..name = 'b' + ..constructorName = 'redirect' + ..arguments.addAll([ + literalNum(1), + literalString('abc'), + ])), + EnumValue((v) => v + ..name = 'c' + ..constructorName = 'redirect'), + ])); + expect(myEnum, equalsDart(''' + enum MyEnum { + a, + b.redirect(1, 'abc'), + c.redirect(); + + const MyEnum(); + + const factory MyEnum.redirect([ + int? myInt, + String? myString, + ]) = MyOtherEnum.named; + } + ''')); + }); + + test('should create an enum which targets an unnamed constructor', () { + final myEnum = Enum((b) => b + ..name = 'MyEnum' + ..constructors.add(Constructor((c) => c + ..constant = true + ..optionalParameters.addAll([ + Parameter((p) => p + ..toThis = true + ..name = 'myInt'), + Parameter((p) => p + ..toThis = true + ..name = 'myString') + ]))) + ..fields.addAll([ + Field((f) => f + ..modifier = FieldModifier.final$ + ..type = refer('int?') + ..name = 'myInt'), + Field((f) => f + ..modifier = FieldModifier.final$ + ..type = refer('String?') + ..name = 'myString') + ]) + ..values.addAll([ + EnumValue((v) => v..name = 'a'), + EnumValue((v) => v + ..name = 'b' + ..arguments.addAll([ + literalNum(1), + literalString('abc'), + ])), + EnumValue((v) => v..name = 'c'), + ])); + expect(myEnum, equalsDart(''' + enum MyEnum { + a, + b(1, 'abc'), + c; + + const MyEnum([ + this.myInt, + this.myString, + ]); + + final int? myInt; + + final String? myString; + } + ''')); + }); + + test('should create an enum with generics', () { + final myEnum = Enum((b) => b + ..name = 'MyEnum' + ..types.add(const Reference('T')) + ..constructors.add(Constructor((c) => c + ..constant = true + ..requiredParameters.add(Parameter((p) => p + ..toThis = true + ..name = 'value')))) + ..fields.add( + Field((f) => f + ..modifier = FieldModifier.final$ + ..type = refer('T') + ..name = 'value'), + ) + ..values.addAll([ + EnumValue((v) => v + ..name = 'a' + ..types.add(const Reference('int')) + ..arguments.add(literalNum(123))), + EnumValue((v) => v + ..name = 'b' + ..types.add(const Reference('String')) + ..arguments.add(literalString('abc'))), + EnumValue((v) => v + ..name = 'c' + ..types.add(const Reference('MyEnum')) + ..arguments.add(refer('MyEnum').property('a'))), + ])); + expect(myEnum, equalsDart(''' + enum MyEnum { + a(123), + b('abc'), + c(MyEnum.a); + + const MyEnum(this.value); + + final T value; + } + ''')); + }); + + test('should create an enum with fields', () { + final myEnum = Enum((b) => b + ..name = 'MyEnum' + ..constructors.add(Constructor((c) => c + ..constant = true + ..optionalParameters.add(Parameter((p) => p + ..toThis = true + ..name = 'myInt')))) + ..fields.addAll([ + Field((f) => f + ..modifier = FieldModifier.final$ + ..type = refer('int?') + ..name = 'myInt'), + Field((f) => f + ..static = true + ..modifier = FieldModifier.constant + ..type = refer('String') + ..name = 'myString' + ..assignment = literalString('abc').code), + ]) + ..values.addAll([ + EnumValue((v) => v..name = 'a'), + EnumValue((v) => v..name = 'b'), + EnumValue((v) => v..name = 'c'), + ])); + expect(myEnum, equalsDart(''' + enum MyEnum { + a, + b, + c; + + const MyEnum([this.myInt]); + + final int? myInt; + + static const String myString = 'abc'; + } + ''')); + }); + + test('should create an enum with methods', () { + final myEnum = Enum((b) => b + ..name = 'MyEnum' + ..methods.addAll([ + Method((m) => m + ..returns = refer('int') + ..type = MethodType.getter + ..name = 'myInt' + ..body = literalNum(123).code), + Method((m) => m + ..returns = refer('Iterable') + ..name = 'myStrings' + ..modifier = MethodModifier.syncStar + ..body = Block.of(const [ + Code("yield 'a';"), + Code("yield 'b';"), + Code("yield 'c';"), + ])) + ]) + ..values.addAll([ + EnumValue((v) => v..name = 'a'), + EnumValue((v) => v..name = 'b'), + EnumValue((v) => v..name = 'c'), + ])); + expect(myEnum, equalsDart(''' + enum MyEnum { + a, + b, + c; + + int get myInt => 123; + Iterable myStrings() sync* { + yield 'a'; + yield 'b'; + yield 'c'; + } + } + ''')); + }); } From 4e9e1ad84fa07791d0cfd0a012330c8dad5d65ce Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 14 Sep 2022 09:48:33 -0700 Subject: [PATCH 211/271] Bump to 4.3.0 (dart-lang/code_builder#377) --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 6ad887996..4e07b83e4 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 4.3.0-dev +## 4.3.0 * Add support for adding more implementation in `enum` classes. * Only emit `late` keyword when using null safety syntax. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 0f686812f..cfb77c69a 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.3.0-dev +version: 4.3.0 description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder From 3336fb0301433ea12f5533a15b7f0d7373eea13d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Oct 2022 11:05:07 -0700 Subject: [PATCH 212/271] Update pkg:lints, add dependabot, update CI actions (dart-lang/code_builder#379) --- pkgs/code_builder/.github/dependabot.yml | 10 ++++ .../.github/workflows/test-package.yml | 8 +-- pkgs/code_builder/CHANGELOG.md | 2 + pkgs/code_builder/analysis_options.yaml | 57 ++++++------------- pkgs/code_builder/lib/src/matchers.dart | 6 +- pkgs/code_builder/pubspec.yaml | 4 +- 6 files changed, 39 insertions(+), 48 deletions(-) create mode 100644 pkgs/code_builder/.github/dependabot.yml diff --git a/pkgs/code_builder/.github/dependabot.yml b/pkgs/code_builder/.github/dependabot.yml new file mode 100644 index 000000000..71cdeea30 --- /dev/null +++ b/pkgs/code_builder/.github/dependabot.yml @@ -0,0 +1,10 @@ +# Set update schedule for GitHub Actions +# See https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot + +version: 2 +updates: + +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 52cb01c7f..b40c64178 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -45,8 +45,8 @@ jobs: os: [ubuntu-latest] sdk: [2.17.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 4e07b83e4..dfafdae8f 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,5 @@ +## 4.3.1-dev + ## 4.3.0 * Add support for adding more implementation in `enum` classes. diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml index bf0f0b696..9d6246a28 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/analysis_options.yaml @@ -1,67 +1,46 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false - implicit-dynamic: false + language: + strict-casts: true + strict-inference: true + strict-raw-types: true linter: rules: - # Error Rules - - comment_references - - control_flow_in_finally - - empty_statements - - hash_and_equals - - iterable_contains_unrelated_type - - list_remove_unrelated_type - - no_adjacent_strings_in_list - - test_types_in_equals - - throw_in_finally - - # Style Rules + - always_declare_return_types - avoid_catching_errors - avoid_private_typedef_functions - avoid_redundant_argument_values - - avoid_renaming_method_parameters - - avoid_returning_null_for_void - avoid_unused_constructor_parameters - - await_only_futures - - camel_case_types + - cancel_subscriptions - cascade_invocations - - constant_identifier_names + - comment_references - directives_ordering - - file_names - - implementation_imports - join_return_with_assignment - lines_longer_than_80_chars + - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings + - no_adjacent_strings_in_list - no_runtimeType_toString - - non_constant_identifier_names + - omit_local_variable_types - only_throw_errors - - package_names - - package_prefixed_library_names + - package_api_docs - prefer_asserts_in_initializer_lists - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - - prefer_function_declarations_over_variables - - prefer_initializing_formals - - prefer_inlined_adds - - prefer_interpolation_to_compose_strings - - prefer_is_not_operator - - prefer_null_aware_operators - prefer_relative_imports - - prefer_typing_uninitialized_variables - - prefer_void_to_null - - provide_deprecation_message + - prefer_single_quotes - sort_pub_dependencies - - unnecessary_brace_in_string_interps + - test_types_in_equals + - throw_in_finally + - type_annotate_public_apis + - unawaited_futures + - unnecessary_await_in_return - unnecessary_lambdas - - unnecessary_null_aware_assignments - - unnecessary_overrides - unnecessary_parenthesis - unnecessary_statements - - unnecessary_string_interpolations - use_string_buffers - - void_checks + - use_super_parameters diff --git a/pkgs/code_builder/lib/src/matchers.dart b/pkgs/code_builder/lib/src/matchers.dart index 11d3d6d73..0cdf73997 100644 --- a/pkgs/code_builder/lib/src/matchers.dart +++ b/pkgs/code_builder/lib/src/matchers.dart @@ -55,8 +55,8 @@ class EqualsDart extends Matcher { Description describeMismatch( covariant Spec item, Description mismatchDescription, - matchState, - verbose, + Map matchState, + bool verbose, ) { final actualSource = _dart(item, _emitter); return equals(_expectedSource).describeMismatch( @@ -68,6 +68,6 @@ class EqualsDart extends Matcher { } @override - bool matches(covariant Spec item, matchState) => + bool matches(covariant Spec item, Object? matchState) => _dart(item, _emitter) == _expectedSource; } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index cfb77c69a..d24b16582 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.3.0 +version: 4.3.1-dev description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder @@ -19,6 +19,6 @@ dev_dependencies: build_runner: ^2.0.3 built_value_generator: ^8.0.0 dart_style: ^2.0.0 - lints: ^1.0.0 + lints: ^2.0.0 source_gen: ^1.0.0 test: ^1.16.0 From c351c1085376c92c4b74f9cec22461544727601b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 1 Dec 2022 09:47:15 -0800 Subject: [PATCH 213/271] Mention imports in the DartEmitter docs (dart-lang/code_builder#380) This has come up as a point of confusion a few times - by default a `DartEmitter` will not emit any imports. Call out imports in the constructor doc comment. --- pkgs/code_builder/CHANGELOG.md | 3 +++ pkgs/code_builder/lib/src/emitter.dart | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index dfafdae8f..3cb573045 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,8 @@ ## 4.3.1-dev +* Mention how the `allocator` argument relates to imports in the `DartEmitter` + constructor doc. + ## 4.3.0 * Add support for adding more implementation in `enum` classes. diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 97d2285fe..a416b57b2 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -70,7 +70,9 @@ class DartEmitter extends Object /// Creates a new instance of [DartEmitter]. /// - /// May specify an [Allocator] to use for symbols, otherwise uses a no-op. + /// 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, From f950d0eea8035e5a3fd603348f50d9dfc0c8e67b Mon Sep 17 00:00:00 2001 From: Eric Seidel Date: Tue, 6 Dec 2022 14:17:58 -0800 Subject: [PATCH 214/271] Add an example of generating an anonymous closure (dart-lang/code_builder#384) This fixes https://github.com/dart-lang/code_builder/issues/381. --- pkgs/code_builder/test/specs/method_test.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 0f2e093cc..297afeb42 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -590,4 +590,19 @@ void main() { '''), ); }); + + test('should create a method as a closure', () { + expect( + Method( + (b) => b + ..requiredParameters.add( + Parameter((b) => b..name = 'a'), + ) + ..body = const Code(''), + ).closure, + equalsDart(r''' + (a) { } + '''), + ); + }); } From 8aff5ab05a468b1e2f42898235e44dfce1302566 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 14 Dec 2022 07:31:09 -0800 Subject: [PATCH 215/271] Update README.md (dart-lang/code_builder#388) --- pkgs/code_builder/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index aba672b37..9628b0358 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -1,5 +1,6 @@ +[![Dart CI](https://github.com/dart-lang/code_builder/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/code_builder/actions/workflows/test-package.yml) [![Pub package](https://img.shields.io/pub/v/code_builder.svg)](https://pub.dev/packages/code_builder) -[![Build Status](https://github.com/dart-lang/code_builder/workflows/Dart%20CI/badge.svg?branch=master)](https://github.com/dart-lang/code_builder/actions?query=workflow%3A%22Dart+CI%22+branch%3Amaster) +[![package publisher](https://img.shields.io/pub/publisher/code_builder.svg)](https://pub.dev/packages/code_builder/publisher) [![Gitter chat](https://badges.gitter.im/dart-lang/build.svg)](https://gitter.im/dart-lang/build) A fluent, builder-based library for generating valid Dart code. From 0baea79655e4b3da0a4ba12c2a6ad4b4f2cd7aa4 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 16 Dec 2022 09:32:18 -0800 Subject: [PATCH 216/271] add support for emitting typedefs (dart-lang/code_builder#387) * add support for emittig typedefs * Apply suggestions from code review suggestions from code review Co-authored-by: Nate Bosch Co-authored-by: Nate Bosch --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/README.md | 2 +- pkgs/code_builder/lib/code_builder.dart | 1 + pkgs/code_builder/lib/src/emitter.dart | 14 ++ pkgs/code_builder/lib/src/specs/typedef.dart | 57 ++++++ .../code_builder/lib/src/specs/typedef.g.dart | 179 ++++++++++++++++++ pkgs/code_builder/lib/src/visitors.dart | 3 + pkgs/code_builder/test/specs/method_test.dart | 24 +++ 8 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 pkgs/code_builder/lib/src/specs/typedef.dart create mode 100644 pkgs/code_builder/lib/src/specs/typedef.g.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 3cb573045..a6f2304b7 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -2,6 +2,7 @@ * Mention how the `allocator` argument relates to imports in the `DartEmitter` constructor doc. +* Add support for emitting typedefs. ## 4.3.0 diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 9628b0358..9ee994bb7 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -85,7 +85,7 @@ will be on a best-effort basis. > format this repository. You can run it simply from the command-line: > > ```sh -> $ pub run dart_style:format -w . +> $ dart pub run dart_style:format -w . > ``` [wiki]: https://github.com/dart-lang/code_builder/wiki diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index b3ccb326c..0f7a7baca 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -57,3 +57,4 @@ export 'src/specs/mixin.dart' show Mixin, MixinBuilder; export 'src/specs/reference.dart' show refer, Reference; export 'src/specs/type_function.dart' show FunctionType, FunctionTypeBuilder; export 'src/specs/type_reference.dart' show TypeReference, TypeReferenceBuilder; +export 'src/specs/typedef.dart' show TypeDef, TypeDefBuilder; diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index a416b57b2..eb4d32314 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -18,6 +18,7 @@ import 'specs/mixin.dart'; import 'specs/reference.dart'; import 'specs/type_function.dart'; import 'specs/type_reference.dart'; +import 'specs/typedef.dart'; import 'visitors.dart'; /// Helper method improving on [StringSink.writeAll]. @@ -514,6 +515,19 @@ class DartEmitter extends Object return out; } + @override + StringSink visitTypeDef(TypeDef spec, [StringSink? output]) { + final out = output ??= StringBuffer(); + spec.docs.forEach(out.writeln); + for (var a in spec.annotations) { + visitAnnotation(a, out); + } + out.write('typedef ${spec.name} = '); + spec.definition.accept(this, out); + out.writeln(';'); + return out; + } + @override StringSink visitMethod(Method spec, [StringSink? output]) { output ??= StringBuffer(); diff --git a/pkgs/code_builder/lib/src/specs/typedef.dart b/pkgs/code_builder/lib/src/specs/typedef.dart new file mode 100644 index 000000000..1c305ef8a --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/typedef.dart @@ -0,0 +1,57 @@ +// Copyright (c) 2022, 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:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../mixins/annotations.dart'; +import '../mixins/dartdoc.dart'; +import '../visitors.dart'; +import 'expression.dart'; + +part 'typedef.g.dart'; + +@immutable +abstract class TypeDef extends Object + with HasAnnotations, HasDartDocs + implements Built, Spec { + factory TypeDef([void Function(TypeDefBuilder)? updates]) = _$TypeDef; + + TypeDef._(); + + /// Name of the typedef. + String get name; + + /// The right hand side of the typedef. + /// + /// Typically a reference to a type, or a Function type. + Expression get definition; + + @override + R accept( + SpecVisitor visitor, [ + R? context, + ]) => + visitor.visitTypeDef(this, context); +} + +abstract class TypeDefBuilder extends Object + with HasAnnotationsBuilder, HasDartDocsBuilder + implements Builder { + factory TypeDefBuilder() = _$TypeDefBuilder; + + TypeDefBuilder._(); + + @override + ListBuilder annotations = ListBuilder(); + + @override + ListBuilder docs = ListBuilder(); + + String? name; + + Expression? definition; +} diff --git a/pkgs/code_builder/lib/src/specs/typedef.g.dart b/pkgs/code_builder/lib/src/specs/typedef.g.dart new file mode 100644 index 000000000..f884376e5 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/typedef.g.dart @@ -0,0 +1,179 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'typedef.dart'; + +// ************************************************************************** +// BuiltValueGenerator +// ************************************************************************** + +class _$TypeDef extends TypeDef { + @override + final String name; + @override + final Expression definition; + @override + final BuiltList annotations; + @override + final BuiltList docs; + + factory _$TypeDef([void Function(TypeDefBuilder)? updates]) => + (new TypeDefBuilder()..update(updates)).build() as _$TypeDef; + + _$TypeDef._( + {required this.name, + required this.definition, + required this.annotations, + required this.docs}) + : super._() { + BuiltValueNullFieldError.checkNotNull(name, r'TypeDef', 'name'); + BuiltValueNullFieldError.checkNotNull(definition, r'TypeDef', 'definition'); + BuiltValueNullFieldError.checkNotNull( + annotations, r'TypeDef', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'TypeDef', 'docs'); + } + + @override + TypeDef rebuild(void Function(TypeDefBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + _$TypeDefBuilder toBuilder() => new _$TypeDefBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is TypeDef && + name == other.name && + definition == other.definition && + annotations == other.annotations && + docs == other.docs; + } + + @override + int get hashCode { + return $jf($jc( + $jc($jc($jc(0, name.hashCode), definition.hashCode), + annotations.hashCode), + docs.hashCode)); + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'TypeDef') + ..add('name', name) + ..add('definition', definition) + ..add('annotations', annotations) + ..add('docs', docs)) + .toString(); + } +} + +class _$TypeDefBuilder extends TypeDefBuilder { + _$TypeDef? _$v; + + @override + String? get name { + _$this; + return super.name; + } + + @override + set name(String? name) { + _$this; + super.name = name; + } + + @override + Expression? get definition { + _$this; + return super.definition; + } + + @override + set definition(Expression? definition) { + _$this; + super.definition = definition; + } + + @override + ListBuilder get annotations { + _$this; + return super.annotations; + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs; + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + _$TypeDefBuilder() : super._(); + + TypeDefBuilder get _$this { + final $v = _$v; + if ($v != null) { + super.name = $v.name; + super.definition = $v.definition; + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(TypeDef other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$TypeDef; + } + + @override + void update(void Function(TypeDefBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + TypeDef build() => _build(); + + _$TypeDef _build() { + _$TypeDef _$result; + try { + _$result = _$v ?? + new _$TypeDef._( + name: BuiltValueNullFieldError.checkNotNull( + name, r'TypeDef', 'name'), + definition: BuiltValueNullFieldError.checkNotNull( + definition, r'TypeDef', 'definition'), + annotations: annotations.build(), + docs: docs.build()); + } catch (_) { + late String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + r'TypeDef', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 4d3ff3d04..5defdbd6c 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -18,6 +18,7 @@ import 'specs/mixin.dart'; import 'specs/reference.dart'; import 'specs/type_function.dart'; import 'specs/type_reference.dart'; +import 'specs/typedef.dart'; @optionalTypeArgs abstract class SpecVisitor { @@ -43,6 +44,8 @@ abstract class SpecVisitor { T visitFunctionType(FunctionType spec, [T? context]); + T visitTypeDef(TypeDef spec, [T? context]); + T visitMethod(Method spec, [T? context]); T visitReference(Reference spec, [T? context]); diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 297afeb42..914a54a92 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -237,6 +237,30 @@ void main() { ); }); + test('should create a typedef to a reference', () { + expect( + TypeDef((b) => b + ..name = 'i32' + ..definition = const Reference('int')), + equalsDart(r''' + typedef i32 = int; + '''), + ); + }); + + test('should create a typedef to a function type', () { + expect( + TypeDef((b) => b + ..name = 'MyMapper' + ..definition = FunctionType((b) => b + ..returnType = refer('String') + ..optionalParameters.add(refer('int')))), + equalsDart(r''' + typedef MyMapper = String Function([int]); + '''), + ); + }); + test('should create a method with a nested function type return type', () { expect( Method((b) => b From 1c744041591d5aeb633e9641e9cfb7e47682ba4c Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 19 Dec 2022 15:32:31 -0800 Subject: [PATCH 217/271] add support for ignore_for_file comments (dart-lang/code_builder#389) * add support for ignore_for_file comments * review comments --- pkgs/code_builder/CHANGELOG.md | 2 + pkgs/code_builder/lib/src/emitter.dart | 20 +++++ pkgs/code_builder/lib/src/specs/library.dart | 8 ++ .../code_builder/lib/src/specs/library.g.dart | 53 +++++++++++- .../code_builder/test/specs/library_test.dart | 80 +++++++++++++++++++ 5 files changed, 161 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index a6f2304b7..78feaa0d2 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -3,6 +3,8 @@ * Mention how the `allocator` argument relates to imports in the `DartEmitter` constructor doc. * Add support for emitting typedefs. +* Add support for emitting leading line comments for libraries. +* Add support for emitting `ignore_for_file` analyzer directive comments. ## 4.3.0 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index eb4d32314..18c822917 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -398,6 +398,26 @@ class DartEmitter extends Object @override StringSink visitLibrary(Library spec, [StringSink? output]) { output ??= StringBuffer(); + + if (spec.comments.isNotEmpty) { + spec.comments.map((line) => '// $line').forEach(output.writeln); + output.writeln(); + } + + if (spec.ignoreForFile.isNotEmpty) { + final ignores = spec.ignoreForFile.toList()..sort(); + final lines = ['// ignore_for_file: ${ignores.first}']; + for (var ignore in ignores.skip(1)) { + if (lines.last.length + 2 + ignore.length > 80) { + lines.add('// ignore_for_file: $ignore'); + } else { + lines[lines.length - 1] = '${lines.last}, $ignore'; + } + } + lines.forEach(output.writeln); + output.writeln(); + } + // Process the body first in order to prime the allocators. final body = StringBuffer(); for (final spec in spec.body) { diff --git a/pkgs/code_builder/lib/src/specs/library.dart b/pkgs/code_builder/lib/src/specs/library.dart index c007c49d4..0e3d7f3f8 100644 --- a/pkgs/code_builder/lib/src/specs/library.dart +++ b/pkgs/code_builder/lib/src/specs/library.dart @@ -27,6 +27,12 @@ abstract class Library BuiltList get directives; BuiltList get body; + /// Line comments to place at the start of the library. + BuiltList get comments; + + /// A list of analysis issues to ignore (`ignore_for_file: ...`). + BuiltList get ignoreForFile; + /// Name of the library. /// /// May be `null` when no [annotations] are specified. @@ -52,5 +58,7 @@ abstract class LibraryBuilder ListBuilder body = ListBuilder(); ListBuilder directives = ListBuilder(); + ListBuilder comments = ListBuilder(); + ListBuilder ignoreForFile = ListBuilder(); String? name; } diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index ec67eaea2..f4451ba78 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -14,6 +14,10 @@ class _$Library extends Library { @override final BuiltList body; @override + final BuiltList comments; + @override + final BuiltList ignoreForFile; + @override final String? name; factory _$Library([void Function(LibraryBuilder)? updates]) => @@ -23,12 +27,17 @@ class _$Library extends Library { {required this.annotations, required this.directives, required this.body, + required this.comments, + required this.ignoreForFile, this.name}) : super._() { BuiltValueNullFieldError.checkNotNull( annotations, r'Library', 'annotations'); BuiltValueNullFieldError.checkNotNull(directives, r'Library', 'directives'); BuiltValueNullFieldError.checkNotNull(body, r'Library', 'body'); + BuiltValueNullFieldError.checkNotNull(comments, r'Library', 'comments'); + BuiltValueNullFieldError.checkNotNull( + ignoreForFile, r'Library', 'ignoreForFile'); } @override @@ -45,14 +54,20 @@ class _$Library extends Library { annotations == other.annotations && directives == other.directives && body == other.body && + comments == other.comments && + ignoreForFile == other.ignoreForFile && name == other.name; } @override int get hashCode { return $jf($jc( - $jc($jc($jc(0, annotations.hashCode), directives.hashCode), - body.hashCode), + $jc( + $jc( + $jc($jc($jc(0, annotations.hashCode), directives.hashCode), + body.hashCode), + comments.hashCode), + ignoreForFile.hashCode), name.hashCode)); } @@ -62,6 +77,8 @@ class _$Library extends Library { ..add('annotations', annotations) ..add('directives', directives) ..add('body', body) + ..add('comments', comments) + ..add('ignoreForFile', ignoreForFile) ..add('name', name)) .toString(); } @@ -106,6 +123,30 @@ class _$LibraryBuilder extends LibraryBuilder { super.body = body; } + @override + ListBuilder get comments { + _$this; + return super.comments; + } + + @override + set comments(ListBuilder comments) { + _$this; + super.comments = comments; + } + + @override + ListBuilder get ignoreForFile { + _$this; + return super.ignoreForFile; + } + + @override + set ignoreForFile(ListBuilder ignoreForFile) { + _$this; + super.ignoreForFile = ignoreForFile; + } + @override String? get name { _$this; @@ -126,6 +167,8 @@ class _$LibraryBuilder extends LibraryBuilder { super.annotations = $v.annotations.toBuilder(); super.directives = $v.directives.toBuilder(); super.body = $v.body.toBuilder(); + super.comments = $v.comments.toBuilder(); + super.ignoreForFile = $v.ignoreForFile.toBuilder(); super.name = $v.name; _$v = null; } @@ -154,6 +197,8 @@ class _$LibraryBuilder extends LibraryBuilder { annotations: annotations.build(), directives: directives.build(), body: body.build(), + comments: comments.build(), + ignoreForFile: ignoreForFile.build(), name: name); } catch (_) { late String _$failedField; @@ -164,6 +209,10 @@ class _$LibraryBuilder extends LibraryBuilder { directives.build(); _$failedField = 'body'; body.build(); + _$failedField = 'comments'; + comments.build(); + _$failedField = 'ignoreForFile'; + ignoreForFile.build(); } catch (e) { throw new BuiltValueNestedFieldError( r'Library', _$failedField, e.toString()); diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index dd74a158c..3c5502ec7 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -13,6 +13,86 @@ void main() { group('File', () { final $LinkedHashMap = refer('LinkedHashMap', 'dart:collection'); + test('should emit a source file with leading line comments', () { + expect( + Library( + (b) => b + ..comments.add('Generated by foo.') + ..body.add( + Class((b) => b..name = 'Foo'), + ), + ), + equalsDart(r''' + // Generated by foo. + + class Foo { } + ''', DartEmitter(allocator: Allocator())), + ); + }); + + test('should emit a source file with multiple leading comments', () { + expect( + Library( + (b) => b + ..comments.addAll([ + 'Generated by foo!', + '', + 'Avoid editing by hand.', + ]) + ..body.add( + Class((b) => b..name = 'Foo'), + ), + ), + equalsDart(r''' + // Generated by foo! + // + // Avoid editing by hand. + + class Foo { } + ''', DartEmitter(allocator: Allocator())), + ); + }); + + test('should emit a source file with ignore comments', () { + expect( + Library( + (b) => b + ..ignoreForFile.add('sort_constructors_first') + ..body.add( + Class((b) => b..name = 'Foo'), + ), + ), + equalsDart(r''' + // ignore_for_file: sort_constructors_first + + class Foo { } + ''', DartEmitter(allocator: Allocator())), + ); + }); + + test('should emit a source file with multiple, sorted ignore comments', () { + expect( + Library( + (b) => b + ..ignoreForFile.addAll([ + 'type=lint', + 'sort_constructors_first', + 'implementation_imports', + 'file_names', + ]) + ..body.add( + Class((b) => b..name = 'Foo'), + ), + ), + equalsDart(r''' + // ignore_for_file: file_names, implementation_imports, sort_constructors_first + // ignore_for_file: type=lint + + class Foo { } + ''', DartEmitter(allocator: Allocator())), + ); + }); + test('should emit a source file with manual imports', () { expect( Library((b) => b From d979badb452b53fafd487aa49829ace0c8d29a3c Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 20 Dec 2022 12:46:23 -0800 Subject: [PATCH 218/271] rev the minor version and prep for publishing (dart-lang/code_builder#391) --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 78feaa0d2..66aee3b69 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 4.3.1-dev +## 4.4.0 * Mention how the `allocator` argument relates to imports in the `DartEmitter` constructor doc. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index d24b16582..f3cce8f20 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.3.1-dev +version: 4.4.0 description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder From 72b2fbce51df80ac140def8d19dcdc6c872809bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 10:12:02 -0800 Subject: [PATCH 219/271] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/code_builder#392) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index b40c64178..0cd9d2104 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [2.17.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 98fec8653e287d653f7b575ca40c71383ee06b1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 09:06:14 -0800 Subject: [PATCH 220/271] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/code_builder#395) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 0cd9d2104..9977e4bc4 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [2.17.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From a32f6c53d822c60983e4e4a0ff06776f606f06b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 09:13:51 -0800 Subject: [PATCH 221/271] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/code_builder#394) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 9977e4bc4..5543f1bd6 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -46,7 +46,7 @@ jobs: sdk: [2.17.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From b476cb974f399616ad8ae30dadedec467a58d47f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 12 Feb 2023 09:58:31 -0800 Subject: [PATCH 222/271] Fix CI, use dart_flutter_team_lints, remove redundant (dart-lang/code_builder#396) --- pkgs/code_builder/analysis_options.yaml | 17 +---------------- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/directive_test.dart | 6 +++--- pkgs/code_builder/test/specs/method_test.dart | 2 +- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml index 9d6246a28..23e98e8d4 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: @@ -8,39 +8,24 @@ analyzer: linter: rules: - - always_declare_return_types - - avoid_catching_errors - avoid_private_typedef_functions - avoid_redundant_argument_values - avoid_unused_constructor_parameters - cancel_subscriptions - cascade_invocations - comment_references - - directives_ordering - join_return_with_assignment - - lines_longer_than_80_chars - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - omit_local_variable_types - - only_throw_errors - package_api_docs - - prefer_asserts_in_initializer_lists - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - prefer_relative_imports - - prefer_single_quotes - - sort_pub_dependencies - test_types_in_equals - - throw_in_finally - - type_annotate_public_apis - - unawaited_futures - unnecessary_await_in_return - - unnecessary_lambdas - - unnecessary_parenthesis - - unnecessary_statements - use_string_buffers - use_super_parameters diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index f3cce8f20..d53f975ad 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -18,7 +18,7 @@ dev_dependencies: build: ^2.0.0 build_runner: ^2.0.3 built_value_generator: ^8.0.0 + dart_flutter_team_lints: ^0.1.0 dart_style: ^2.0.0 - lints: ^2.0.0 source_gen: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/code_builder/test/directive_test.dart b/pkgs/code_builder/test/directive_test.dart index 11b862373..0aee6ae57 100644 --- a/pkgs/code_builder/test/directive_test.dart +++ b/pkgs/code_builder/test/directive_test.dart @@ -13,9 +13,9 @@ void main() { final $LinkedHashMap = refer('LinkedHashMap', 'dart:collection'); final library = Library((b) => b - ..directives.add((Directive.export('../relative.dart'))) - ..directives.add((Directive.export('package:foo/foo.dart'))) - ..directives.add((Directive.part('lib.g.dart'))) + ..directives.add(Directive.export('../relative.dart')) + ..directives.add(Directive.export('package:foo/foo.dart')) + ..directives.add(Directive.part('lib.g.dart')) ..body.add(Field((b) => b ..name = 'relativeRef' ..modifier = FieldModifier.final$ diff --git a/pkgs/code_builder/test/specs/method_test.dart b/pkgs/code_builder/test/specs/method_test.dart index 914a54a92..5621bc52c 100644 --- a/pkgs/code_builder/test/specs/method_test.dart +++ b/pkgs/code_builder/test/specs/method_test.dart @@ -109,7 +109,7 @@ void main() { Method((b) => b ..name = 'foo' ..external = true - ..requiredParameters.add((Parameter((b) => b..name = 'foo'))) + ..requiredParameters.add(Parameter((b) => b..name = 'foo')) ..type = MethodType.setter), equalsDart(r''' external set foo(foo); From 2b3d1d22056e05313e65f799ab6fc6ff3b247a08 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 7 Mar 2023 11:36:54 -0800 Subject: [PATCH 223/271] Failing test for assigning to nullable typed var (dart-lang/code_builder#401) Towards dart-lang/code_builder#315 Add a skipped test which demonstrates that the nullability of a type reference is ignored when emitting a variable assignment. --- pkgs/code_builder/CHANGELOG.md | 2 ++ pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/code/expression_test.dart | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 66aee3b69..7f18c6b0d 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,5 @@ +## 4.4.1-dev + ## 4.4.0 * Mention how the `allocator` argument relates to imports in the `DartEmitter` diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index d53f975ad..7dc1c4f0e 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.4.0 +version: 4.4.1-dev description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 08e00852f..cc55402e2 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -639,6 +639,16 @@ void main() { equalsDart('final String foo = bar')); }); + test('should emit a nullable typed final variable declaration', () { + final emitter = DartEmitter.scoped(useNullSafetySyntax: true); + expect( + declareFinal('foo', + type: TypeReference((b) => b + ..symbol = 'String' + ..isNullable = true)).assign(refer('bar')), + equalsDart('final String? foo = bar', emitter)); + }, skip: 'https://github.com/dart-lang/code_builder/issues/315'); + test('should emit a late final variable declaration', () { expect(declareFinal('foo', late: true).assign(refer('bar')), equalsDart('late final foo = bar')); From 2ad40f8718eb3cede0dd59c369fceca9eb13e620 Mon Sep 17 00:00:00 2001 From: Don Olmstead Date: Thu, 9 Mar 2023 12:36:57 -0800 Subject: [PATCH 224/271] Regenerate files (dart-lang/code_builder#404) --- pkgs/code_builder/lib/src/specs/class.g.dart | 36 ++++----- pkgs/code_builder/lib/src/specs/code.g.dart | 7 +- .../lib/src/specs/constructor.g.dart | 39 ++++------ .../lib/src/specs/directive.g.dart | 17 ++-- pkgs/code_builder/lib/src/specs/enum.g.dart | 48 ++++++------ .../lib/src/specs/extension.g.dart | 22 +++--- pkgs/code_builder/lib/src/specs/field.g.dart | 25 +++--- .../code_builder/lib/src/specs/library.g.dart | 19 ++--- pkgs/code_builder/lib/src/specs/method.g.dart | 78 ++++++++----------- pkgs/code_builder/lib/src/specs/mixin.g.dart | 25 +++--- .../lib/src/specs/type_function.g.dart | 22 +++--- .../lib/src/specs/type_reference.g.dart | 14 ++-- .../code_builder/lib/src/specs/typedef.g.dart | 13 ++-- 13 files changed, 173 insertions(+), 192 deletions(-) diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index 81854a2a8..25d17188a 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -85,26 +85,20 @@ class _$Class extends Class { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc($jc(0, abstract.hashCode), - annotations.hashCode), - docs.hashCode), - extend.hashCode), - implements.hashCode), - mixins.hashCode), - types.hashCode), - constructors.hashCode), - methods.hashCode), - fields.hashCode), - name.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, abstract.hashCode); + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, extend.hashCode); + _$hash = $jc(_$hash, implements.hashCode); + _$hash = $jc(_$hash, mixins.hashCode); + _$hash = $jc(_$hash, types.hashCode); + _$hash = $jc(_$hash, constructors.hashCode); + _$hash = $jc(_$hash, methods.hashCode); + _$hash = $jc(_$hash, fields.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -344,4 +338,4 @@ class _$ClassBuilder extends ClassBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/code.g.dart b/pkgs/code_builder/lib/src/specs/code.g.dart index beb7e5c3f..7b5ba7825 100644 --- a/pkgs/code_builder/lib/src/specs/code.g.dart +++ b/pkgs/code_builder/lib/src/specs/code.g.dart @@ -32,7 +32,10 @@ class _$Block extends Block { @override int get hashCode { - return $jf($jc(0, statements.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, statements.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -103,4 +106,4 @@ class _$BlockBuilder extends BlockBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/constructor.g.dart b/pkgs/code_builder/lib/src/specs/constructor.g.dart index 071329928..3f0693272 100644 --- a/pkgs/code_builder/lib/src/specs/constructor.g.dart +++ b/pkgs/code_builder/lib/src/specs/constructor.g.dart @@ -90,28 +90,21 @@ class _$Constructor extends Constructor { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc($jc(0, annotations.hashCode), - docs.hashCode), - optionalParameters.hashCode), - requiredParameters.hashCode), - initializers.hashCode), - body.hashCode), - external.hashCode), - constant.hashCode), - factory.hashCode), - lambda.hashCode), - name.hashCode), - redirect.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, optionalParameters.hashCode); + _$hash = $jc(_$hash, requiredParameters.hashCode); + _$hash = $jc(_$hash, initializers.hashCode); + _$hash = $jc(_$hash, body.hashCode); + _$hash = $jc(_$hash, external.hashCode); + _$hash = $jc(_$hash, constant.hashCode); + _$hash = $jc(_$hash, factory.hashCode); + _$hash = $jc(_$hash, lambda.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, redirect.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -360,4 +353,4 @@ class _$ConstructorBuilder extends ConstructorBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/directive.g.dart b/pkgs/code_builder/lib/src/specs/directive.g.dart index 598ef1667..b28158e07 100644 --- a/pkgs/code_builder/lib/src/specs/directive.g.dart +++ b/pkgs/code_builder/lib/src/specs/directive.g.dart @@ -59,12 +59,15 @@ class _$Directive extends Directive { @override int get hashCode { - return $jf($jc( - $jc( - $jc($jc($jc($jc(0, as.hashCode), url.hashCode), type.hashCode), - show.hashCode), - hide.hashCode), - deferred.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, as.hashCode); + _$hash = $jc(_$hash, url.hashCode); + _$hash = $jc(_$hash, type.hashCode); + _$hash = $jc(_$hash, show.hashCode); + _$hash = $jc(_$hash, hide.hashCode); + _$hash = $jc(_$hash, deferred.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -204,4 +207,4 @@ class _$DirectiveBuilder extends DirectiveBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/enum.g.dart b/pkgs/code_builder/lib/src/specs/enum.g.dart index 5ed4e5037..050885b3e 100644 --- a/pkgs/code_builder/lib/src/specs/enum.g.dart +++ b/pkgs/code_builder/lib/src/specs/enum.g.dart @@ -81,22 +81,19 @@ class _$Enum extends Enum { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc($jc($jc(0, name.hashCode), values.hashCode), - annotations.hashCode), - docs.hashCode), - implements.hashCode), - mixins.hashCode), - types.hashCode), - constructors.hashCode), - methods.hashCode), - fields.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, values.hashCode); + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, implements.hashCode); + _$hash = $jc(_$hash, mixins.hashCode); + _$hash = $jc(_$hash, types.hashCode); + _$hash = $jc(_$hash, constructors.hashCode); + _$hash = $jc(_$hash, methods.hashCode); + _$hash = $jc(_$hash, fields.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -375,14 +372,15 @@ class _$EnumValue extends EnumValue { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc($jc($jc(0, name.hashCode), annotations.hashCode), - docs.hashCode), - constructorName.hashCode), - types.hashCode), - arguments.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, constructorName.hashCode); + _$hash = $jc(_$hash, types.hashCode); + _$hash = $jc(_$hash, arguments.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -538,4 +536,4 @@ class _$EnumValueBuilder extends EnumValueBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/extension.g.dart b/pkgs/code_builder/lib/src/specs/extension.g.dart index 7d4afce7c..83de17614 100644 --- a/pkgs/code_builder/lib/src/specs/extension.g.dart +++ b/pkgs/code_builder/lib/src/specs/extension.g.dart @@ -64,16 +64,16 @@ class _$Extension extends Extension { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc( - $jc($jc($jc(0, annotations.hashCode), docs.hashCode), - on.hashCode), - types.hashCode), - methods.hashCode), - fields.hashCode), - name.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, on.hashCode); + _$hash = $jc(_$hash, types.hashCode); + _$hash = $jc(_$hash, methods.hashCode); + _$hash = $jc(_$hash, fields.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -245,4 +245,4 @@ class _$ExtensionBuilder extends ExtensionBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index 543a053df..c8e9f05b0 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -68,18 +68,17 @@ class _$Field extends Field { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc( - $jc( - $jc($jc($jc(0, annotations.hashCode), docs.hashCode), - assignment.hashCode), - static.hashCode), - late.hashCode), - name.hashCode), - type.hashCode), - modifier.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, assignment.hashCode); + _$hash = $jc(_$hash, static.hashCode); + _$hash = $jc(_$hash, late.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, type.hashCode); + _$hash = $jc(_$hash, modifier.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -263,4 +262,4 @@ class _$FieldBuilder extends FieldBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index f4451ba78..6bf19b309 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -61,14 +61,15 @@ class _$Library extends Library { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc($jc($jc(0, annotations.hashCode), directives.hashCode), - body.hashCode), - comments.hashCode), - ignoreForFile.hashCode), - name.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, directives.hashCode); + _$hash = $jc(_$hash, body.hashCode); + _$hash = $jc(_$hash, comments.hashCode); + _$hash = $jc(_$hash, ignoreForFile.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -224,4 +225,4 @@ class _$LibraryBuilder extends LibraryBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/method.g.dart b/pkgs/code_builder/lib/src/specs/method.g.dart index f503da88f..214f6b214 100644 --- a/pkgs/code_builder/lib/src/specs/method.g.dart +++ b/pkgs/code_builder/lib/src/specs/method.g.dart @@ -92,32 +92,22 @@ class _$Method extends Method { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc(0, - annotations.hashCode), - docs.hashCode), - types.hashCode), - optionalParameters.hashCode), - requiredParameters.hashCode), - body.hashCode), - external.hashCode), - lambda.hashCode), - static.hashCode), - name.hashCode), - type.hashCode), - modifier.hashCode), - returns.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, types.hashCode); + _$hash = $jc(_$hash, optionalParameters.hashCode); + _$hash = $jc(_$hash, requiredParameters.hashCode); + _$hash = $jc(_$hash, body.hashCode); + _$hash = $jc(_$hash, external.hashCode); + _$hash = $jc(_$hash, lambda.hashCode); + _$hash = $jc(_$hash, static.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, type.hashCode); + _$hash = $jc(_$hash, modifier.hashCode); + _$hash = $jc(_$hash, returns.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -458,26 +448,20 @@ class _$Parameter extends Parameter { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc( - $jc($jc(0, defaultTo.hashCode), - name.hashCode), - named.hashCode), - toThis.hashCode), - toSuper.hashCode), - annotations.hashCode), - docs.hashCode), - types.hashCode), - type.hashCode), - required.hashCode), - covariant.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, defaultTo.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, named.hashCode); + _$hash = $jc(_$hash, toThis.hashCode); + _$hash = $jc(_$hash, toSuper.hashCode); + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, types.hashCode); + _$hash = $jc(_$hash, type.hashCode); + _$hash = $jc(_$hash, required.hashCode); + _$hash = $jc(_$hash, covariant.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -710,4 +694,4 @@ class _$ParameterBuilder extends ParameterBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/mixin.g.dart b/pkgs/code_builder/lib/src/specs/mixin.g.dart index ea9700e60..b1cb622d4 100644 --- a/pkgs/code_builder/lib/src/specs/mixin.g.dart +++ b/pkgs/code_builder/lib/src/specs/mixin.g.dart @@ -69,18 +69,17 @@ class _$Mixin extends Mixin { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc( - $jc( - $jc($jc($jc(0, annotations.hashCode), docs.hashCode), - on.hashCode), - implements.hashCode), - types.hashCode), - methods.hashCode), - fields.hashCode), - name.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, on.hashCode); + _$hash = $jc(_$hash, implements.hashCode); + _$hash = $jc(_$hash, types.hashCode); + _$hash = $jc(_$hash, methods.hashCode); + _$hash = $jc(_$hash, fields.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -270,4 +269,4 @@ class _$MixinBuilder extends MixinBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/type_function.g.dart b/pkgs/code_builder/lib/src/specs/type_function.g.dart index f9fe0d678..d09f59b03 100644 --- a/pkgs/code_builder/lib/src/specs/type_function.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_function.g.dart @@ -68,16 +68,16 @@ class _$FunctionType extends FunctionType { @override int get hashCode { - return $jf($jc( - $jc( - $jc( - $jc( - $jc($jc($jc(0, returnType.hashCode), types.hashCode), - requiredParameters.hashCode), - optionalParameters.hashCode), - namedParameters.hashCode), - namedRequiredParameters.hashCode), - isNullable.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, returnType.hashCode); + _$hash = $jc(_$hash, types.hashCode); + _$hash = $jc(_$hash, requiredParameters.hashCode); + _$hash = $jc(_$hash, optionalParameters.hashCode); + _$hash = $jc(_$hash, namedParameters.hashCode); + _$hash = $jc(_$hash, namedRequiredParameters.hashCode); + _$hash = $jc(_$hash, isNullable.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -249,4 +249,4 @@ class _$FunctionTypeBuilder extends FunctionTypeBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/type_reference.g.dart b/pkgs/code_builder/lib/src/specs/type_reference.g.dart index b0f5f0d12..124e8b4f0 100644 --- a/pkgs/code_builder/lib/src/specs/type_reference.g.dart +++ b/pkgs/code_builder/lib/src/specs/type_reference.g.dart @@ -53,10 +53,14 @@ class _$TypeReference extends TypeReference { @override int get hashCode { - return $jf($jc( - $jc($jc($jc($jc(0, symbol.hashCode), url.hashCode), bound.hashCode), - types.hashCode), - isNullable.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, symbol.hashCode); + _$hash = $jc(_$hash, url.hashCode); + _$hash = $jc(_$hash, bound.hashCode); + _$hash = $jc(_$hash, types.hashCode); + _$hash = $jc(_$hash, isNullable.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -190,4 +194,4 @@ class _$TypeReferenceBuilder extends TypeReferenceBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/specs/typedef.g.dart b/pkgs/code_builder/lib/src/specs/typedef.g.dart index f884376e5..552dbccb4 100644 --- a/pkgs/code_builder/lib/src/specs/typedef.g.dart +++ b/pkgs/code_builder/lib/src/specs/typedef.g.dart @@ -51,10 +51,13 @@ class _$TypeDef extends TypeDef { @override int get hashCode { - return $jf($jc( - $jc($jc($jc(0, name.hashCode), definition.hashCode), - annotations.hashCode), - docs.hashCode)); + var _$hash = 0; + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, definition.hashCode); + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jf(_$hash); + return _$hash; } @override @@ -176,4 +179,4 @@ class _$TypeDefBuilder extends TypeDefBuilder { } } -// ignore_for_file: always_put_control_body_on_new_line,always_specify_types,annotate_overrides,avoid_annotating_with_dynamic,avoid_as,avoid_catches_without_on_clauses,avoid_returning_this,deprecated_member_use_from_same_package,lines_longer_than_80_chars,no_leading_underscores_for_local_identifiers,omit_local_variable_types,prefer_expression_function_bodies,sort_constructors_first,test_types_in_equals,unnecessary_const,unnecessary_new,unnecessary_lambdas +// ignore_for_file: deprecated_member_use_from_same_package,type=lint From 396f2489b712d47d804cf446e519e48eff690892 Mon Sep 17 00:00:00 2001 From: Don Olmstead Date: Thu, 9 Mar 2023 12:38:24 -0800 Subject: [PATCH 225/271] Add support for spreads in map literals (dart-lang/code_builder#400) Adds `literalSpread` and `literalNullSafeSpread` which can be used as keys in `literalMap` and `literalConstMap` to signal that the corresponding value should be spread across the Map. --- pkgs/code_builder/CHANGELOG.md | 21 ++++++++++++++++++- .../lib/src/specs/expression.dart | 4 +++- .../lib/src/specs/expression/literal.dart | 19 +++++++++++++++++ pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 13 ++++++++++++ 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 7f18c6b0d..9f027a3e4 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,23 @@ -## 4.4.1-dev +## 4.5.0-dev + +* Add `literalSpread` and `literalNullSafeSpread` to support adding spreads to + `literalMap`. + +```dart +void main() { + // Creates a map + // { + // ...one, + // 2: two, + // ...?three, + // } + final map = literalMap({ + literalSpread(): refer('one'), + 2: refer('two'), + literalNullSafeSpread(): refer('three'), + }); +} +``` ## 4.4.0 diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 5400b388b..20bcad6a5 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -593,7 +593,9 @@ abstract class ExpressionEmitter implements ExpressionVisitor { visitAll(expression.values.keys, out, (key) { final value = expression.values[key]; _acceptLiteral(key, out); - out.write(': '); + if (key is! LiteralSpreadExpression) { + out.write(': '); + } _acceptLiteral(value, out); }); if (expression.values.length > 1) { diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 2d301f5e6..1c28c9b5f 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -65,6 +65,20 @@ Expression literalString(String value, {bool raw = false}) { return LiteralExpression._("${raw ? 'r' : ''}'$escaped'"); } +/// Create a literal `...` operator for use when creating a Map literal. +/// +/// *NOTE* This is used as a sentinel when constructing a `literalMap` or a +/// or `literalConstMap` to signify that the value should be spread. Do NOT +/// reuse the value when creating a Map with multiple spreads. +Expression literalSpread() => LiteralSpreadExpression._(false); + +/// Create a literal `...?` operator for use when creating a Map literal. +/// +/// *NOTE* This is used as a sentinel when constructing a `literalMap` or a +/// or `literalConstMap` to signify that the value should be spread. Do NOT +/// reuse the value when creating a Map with multiple spreads. +Expression literalNullSafeSpread() => LiteralSpreadExpression._(true); + /// Creates a literal list expression from [values]. LiteralListExpression literalList(Iterable values, [Reference? type]) => @@ -122,6 +136,11 @@ class LiteralExpression extends Expression { String toString() => literal; } +class LiteralSpreadExpression extends LiteralExpression { + LiteralSpreadExpression._(bool nullAware) + : super._('...${nullAware ? '?' : ''}'); +} + class LiteralListExpression extends Expression { @override final bool isConst; diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 7dc1c4f0e..267fca1b0 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.4.1-dev +version: 4.5.0-dev description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index cc55402e2..47ab3c404 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/src/specs/expression.dart'; import 'package:test/test.dart'; import '../../common.dart'; @@ -100,6 +101,18 @@ void main() { ); }); + test('should emit a map with spreads', () { + expect( + literalMap({ + literalSpread(): refer('one'), + 2: refer('two'), + literalNullSafeSpread(): refer('three'), + refer('Map').newInstance([]): null, + }), + equalsDart('{...one, 2: two, ...?three, Map(): null, }'), + ); + }); + test('should emit a list of other literals and expressions', () { expect( literalList([ From 911994075490eff0dcc5d7aac6bdeb5c9710eaf0 Mon Sep 17 00:00:00 2001 From: Jonathan Rezende Date: Thu, 9 Mar 2023 20:29:41 -0300 Subject: [PATCH 226/271] Allow type parameters in typedefs (dart-lang/code_builder#403) Add a `types` field and read it in the emitter. --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/README.md | 2 +- pkgs/code_builder/lib/src/emitter.dart | 4 ++- pkgs/code_builder/lib/src/specs/typedef.dart | 9 ++++-- .../code_builder/lib/src/specs/typedef.g.dart | 31 ++++++++++++++++--- 5 files changed, 39 insertions(+), 8 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 9f027a3e4..7ce07b130 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,6 @@ ## 4.5.0-dev +* Add support for emitting type parameters for typedefs. * Add `literalSpread` and `literalNullSafeSpread` to support adding spreads to `literalMap`. diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 9ee994bb7..2d77a256e 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -85,7 +85,7 @@ will be on a best-effort basis. > format this repository. You can run it simply from the command-line: > > ```sh -> $ dart pub run dart_style:format -w . +> $ dart run dart_style:format -w . > ``` [wiki]: https://github.com/dart-lang/code_builder/wiki diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 18c822917..697fe27f7 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -542,7 +542,9 @@ class DartEmitter extends Object for (var a in spec.annotations) { visitAnnotation(a, out); } - out.write('typedef ${spec.name} = '); + out.write('typedef ${spec.name}'); + visitTypeParameters(spec.types.map((r) => r.type), out); + out.write(' = '); spec.definition.accept(this, out); out.writeln(';'); return out; diff --git a/pkgs/code_builder/lib/src/specs/typedef.dart b/pkgs/code_builder/lib/src/specs/typedef.dart index 1c305ef8a..fe5d8f12c 100644 --- a/pkgs/code_builder/lib/src/specs/typedef.dart +++ b/pkgs/code_builder/lib/src/specs/typedef.dart @@ -9,14 +9,16 @@ import 'package:meta/meta.dart'; import '../base.dart'; import '../mixins/annotations.dart'; import '../mixins/dartdoc.dart'; +import '../mixins/generics.dart'; import '../visitors.dart'; import 'expression.dart'; +import 'reference.dart'; part 'typedef.g.dart'; @immutable abstract class TypeDef extends Object - with HasAnnotations, HasDartDocs + with HasAnnotations, HasDartDocs, HasGenerics implements Built, Spec { factory TypeDef([void Function(TypeDefBuilder)? updates]) = _$TypeDef; @@ -39,7 +41,7 @@ abstract class TypeDef extends Object } abstract class TypeDefBuilder extends Object - with HasAnnotationsBuilder, HasDartDocsBuilder + with HasAnnotationsBuilder, HasDartDocsBuilder, HasGenericsBuilder implements Builder { factory TypeDefBuilder() = _$TypeDefBuilder; @@ -51,6 +53,9 @@ abstract class TypeDefBuilder extends Object @override ListBuilder docs = ListBuilder(); + @override + ListBuilder types = ListBuilder(); + String? name; Expression? definition; diff --git a/pkgs/code_builder/lib/src/specs/typedef.g.dart b/pkgs/code_builder/lib/src/specs/typedef.g.dart index 552dbccb4..8c2a16c2d 100644 --- a/pkgs/code_builder/lib/src/specs/typedef.g.dart +++ b/pkgs/code_builder/lib/src/specs/typedef.g.dart @@ -15,6 +15,8 @@ class _$TypeDef extends TypeDef { final BuiltList annotations; @override final BuiltList docs; + @override + final BuiltList types; factory _$TypeDef([void Function(TypeDefBuilder)? updates]) => (new TypeDefBuilder()..update(updates)).build() as _$TypeDef; @@ -23,13 +25,15 @@ class _$TypeDef extends TypeDef { {required this.name, required this.definition, required this.annotations, - required this.docs}) + required this.docs, + required this.types}) : super._() { BuiltValueNullFieldError.checkNotNull(name, r'TypeDef', 'name'); BuiltValueNullFieldError.checkNotNull(definition, r'TypeDef', 'definition'); BuiltValueNullFieldError.checkNotNull( annotations, r'TypeDef', 'annotations'); BuiltValueNullFieldError.checkNotNull(docs, r'TypeDef', 'docs'); + BuiltValueNullFieldError.checkNotNull(types, r'TypeDef', 'types'); } @override @@ -46,7 +50,8 @@ class _$TypeDef extends TypeDef { name == other.name && definition == other.definition && annotations == other.annotations && - docs == other.docs; + docs == other.docs && + types == other.types; } @override @@ -56,6 +61,7 @@ class _$TypeDef extends TypeDef { _$hash = $jc(_$hash, definition.hashCode); _$hash = $jc(_$hash, annotations.hashCode); _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, types.hashCode); _$hash = $jf(_$hash); return _$hash; } @@ -66,7 +72,8 @@ class _$TypeDef extends TypeDef { ..add('name', name) ..add('definition', definition) ..add('annotations', annotations) - ..add('docs', docs)) + ..add('docs', docs) + ..add('types', types)) .toString(); } } @@ -122,6 +129,18 @@ class _$TypeDefBuilder extends TypeDefBuilder { super.docs = docs; } + @override + ListBuilder get types { + _$this; + return super.types; + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + _$TypeDefBuilder() : super._(); TypeDefBuilder get _$this { @@ -131,6 +150,7 @@ class _$TypeDefBuilder extends TypeDefBuilder { super.definition = $v.definition; super.annotations = $v.annotations.toBuilder(); super.docs = $v.docs.toBuilder(); + super.types = $v.types.toBuilder(); _$v = null; } return this; @@ -160,7 +180,8 @@ class _$TypeDefBuilder extends TypeDefBuilder { definition: BuiltValueNullFieldError.checkNotNull( definition, r'TypeDef', 'definition'), annotations: annotations.build(), - docs: docs.build()); + docs: docs.build(), + types: types.build()); } catch (_) { late String _$failedField; try { @@ -168,6 +189,8 @@ class _$TypeDefBuilder extends TypeDefBuilder { annotations.build(); _$failedField = 'docs'; docs.build(); + _$failedField = 'types'; + types.build(); } catch (e) { throw new BuiltValueNestedFieldError( r'TypeDef', _$failedField, e.toString()); From 7c4b20b5d8ec3c808e79be64dd94c4d264d7fd6d Mon Sep 17 00:00:00 2001 From: Don Olmstead Date: Fri, 10 Mar 2023 10:57:45 -0800 Subject: [PATCH 227/271] Show spread literals (dart-lang/code_builder#406) Add `literalSpread` and `literalNullSafeSpread` to the exports for `expression.dart`. --- pkgs/code_builder/lib/code_builder.dart | 2 ++ pkgs/code_builder/test/specs/code/expression_test.dart | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 0f7a7baca..01a82dbd4 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -40,6 +40,8 @@ export 'src/specs/expression.dart' literalMap, literalConstMap, literalString, + literalSpread, + literalNullSafeSpread, literalTrue, literalFalse; export 'src/specs/extension.dart' show Extension, ExtensionBuilder; diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 47ab3c404..e78b2f42f 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/src/specs/expression.dart'; import 'package:test/test.dart'; import '../../common.dart'; From 65c1406975cc7202b4032e405476b00d46790188 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 14 Mar 2023 12:08:52 -0700 Subject: [PATCH 228/271] Require Dart 2.19, update to and fix latest lints (dart-lang/code_builder#407) Also some small spelling fixes Also a todo about an incorrectly spelled function --- .../.github/workflows/test-package.yml | 2 +- pkgs/code_builder/CHANGELOG.md | 5 ++-- pkgs/code_builder/lib/code_builder.dart | 30 +++++++++---------- .../lib/src/specs/expression.dart | 5 ++-- .../lib/src/specs/expression/binary.dart | 2 +- .../lib/src/specs/expression/closure.dart | 2 +- .../lib/src/specs/expression/code.dart | 2 +- .../lib/src/specs/expression/invoke.dart | 2 +- .../lib/src/specs/expression/literal.dart | 2 +- .../src/specs/expression/parenthesized.dart | 2 +- .../code_builder/lib/src/specs/reference.dart | 2 -- pkgs/code_builder/pubspec.yaml | 4 +-- .../test/specs/code/expression_test.dart | 2 +- .../test/specs/code/statement_test.dart | 2 +- pkgs/code_builder/test/specs/enum_test.dart | 4 +-- 15 files changed, 33 insertions(+), 35 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 5543f1bd6..dd6e70ba9 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [2.17.0, dev] + sdk: [2.19.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 7ce07b130..b05e24c4f 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,6 @@ ## 4.5.0-dev +* Require Dart 2.19 * Add support for emitting type parameters for typedefs. * Add `literalSpread` and `literalNullSafeSpread` to support adding spreads to `literalMap`. @@ -48,7 +49,7 @@ void main() { * Add `declareConst`, `declareFinal`, and `declareVar` to replace `Expression.assignConst`, `assignFinal`, and `assignVar`. Add support for late variables with the `declare*` utilities. -* Add `ParameterBuilder.toSuper` so suport super formal parameters language +* Add `ParameterBuilder.toSuper` so support super formal parameters language feature. ## 4.1.0 @@ -63,7 +64,7 @@ void main() { ## 4.0.0 * Migrate to null safety. -* Changed the DartEmittor constructor to use named optional parameters. +* Changed the `DartEmitter` constructor to use named optional parameters. * Add `ParenthesizedExpression` and `ExpressionVisitor.visitParenthesizedExpression.` diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 01a82dbd4..d34ad7481 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -3,20 +3,19 @@ // BSD-style license that can be found in the LICENSE file. export 'src/allocator.dart' show Allocator; -export 'src/base.dart' show lazySpec, Spec; +export 'src/base.dart' show Spec, lazySpec; export 'src/emitter.dart' show DartEmitter; -export 'src/matchers.dart' show equalsDart, EqualsDart; +export 'src/matchers.dart' show EqualsDart, equalsDart; export 'src/specs/class.dart' show Class, ClassBuilder; export 'src/specs/code.dart' - show lazyCode, Block, BlockBuilder, Code, StaticCode, ScopedCode; + show Block, BlockBuilder, Code, ScopedCode, StaticCode, lazyCode; export 'src/specs/constructor.dart' show Constructor, ConstructorBuilder; export 'src/specs/directive.dart' - show Directive, DirectiveType, DirectiveBuilder; + show Directive, DirectiveBuilder, DirectiveType; export 'src/specs/enum.dart' show Enum, EnumBuilder, EnumValue, EnumValueBuilder; export 'src/specs/expression.dart' show - ToCodeExpression, BinaryExpression, CodeExpression, Expression, @@ -26,24 +25,25 @@ export 'src/specs/expression.dart' InvokeExpressionType, LiteralExpression, LiteralListExpression, + ToCodeExpression, declareConst, declareFinal, declareVar, literal, - literalNull, - literalNum, literalBool, - literalList, literalConstList, - literalSet, + literalConstMap, literalConstSet, + literalFalse, + literalList, literalMap, - literalConstMap, - literalString, - literalSpread, + literalNull, literalNullSafeSpread, - literalTrue, - literalFalse; + literalNum, + literalSet, + literalSpread, + literalString, + literalTrue; export 'src/specs/extension.dart' show Extension, ExtensionBuilder; export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; export 'src/specs/library.dart' show Library, LibraryBuilder; @@ -56,7 +56,7 @@ export 'src/specs/method.dart' Parameter, ParameterBuilder; export 'src/specs/mixin.dart' show Mixin, MixinBuilder; -export 'src/specs/reference.dart' show refer, Reference; +export 'src/specs/reference.dart' show Reference, refer; export 'src/specs/type_function.dart' show FunctionType, FunctionTypeBuilder; export 'src/specs/type_reference.dart' show TypeReference, TypeReferenceBuilder; export 'src/specs/typedef.dart' show TypeDef, TypeDefBuilder; diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 20bcad6a5..9c1380718 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.expression; - import 'package:meta/meta.dart'; import '../base.dart'; @@ -149,6 +147,7 @@ abstract class Expression implements Spec { ); /// Returns the result of `this` `-` [other]. + // TODO(kevmoo): create a function spelled correctly and deprecate this one! Expression operatorSubstract(Expression other) => BinaryExpression._( expression, other, @@ -314,7 +313,7 @@ abstract class Expression implements Spec { addSpace: false, ); - /// This expression precenede by the null safe spread operator `?...`. + /// This expression preceded by the null safe spread operator `?...`. Expression get nullSafeSpread => BinaryExpression._( const LiteralExpression._('...?'), this, diff --git a/pkgs/code_builder/lib/src/specs/expression/binary.dart b/pkgs/code_builder/lib/src/specs/expression/binary.dart index 35e530589..d02a2a6a9 100644 --- a/pkgs/code_builder/lib/src/specs/expression/binary.dart +++ b/pkgs/code_builder/lib/src/specs/expression/binary.dart @@ -2,7 +2,7 @@ // 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. -part of code_builder.src.specs.expression; +part of '../expression.dart'; /// Represents two expressions ([left] and [right]) and an [operator]. class BinaryExpression extends Expression { diff --git a/pkgs/code_builder/lib/src/specs/expression/closure.dart b/pkgs/code_builder/lib/src/specs/expression/closure.dart index 0506465ac..706600c14 100644 --- a/pkgs/code_builder/lib/src/specs/expression/closure.dart +++ b/pkgs/code_builder/lib/src/specs/expression/closure.dart @@ -2,7 +2,7 @@ // 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. -part of code_builder.src.specs.expression; +part of '../expression.dart'; /// Returns [method] as closure, removing its return type and type parameters. Expression toClosure(Method method) { diff --git a/pkgs/code_builder/lib/src/specs/expression/code.dart b/pkgs/code_builder/lib/src/specs/expression/code.dart index 0eb0c3d03..1529edb78 100644 --- a/pkgs/code_builder/lib/src/specs/expression/code.dart +++ b/pkgs/code_builder/lib/src/specs/expression/code.dart @@ -2,7 +2,7 @@ // 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. -part of code_builder.src.specs.expression; +part of '../expression.dart'; /// Represents a [Code] block as an [Expression]. class CodeExpression extends Expression { diff --git a/pkgs/code_builder/lib/src/specs/expression/invoke.dart b/pkgs/code_builder/lib/src/specs/expression/invoke.dart index 198ad1025..f54dc0ecd 100644 --- a/pkgs/code_builder/lib/src/specs/expression/invoke.dart +++ b/pkgs/code_builder/lib/src/specs/expression/invoke.dart @@ -4,7 +4,7 @@ // ignore_for_file: deprecated_member_use_from_same_package -part of code_builder.src.specs.expression; +part of '../expression.dart'; /// Represents invoking [target] as a method with arguments. class InvokeExpression extends Expression { diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 1c28c9b5f..5ff4bec17 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -2,7 +2,7 @@ // 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. -part of code_builder.src.specs.expression; +part of '../expression.dart'; /// Converts a runtime Dart [literal] value into an [Expression]. /// diff --git a/pkgs/code_builder/lib/src/specs/expression/parenthesized.dart b/pkgs/code_builder/lib/src/specs/expression/parenthesized.dart index cc4d468ab..ea34ae82f 100644 --- a/pkgs/code_builder/lib/src/specs/expression/parenthesized.dart +++ b/pkgs/code_builder/lib/src/specs/expression/parenthesized.dart @@ -2,7 +2,7 @@ // 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. -part of code_builder.src.specs.expression; +part of '../expression.dart'; /// An [Expression] wrapped with parenthesis. class ParenthesizedExpression extends Expression { diff --git a/pkgs/code_builder/lib/src/specs/reference.dart b/pkgs/code_builder/lib/src/specs/reference.dart index 6668e8117..06032ad3c 100644 --- a/pkgs/code_builder/lib/src/specs/reference.dart +++ b/pkgs/code_builder/lib/src/specs/reference.dart @@ -2,8 +2,6 @@ // 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. -library code_builder.src.specs.reference; - import 'package:built_value/built_value.dart'; import 'package:meta/meta.dart'; diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 267fca1b0..5f3f97465 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -5,7 +5,7 @@ description: >- repository: https://github.com/dart-lang/code_builder environment: - sdk: '>=2.17.0 <3.0.0' + sdk: '>=2.19.0 <3.0.0' dependencies: built_collection: ^5.0.0 @@ -18,7 +18,7 @@ dev_dependencies: build: ^2.0.0 build_runner: ^2.0.3 built_value_generator: ^8.0.0 - dart_flutter_team_lints: ^0.1.0 + dart_flutter_team_lints: ^1.0.0 dart_style: ^2.0.0 source_gen: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index e78b2f42f..e10ba2ed6 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -611,7 +611,7 @@ void main() { expect(refer('foo').operatorAdd(refer('foo2')), equalsDart('foo + foo2')); }); - test('should emit an operator substract call', () { + test('should emit an operator subtract call', () { expect(refer('foo').operatorSubstract(refer('foo2')), equalsDart('foo - foo2')); }); diff --git a/pkgs/code_builder/test/specs/code/statement_test.dart b/pkgs/code_builder/test/specs/code/statement_test.dart index 72ed6fe1a..cd3d53afc 100644 --- a/pkgs/code_builder/test/specs/code/statement_test.dart +++ b/pkgs/code_builder/test/specs/code/statement_test.dart @@ -40,7 +40,7 @@ void main() { ); }); - test('should emit a block of code with lazyily invoked generators', () { + test('should emit a block of code with lazily invoked generators', () { expect( Method((b) => b ..name = 'main' diff --git a/pkgs/code_builder/test/specs/enum_test.dart b/pkgs/code_builder/test/specs/enum_test.dart index 420f994fe..1025e66dd 100644 --- a/pkgs/code_builder/test/specs/enum_test.dart +++ b/pkgs/code_builder/test/specs/enum_test.dart @@ -55,7 +55,7 @@ void main() { ..name = 'okay' ..annotations.addAll([ refer('deprecated'), - refer('Deprecated').call([literalString('use Good insted')]), + refer('Deprecated').call([literalString('use Good instead')]), ])), EnumValue((b) => b ..name = 'good' @@ -66,7 +66,7 @@ void main() { equalsDart(r''' enum Status { @deprecated - @Deprecated('use Good insted') + @Deprecated('use Good instead') okay, @JsonKey('good') good From 4ac9a5a3cc2fffb564fbde28a4642bb554ed670b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 20 Mar 2023 13:21:31 -0700 Subject: [PATCH 229/271] Prepare to publish (dart-lang/code_builder#408) Add publish workflow for github actions. Drop `-dev` version suffix. --- .../code_builder/.github/workflows/publish.yaml | 17 +++++++++++++++++ pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 pkgs/code_builder/.github/workflows/publish.yaml diff --git a/pkgs/code_builder/.github/workflows/publish.yaml b/pkgs/code_builder/.github/workflows/publish.yaml new file mode 100644 index 000000000..6cafbee3b --- /dev/null +++ b/pkgs/code_builder/.github/workflows/publish.yaml @@ -0,0 +1,17 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + types: [opened, synchronize, reopened, labeled, unlabeled] + push: + tags: [ '[A-z]+-v[0-9]+.[0-9]+.[0-9]+*' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + with: + sdk: dev diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index b05e24c4f..ee6356cfc 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 4.5.0-dev +## 4.5.0 * Require Dart 2.19 * Add support for emitting type parameters for typedefs. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 5f3f97465..c19943156 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.5.0-dev +version: 4.5.0 description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder From c9415331ba644bbb0c9dd1c3afaba2e6af9c77fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Apr 2023 17:27:45 -0700 Subject: [PATCH 230/271] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/code_builder#411) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index dd6e70ba9..d9f60a400 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 8cb497fac79741faa2582d865c67193e2629e002 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:54:51 -0700 Subject: [PATCH 231/271] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/code_builder#410) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index d9f60a400..46c6da399 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -46,7 +46,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From b32dd2051d3d743575ef32269fa645c484a373fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:22:27 -0700 Subject: [PATCH 232/271] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/code_builder#413) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 46c6da399..8e2b0507b 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 6ec25aaa17c543792de593a39ae73b1fb5f8b052 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 15 May 2023 14:34:38 -0700 Subject: [PATCH 233/271] blast_repo fixes (dart-lang/code_builder#415) dependabot --- pkgs/code_builder/.github/dependabot.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/.github/dependabot.yml b/pkgs/code_builder/.github/dependabot.yml index 71cdeea30..e802353f4 100644 --- a/pkgs/code_builder/.github/dependabot.yml +++ b/pkgs/code_builder/.github/dependabot.yml @@ -4,7 +4,9 @@ version: 2 updates: -- package-ecosystem: "github-actions" - directory: "/" +- package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From b18e32e5167f7c7377d607c33b016b75cc484cde Mon Sep 17 00:00:00 2001 From: Dillon Nys <24740863+dnys1@users.noreply.github.com> Date: Wed, 24 May 2023 10:37:08 -0700 Subject: [PATCH 234/271] Class modifiers (dart-lang/code_builder#414) Add support for adding modifiers on class definitions. Add `sealed` and `mixin` modifiers as boolean options so they can be combined with others. Add `final`, `base`, and `interface` as enum options for a single additional modifier since they are mutually exclusive. --- pkgs/code_builder/CHANGELOG.md | 4 + pkgs/code_builder/lib/code_builder.dart | 2 +- pkgs/code_builder/lib/src/emitter.dart | 22 ++++- pkgs/code_builder/lib/src/specs/class.dart | 35 ++++++++ pkgs/code_builder/lib/src/specs/class.g.dart | 64 +++++++++++++ pkgs/code_builder/lib/src/specs/mixin.dart | 6 ++ pkgs/code_builder/lib/src/specs/mixin.g.dart | 24 ++++- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/class_test.dart | 94 ++++++++++++++++++++ pkgs/code_builder/test/specs/mixin_test.dart | 11 +++ 10 files changed, 259 insertions(+), 5 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index ee6356cfc..51bd6ccab 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.6.0-dev + +* Add support for class modifiers. + ## 4.5.0 * Require Dart 2.19 diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index d34ad7481..c099b61f3 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -6,7 +6,7 @@ export 'src/allocator.dart' show Allocator; export 'src/base.dart' show Spec, lazySpec; export 'src/emitter.dart' show DartEmitter; export 'src/matchers.dart' show EqualsDart, equalsDart; -export 'src/specs/class.dart' show Class, ClassBuilder; +export 'src/specs/class.dart' show Class, ClassBuilder, ClassModifier; export 'src/specs/code.dart' show Block, BlockBuilder, Code, ScopedCode, StaticCode, lazyCode; export 'src/specs/constructor.dart' show Constructor, ConstructorBuilder; diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 697fe27f7..076614b84 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -115,8 +115,23 @@ class DartEmitter extends Object for (var a in spec.annotations) { visitAnnotation(a, out); } - if (spec.abstract) { - out.write('abstract '); + + void writeModifier() { + if (spec.modifier != null) { + out.write('${spec.modifier!.name} '); + } + } + + if (spec.sealed) { + out.write('sealed '); + } else { + if (spec.abstract) { + out.write('abstract '); + } + writeModifier(); + if (spec.mixin) { + out.write('mixin '); + } } out.write('class ${spec.name}'); visitTypeParameters(spec.types.map((r) => r.type), out); @@ -164,6 +179,9 @@ class DartEmitter extends Object visitAnnotation(a, out); } + if (spec.base) { + out.write('base '); + } out.write('mixin ${spec.name}'); visitTypeParameters(spec.types.map((r) => r.type), out); if (spec.on != null) { diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart index bd847c428..6636d9423 100644 --- a/pkgs/code_builder/lib/src/specs/class.dart +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -30,6 +30,15 @@ abstract class Class extends Object /// Whether the class is `abstract`. bool get abstract; + /// Whether the class is `sealed`. + bool get sealed; + + /// Whether the class is a `mixin class`. + bool get mixin; + + /// The class modifier, i.e. `base`, `final`, `interface`. + ClassModifier? get modifier; + @override BuiltList get annotations; @@ -60,6 +69,23 @@ abstract class Class extends Object visitor.visitClass(this, context); } +enum ClassModifier { + base, + final$, + interface; + + String get name { + switch (this) { + case ClassModifier.base: + return 'base'; + case ClassModifier.final$: + return 'final'; + case ClassModifier.interface: + return 'interface'; + } + } +} + abstract class ClassBuilder extends Object with HasAnnotationsBuilder, HasDartDocsBuilder, HasGenericsBuilder implements Builder { @@ -75,6 +101,15 @@ abstract class ClassBuilder extends Object /// Whether the class is `abstract`. bool abstract = false; + /// Whether the class is `sealed`. + bool sealed = false; + + /// Whether the class is a `mixin class`. + bool mixin = false; + + /// The class modifier, i.e. `base`, `final`, `interface`. + ClassModifier? modifier; + @override ListBuilder annotations = ListBuilder(); diff --git a/pkgs/code_builder/lib/src/specs/class.g.dart b/pkgs/code_builder/lib/src/specs/class.g.dart index 25d17188a..423f576ce 100644 --- a/pkgs/code_builder/lib/src/specs/class.g.dart +++ b/pkgs/code_builder/lib/src/specs/class.g.dart @@ -10,6 +10,12 @@ class _$Class extends Class { @override final bool abstract; @override + final bool sealed; + @override + final bool mixin; + @override + final ClassModifier? modifier; + @override final BuiltList annotations; @override final BuiltList docs; @@ -35,6 +41,9 @@ class _$Class extends Class { _$Class._( {required this.abstract, + required this.sealed, + required this.mixin, + this.modifier, required this.annotations, required this.docs, this.extend, @@ -47,6 +56,8 @@ class _$Class extends Class { required this.name}) : super._() { BuiltValueNullFieldError.checkNotNull(abstract, r'Class', 'abstract'); + BuiltValueNullFieldError.checkNotNull(sealed, r'Class', 'sealed'); + BuiltValueNullFieldError.checkNotNull(mixin, r'Class', 'mixin'); BuiltValueNullFieldError.checkNotNull(annotations, r'Class', 'annotations'); BuiltValueNullFieldError.checkNotNull(docs, r'Class', 'docs'); BuiltValueNullFieldError.checkNotNull(implements, r'Class', 'implements'); @@ -71,6 +82,9 @@ class _$Class extends Class { if (identical(other, this)) return true; return other is Class && abstract == other.abstract && + sealed == other.sealed && + mixin == other.mixin && + modifier == other.modifier && annotations == other.annotations && docs == other.docs && extend == other.extend && @@ -87,6 +101,9 @@ class _$Class extends Class { int get hashCode { var _$hash = 0; _$hash = $jc(_$hash, abstract.hashCode); + _$hash = $jc(_$hash, sealed.hashCode); + _$hash = $jc(_$hash, mixin.hashCode); + _$hash = $jc(_$hash, modifier.hashCode); _$hash = $jc(_$hash, annotations.hashCode); _$hash = $jc(_$hash, docs.hashCode); _$hash = $jc(_$hash, extend.hashCode); @@ -105,6 +122,9 @@ class _$Class extends Class { String toString() { return (newBuiltValueToStringHelper(r'Class') ..add('abstract', abstract) + ..add('sealed', sealed) + ..add('mixin', mixin) + ..add('modifier', modifier) ..add('annotations', annotations) ..add('docs', docs) ..add('extend', extend) @@ -134,6 +154,42 @@ class _$ClassBuilder extends ClassBuilder { super.abstract = abstract; } + @override + bool get sealed { + _$this; + return super.sealed; + } + + @override + set sealed(bool sealed) { + _$this; + super.sealed = sealed; + } + + @override + bool get mixin { + _$this; + return super.mixin; + } + + @override + set mixin(bool mixin) { + _$this; + super.mixin = mixin; + } + + @override + ClassModifier? get modifier { + _$this; + return super.modifier; + } + + @override + set modifier(ClassModifier? modifier) { + _$this; + super.modifier = modifier; + } + @override ListBuilder get annotations { _$this; @@ -260,6 +316,9 @@ class _$ClassBuilder extends ClassBuilder { final $v = _$v; if ($v != null) { super.abstract = $v.abstract; + super.sealed = $v.sealed; + super.mixin = $v.mixin; + super.modifier = $v.modifier; super.annotations = $v.annotations.toBuilder(); super.docs = $v.docs.toBuilder(); super.extend = $v.extend; @@ -296,6 +355,11 @@ class _$ClassBuilder extends ClassBuilder { new _$Class._( abstract: BuiltValueNullFieldError.checkNotNull( abstract, r'Class', 'abstract'), + sealed: BuiltValueNullFieldError.checkNotNull( + sealed, r'Class', 'sealed'), + mixin: BuiltValueNullFieldError.checkNotNull( + mixin, r'Class', 'mixin'), + modifier: modifier, annotations: annotations.build(), docs: docs.build(), extend: extend, diff --git a/pkgs/code_builder/lib/src/specs/mixin.dart b/pkgs/code_builder/lib/src/specs/mixin.dart index 475f408b3..e666bddaa 100644 --- a/pkgs/code_builder/lib/src/specs/mixin.dart +++ b/pkgs/code_builder/lib/src/specs/mixin.dart @@ -26,6 +26,9 @@ abstract class Mixin extends Object Mixin._(); + /// Whether the mixin is a `base mixin`. + bool get base; + @override BuiltList get annotations; @@ -60,6 +63,9 @@ abstract class MixinBuilder extends Object MixinBuilder._(); + /// Whether the mixin is a `base mixin`. + bool base = false; + @override ListBuilder annotations = ListBuilder(); diff --git a/pkgs/code_builder/lib/src/specs/mixin.g.dart b/pkgs/code_builder/lib/src/specs/mixin.g.dart index b1cb622d4..28c7356c4 100644 --- a/pkgs/code_builder/lib/src/specs/mixin.g.dart +++ b/pkgs/code_builder/lib/src/specs/mixin.g.dart @@ -7,6 +7,8 @@ part of 'mixin.dart'; // ************************************************************************** class _$Mixin extends Mixin { + @override + final bool base; @override final BuiltList annotations; @override @@ -28,7 +30,8 @@ class _$Mixin extends Mixin { (new MixinBuilder()..update(updates)).build() as _$Mixin; _$Mixin._( - {required this.annotations, + {required this.base, + required this.annotations, required this.docs, this.on, required this.implements, @@ -37,6 +40,7 @@ class _$Mixin extends Mixin { required this.fields, required this.name}) : super._() { + BuiltValueNullFieldError.checkNotNull(base, r'Mixin', 'base'); BuiltValueNullFieldError.checkNotNull(annotations, r'Mixin', 'annotations'); BuiltValueNullFieldError.checkNotNull(docs, r'Mixin', 'docs'); BuiltValueNullFieldError.checkNotNull(implements, r'Mixin', 'implements'); @@ -57,6 +61,7 @@ class _$Mixin extends Mixin { bool operator ==(Object other) { if (identical(other, this)) return true; return other is Mixin && + base == other.base && annotations == other.annotations && docs == other.docs && on == other.on && @@ -70,6 +75,7 @@ class _$Mixin extends Mixin { @override int get hashCode { var _$hash = 0; + _$hash = $jc(_$hash, base.hashCode); _$hash = $jc(_$hash, annotations.hashCode); _$hash = $jc(_$hash, docs.hashCode); _$hash = $jc(_$hash, on.hashCode); @@ -85,6 +91,7 @@ class _$Mixin extends Mixin { @override String toString() { return (newBuiltValueToStringHelper(r'Mixin') + ..add('base', base) ..add('annotations', annotations) ..add('docs', docs) ..add('on', on) @@ -100,6 +107,18 @@ class _$Mixin extends Mixin { class _$MixinBuilder extends MixinBuilder { _$Mixin? _$v; + @override + bool get base { + _$this; + return super.base; + } + + @override + set base(bool base) { + _$this; + super.base = base; + } + @override ListBuilder get annotations { _$this; @@ -201,6 +220,7 @@ class _$MixinBuilder extends MixinBuilder { MixinBuilder get _$this { final $v = _$v; if ($v != null) { + super.base = $v.base; super.annotations = $v.annotations.toBuilder(); super.docs = $v.docs.toBuilder(); super.on = $v.on; @@ -233,6 +253,8 @@ class _$MixinBuilder extends MixinBuilder { try { _$result = _$v ?? new _$Mixin._( + base: + BuiltValueNullFieldError.checkNotNull(base, r'Mixin', 'base'), annotations: annotations.build(), docs: docs.build(), on: on, diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index c19943156..e4577f147 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.5.0 +version: 4.6.0-dev description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/class_test.dart b/pkgs/code_builder/test/specs/class_test.dart index 915c7744c..562bca4c6 100644 --- a/pkgs/code_builder/test/specs/class_test.dart +++ b/pkgs/code_builder/test/specs/class_test.dart @@ -30,6 +30,100 @@ void main() { ); }); + test('should create an abstract base class', () { + expect( + Class((b) => b + ..name = 'Foo' + ..abstract = true + ..modifier = ClassModifier.base), + equalsDart(r''' + abstract base class Foo {} + '''), + ); + }); + + test('should create a final class', () { + expect( + Class((b) => b + ..name = 'Foo' + ..modifier = ClassModifier.final$), + equalsDart(r''' + final class Foo {} + '''), + ); + }); + + test('should create a sealed class', () { + expect( + Class((b) => b + ..name = 'Foo' + ..sealed = true), + equalsDart(r''' + sealed class Foo {} + '''), + ); + }); + + test('should create an abstract interface class', () { + expect( + Class((b) => b + ..name = 'Foo' + ..abstract = true + ..modifier = ClassModifier.interface), + equalsDart(r''' + abstract interface class Foo {} + '''), + ); + }); + + test('should create a mixin class', () { + expect( + Class((b) => b + ..name = 'Foo' + ..mixin = true), + equalsDart(r''' + mixin class Foo {} + '''), + ); + }); + + test('should create an abstract mixin class', () { + expect( + Class((b) => b + ..name = 'Foo' + ..abstract = true + ..mixin = true), + equalsDart(r''' + abstract mixin class Foo {} + '''), + ); + }); + + test('should create a base mixin class', () { + expect( + Class((b) => b + ..name = 'Foo' + ..mixin = true + ..modifier = ClassModifier.base), + equalsDart(r''' + base mixin class Foo {} + '''), + ); + }); + + test('should create an abstract base mixin class', () { + expect( + Class((b) => b + ..name = 'Foo' + ..abstract = true + ..mixin = true + ..modifier = ClassModifier.base), + equalsDart(r''' + abstract base mixin class Foo {} + '''), + ); + }); + test('should create a class with documentations', () { expect( Class( diff --git a/pkgs/code_builder/test/specs/mixin_test.dart b/pkgs/code_builder/test/specs/mixin_test.dart index c03e75611..e167d02a5 100644 --- a/pkgs/code_builder/test/specs/mixin_test.dart +++ b/pkgs/code_builder/test/specs/mixin_test.dart @@ -19,6 +19,17 @@ void main() { ); }); + test('should create a base mixin', () { + expect( + Mixin((b) => b + ..name = 'Foo' + ..base = true), + equalsDart(r''' + base mixin Foo {} + '''), + ); + }); + test('should create a mixin with documentations', () { expect( Mixin( From 3e71ab573c48812794563fcb71434b14e8873c80 Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Wed, 24 May 2023 12:29:34 +0200 Subject: [PATCH 235/271] Add support for emitting literal records --- .../lib/src/specs/expression.dart | 29 ++++++++++++++ .../lib/src/specs/expression/literal.dart | 33 ++++++++++++++++ .../test/specs/code/expression_test.dart | 39 +++++++++++++++++++ 3 files changed, 101 insertions(+) diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 9c1380718..275404e10 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -412,6 +412,8 @@ abstract class ExpressionVisitor implements SpecVisitor { T visitLiteralListExpression(LiteralListExpression expression, [T? context]); T visitLiteralSetExpression(LiteralSetExpression expression, [T? context]); T visitLiteralMapExpression(LiteralMapExpression expression, [T? context]); + T visitLiteralRecordExpression(LiteralRecordExpression expression, + [T? context]); T visitParenthesizedExpression(ParenthesizedExpression expression, [T? context]); } @@ -604,6 +606,33 @@ abstract class ExpressionEmitter implements ExpressionVisitor { }); } + @override + StringSink visitLiteralRecordExpression( + LiteralRecordExpression expression, [ + StringSink? output, + ]) { + final out = output ??= StringBuffer(); + return _writeConstExpression(out, expression.isConst, () { + out.write('('); + visitAll(expression.positionalFieldValues, out, (value) { + _acceptLiteral(value, out); + }); + if (expression.namedFieldValues.isNotEmpty) { + if (expression.positionalFieldValues.isNotEmpty) { + out.write(', '); + } + } else if (expression.positionalFieldValues.length == 1) { + out.write(','); + } + visitAll>( + expression.namedFieldValues.entries, out, (entry) { + out.write('${entry.key}: '); + _acceptLiteral(entry.value, out); + }); + return out..write(')'); + }); + } + @override StringSink visitParenthesizedExpression( ParenthesizedExpression expression, [ diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index 5ff4bec17..a305fa623 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -113,6 +113,18 @@ LiteralMapExpression literalConstMap( ]) => LiteralMapExpression._(true, values, keyType, valueType); +/// Create a literal record expression from [positionalFieldValues] and +/// [namedFieldValues]. +LiteralRecordExpression literalRecord(List positionalFieldValues, + Map namedFieldValues) => + LiteralRecordExpression._(false, positionalFieldValues, namedFieldValues); + +/// Create a literal `const` record expression from [positionalFieldValues] and +/// [namedFieldValues]. +LiteralRecordExpression literalConstRecord(List positionalFieldValues, + Map namedFieldValues) => + LiteralRecordExpression._(true, positionalFieldValues, namedFieldValues); + /// Represents a literal value in Dart source code. /// /// For example, `LiteralExpression('null')` should emit `null`. @@ -194,3 +206,24 @@ class LiteralMapExpression extends Expression { @override String toString() => '{$values}'; } + +class LiteralRecordExpression extends Expression { + @override + final bool isConst; + final List positionalFieldValues; + final Map namedFieldValues; + + const LiteralRecordExpression._( + this.isConst, this.positionalFieldValues, this.namedFieldValues); + + @override + R accept(ExpressionVisitor visitor, [R? context]) => + visitor.visitLiteralRecordExpression(this, context); + + @override + String toString() { + final allFields = positionalFieldValues.map((v) => v.toString()).followedBy( + namedFieldValues.entries.map((e) => '${e.key}: ${e.value}')); + return '(${allFields.join(', ')})'; + } +} diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index e10ba2ed6..38b59d00d 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:code_builder/code_builder.dart'; +import 'package:code_builder/src/specs/expression.dart'; import 'package:test/test.dart'; import '../../common.dart'; @@ -141,6 +142,44 @@ void main() { ); }); + test('should emit an empty record', () { + expect(literalRecord([], {}), equalsDart('()')); + }); + + test('should emit a const empty record', () { + expect(literalConstRecord([], {}), equalsDart('const ()')); + }); + + test('should emit a record with only positional fields', () { + expect(literalRecord([1, ''], {}), equalsDart("(1, '')")); + }); + + test('should correctly emit a record with a single positional field', () { + expect(literalRecord([1], {}), equalsDart('(1,)')); + }); + + test('should emit a record with only named fields', () { + expect(literalRecord([], {'named': 1, 'other': []}), + equalsDart('(named: 1, other: [])')); + }); + + test('should emit a record with both positional and named fields', () { + expect(literalRecord([0], {'x': true, 'y': 0}), + equalsDart('(0, x: true, y: 0)')); + }); + + test('should emit a record of other literals and expressions', () { + expect( + literalRecord([ + 1, + refer('one'), + 'one' + ], { + 'named': refer('Foo').newInstance([literalNum(1)]) + }), + equalsDart("(1, one, 'one', named: Foo(1))")); + }); + test('should emit a type as an expression', () { expect(refer('Map'), equalsDart('Map')); }); From f56cdb1eca67a966f4e9ee0b13f968333e2cc01d Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Wed, 24 May 2023 16:19:04 +0200 Subject: [PATCH 236/271] Add support for record types --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/emitter.dart | 31 ++++ .../lib/src/specs/type_record.dart | 99 +++++++++++ .../lib/src/specs/type_record.g.dart | 159 ++++++++++++++++++ pkgs/code_builder/lib/src/visitors.dart | 3 + .../test/specs/record_type_test.dart | 69 ++++++++ 6 files changed, 362 insertions(+) create mode 100644 pkgs/code_builder/lib/src/specs/type_record.dart create mode 100644 pkgs/code_builder/lib/src/specs/type_record.g.dart create mode 100644 pkgs/code_builder/test/specs/record_type_test.dart diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 51bd6ccab..2e67e75f1 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -24,6 +24,7 @@ void main() { }); } ``` +* Add support for records (both types and record literals). ## 4.4.0 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 076614b84..21f680d2d 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -17,6 +17,7 @@ import 'specs/method.dart'; import 'specs/mixin.dart'; import 'specs/reference.dart'; import 'specs/type_function.dart'; +import 'specs/type_record.dart'; import 'specs/type_reference.dart'; import 'specs/typedef.dart'; import 'visitors.dart'; @@ -553,6 +554,36 @@ class DartEmitter extends Object return out; } + @override + StringSink visitRecordType(RecordType spec, [StringSink? output]) { + final out = (output ??= StringBuffer())..write('('); + visitAll(spec.positionalFieldTypes, out, (spec) { + spec.accept(this, out); + }); + if (spec.namedFieldTypes.isNotEmpty) { + if (spec.positionalFieldTypes.isNotEmpty) { + out.write(', '); + } + out.write('{'); + visitAll>(spec.namedFieldTypes.entries, out, + (entry) { + entry.value.accept(this, out); + out.write(' ${entry.key}'); + }); + out.write('}'); + } else if (spec.positionalFieldTypes.length == 1) { + out.write(','); + } + out.write(')'); + // It doesn't really make sense to use records without + // `_useNullSafetySyntax`, but since code_builder is generally very + // permissive, follow it here too. + if (_useNullSafetySyntax && (spec.isNullable ?? false)) { + out.write('?'); + } + return out; + } + @override StringSink visitTypeDef(TypeDef spec, [StringSink? output]) { final out = output ??= StringBuffer(); diff --git a/pkgs/code_builder/lib/src/specs/type_record.dart b/pkgs/code_builder/lib/src/specs/type_record.dart new file mode 100644 index 000000000..2f0594c77 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/type_record.dart @@ -0,0 +1,99 @@ +// Copyright (c) 2023, 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:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../visitors.dart'; +import 'expression.dart'; +import 'reference.dart'; + +part 'type_record.g.dart'; + +@immutable +abstract class RecordType extends Expression + implements Built, Reference, Spec { + factory RecordType([ + void Function(RecordTypeBuilder) updates, + ]) = _$RecordType; + + RecordType._(); + + @override + R accept( + SpecVisitor visitor, [ + R? context, + ]) => + visitor.visitRecordType(this, context); + + BuiltList get positionalFieldTypes; + + BuiltMap get namedFieldTypes; + + @override + String? get url => null; + + @override + String? get symbol => null; + + @override + Reference get type => this; + + /// Optional nullability. + bool? get isNullable; + + @override + Expression newInstance( + Iterable positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) => + throw UnsupportedError('Cannot instantiate a record type.'); + + @override + Expression newInstanceNamed( + String name, + Iterable positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) => + throw UnsupportedError('Cannot instantiate a record type.'); + + @override + Expression constInstance( + Iterable positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) => + throw UnsupportedError('Cannot "const" a record type.'); + + @override + Expression constInstanceNamed( + String name, + Iterable positionalArguments, [ + Map namedArguments = const {}, + List typeArguments = const [], + ]) => + throw UnsupportedError('Cannot "const" a record type.'); +} + +abstract class RecordTypeBuilder extends Object + implements Builder { + factory RecordTypeBuilder() = _$RecordTypeBuilder; + + RecordTypeBuilder._(); + + ListBuilder positionalFieldTypes = ListBuilder(); + + MapBuilder namedFieldTypes = + MapBuilder(); + + bool? isNullable; + + String? url; + + String? symbol; +} diff --git a/pkgs/code_builder/lib/src/specs/type_record.g.dart b/pkgs/code_builder/lib/src/specs/type_record.g.dart new file mode 100644 index 000000000..b1d47dfbd --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/type_record.g.dart @@ -0,0 +1,159 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'type_record.dart'; + +// ************************************************************************** +// BuiltValueGenerator +// ************************************************************************** + +class _$RecordType extends RecordType { + @override + final BuiltList positionalFieldTypes; + @override + final BuiltMap namedFieldTypes; + @override + final bool? isNullable; + + factory _$RecordType([void Function(RecordTypeBuilder)? updates]) => + (new RecordTypeBuilder()..update(updates)).build() as _$RecordType; + + _$RecordType._( + {required this.positionalFieldTypes, + required this.namedFieldTypes, + this.isNullable}) + : super._() { + BuiltValueNullFieldError.checkNotNull( + positionalFieldTypes, r'RecordType', 'positionalFieldTypes'); + BuiltValueNullFieldError.checkNotNull( + namedFieldTypes, r'RecordType', 'namedFieldTypes'); + } + + @override + RecordType rebuild(void Function(RecordTypeBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + _$RecordTypeBuilder toBuilder() => new _$RecordTypeBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is RecordType && + positionalFieldTypes == other.positionalFieldTypes && + namedFieldTypes == other.namedFieldTypes && + isNullable == other.isNullable; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, positionalFieldTypes.hashCode); + _$hash = $jc(_$hash, namedFieldTypes.hashCode); + _$hash = $jc(_$hash, isNullable.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'RecordType') + ..add('positionalFieldTypes', positionalFieldTypes) + ..add('namedFieldTypes', namedFieldTypes) + ..add('isNullable', isNullable)) + .toString(); + } +} + +class _$RecordTypeBuilder extends RecordTypeBuilder { + _$RecordType? _$v; + + @override + ListBuilder get positionalFieldTypes { + _$this; + return super.positionalFieldTypes; + } + + @override + set positionalFieldTypes(ListBuilder positionalFieldTypes) { + _$this; + super.positionalFieldTypes = positionalFieldTypes; + } + + @override + MapBuilder get namedFieldTypes { + _$this; + return super.namedFieldTypes; + } + + @override + set namedFieldTypes(MapBuilder namedFieldTypes) { + _$this; + super.namedFieldTypes = namedFieldTypes; + } + + @override + bool? get isNullable { + _$this; + return super.isNullable; + } + + @override + set isNullable(bool? isNullable) { + _$this; + super.isNullable = isNullable; + } + + _$RecordTypeBuilder() : super._(); + + RecordTypeBuilder get _$this { + final $v = _$v; + if ($v != null) { + super.positionalFieldTypes = $v.positionalFieldTypes.toBuilder(); + super.namedFieldTypes = $v.namedFieldTypes.toBuilder(); + super.isNullable = $v.isNullable; + _$v = null; + } + return this; + } + + @override + void replace(RecordType other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$RecordType; + } + + @override + void update(void Function(RecordTypeBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + RecordType build() => _build(); + + _$RecordType _build() { + _$RecordType _$result; + try { + _$result = _$v ?? + new _$RecordType._( + positionalFieldTypes: positionalFieldTypes.build(), + namedFieldTypes: namedFieldTypes.build(), + isNullable: isNullable); + } catch (_) { + late String _$failedField; + try { + _$failedField = 'positionalFieldTypes'; + positionalFieldTypes.build(); + _$failedField = 'namedFieldTypes'; + namedFieldTypes.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + r'RecordType', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 5defdbd6c..0075bd7a6 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -17,6 +17,7 @@ import 'specs/method.dart'; import 'specs/mixin.dart'; import 'specs/reference.dart'; import 'specs/type_function.dart'; +import 'specs/type_record.dart'; import 'specs/type_reference.dart'; import 'specs/typedef.dart'; @@ -48,6 +49,8 @@ abstract class SpecVisitor { T visitMethod(Method spec, [T? context]); + T visitRecordType(RecordType spec, [T? context]); + T visitReference(Reference spec, [T? context]); T visitSpec(Spec spec, [T? context]); diff --git a/pkgs/code_builder/test/specs/record_type_test.dart b/pkgs/code_builder/test/specs/record_type_test.dart new file mode 100644 index 000000000..b8ad4e881 --- /dev/null +++ b/pkgs/code_builder/test/specs/record_type_test.dart @@ -0,0 +1,69 @@ +// Copyright (c) 2023, 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:code_builder/src/specs/type_record.dart'; +import 'package:test/test.dart'; + +import '../common.dart'; + +void main() { + late DartEmitter emitter; + + useDartfmt(); + + setUp(() => emitter = DartEmitter.scoped(useNullSafetySyntax: true)); + + final intRef = TypeReference((b) => b.symbol = 'int'); + TypeReference listRef(TypeReference argType) => TypeReference((b) => b + ..symbol = 'List' + ..types.add(argType)); + + test('should create an empty record type', () { + expect(RecordType(), equalsDart('()', emitter)); + }); + + test('should create a record type with positional fields', () { + expect( + RecordType((b) => b + ..positionalFieldTypes.addAll( + [intRef, listRef(intRef).rebuild((b) => b..isNullable = true)]) + ..isNullable = true), + equalsDart('(int, List?)?', emitter), + ); + }); + + test('should create a record type with one positional field', () { + expect(RecordType((b) => b..positionalFieldTypes.add(intRef)), + equalsDart('(int,)', emitter)); + }); + + test('should create a record type with named fields', () { + expect( + RecordType((b) => b + ..namedFieldTypes.addAll({ + 'named': intRef, + 'other': listRef(intRef), + })), + equalsDart('({int named, List other})', emitter)); + }); + + test('should create a record type with both positional and named fields', () { + expect( + RecordType((b) => b + ..positionalFieldTypes.add(listRef(intRef)) + ..namedFieldTypes.addAll({'named': intRef}) + ..isNullable = true), + equalsDart('(List, {int named})?', emitter)); + }); + + test('should create a nested record type', () { + expect( + RecordType((b) => b + ..positionalFieldTypes.add(RecordType((b) => b + ..namedFieldTypes.addAll({'named': intRef, 'other': intRef}) + ..isNullable = true))), + equalsDart('(({int named, int other})?,)', emitter)); + }); +} From e8aaecb5c038b2a395a749d5b107a2e82059b3d0 Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Fri, 26 May 2023 10:13:01 +0200 Subject: [PATCH 237/271] Fix CHANGELOG.md and export record-related APIs (dart-lang/code_builder#418) * Fix CHANGELOG.md (records didn't make it to 4.5.0) * Export record-related classes and functions --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/lib/code_builder.dart | 3 +++ pkgs/code_builder/test/specs/code/expression_test.dart | 1 - pkgs/code_builder/test/specs/record_type_test.dart | 1 - 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 2e67e75f1..c7937a496 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ ## 4.6.0-dev * Add support for class modifiers. +* Add support for records (both types and record literals). ## 4.5.0 @@ -24,7 +25,6 @@ void main() { }); } ``` -* Add support for records (both types and record literals). ## 4.4.0 diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index c099b61f3..6cfaf6add 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -33,6 +33,7 @@ export 'src/specs/expression.dart' literalBool, literalConstList, literalConstMap, + literalConstRecord, literalConstSet, literalFalse, literalList, @@ -40,6 +41,7 @@ export 'src/specs/expression.dart' literalNull, literalNullSafeSpread, literalNum, + literalRecord, literalSet, literalSpread, literalString, @@ -58,5 +60,6 @@ export 'src/specs/method.dart' export 'src/specs/mixin.dart' show Mixin, MixinBuilder; export 'src/specs/reference.dart' show Reference, refer; 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; diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 38b59d00d..2f2576abc 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/src/specs/expression.dart'; import 'package:test/test.dart'; import '../../common.dart'; diff --git a/pkgs/code_builder/test/specs/record_type_test.dart b/pkgs/code_builder/test/specs/record_type_test.dart index b8ad4e881..0084c507d 100644 --- a/pkgs/code_builder/test/specs/record_type_test.dart +++ b/pkgs/code_builder/test/specs/record_type_test.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/src/specs/type_record.dart'; import 'package:test/test.dart'; import '../common.dart'; From 913efaf197e06772dc9ead6066394e367a083cea Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 31 May 2023 20:49:39 -0700 Subject: [PATCH 238/271] Prepare to publish (dart-lang/code_builder#419) Collapse changelog back to `4.5.0` version which was never published. --- pkgs/code_builder/CHANGELOG.md | 7 ++----- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index c7937a496..6065403ca 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,12 +1,9 @@ -## 4.6.0-dev - -* Add support for class modifiers. -* Add support for records (both types and record literals). - ## 4.5.0 * Require Dart 2.19 * Add support for emitting type parameters for typedefs. +* Add support for class modifiers. +* Add support for records (both types and record literals). * Add `literalSpread` and `literalNullSafeSpread` to support adding spreads to `literalMap`. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index e4577f147..c19943156 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.6.0-dev +version: 4.5.0 description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder From 61346471498830bf83a2edb6d3740ab112c38397 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 31 May 2023 21:02:03 -0700 Subject: [PATCH 239/271] Drop package name tag prefix for workflow (dart-lang/code_builder#420) Fix an incorrect copy/paste. --- pkgs/code_builder/.github/workflows/publish.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/code_builder/.github/workflows/publish.yaml b/pkgs/code_builder/.github/workflows/publish.yaml index 6cafbee3b..1af8f47dc 100644 --- a/pkgs/code_builder/.github/workflows/publish.yaml +++ b/pkgs/code_builder/.github/workflows/publish.yaml @@ -7,7 +7,7 @@ on: branches: [ master ] types: [opened, synchronize, reopened, labeled, unlabeled] push: - tags: [ '[A-z]+-v[0-9]+.[0-9]+.[0-9]+*' ] + tags: [ 'v[0-9]+.[0-9]+.[0-9]+*' ] jobs: publish: From 4f928ec965818c11b4ee8f40ce1c2797af881693 Mon Sep 17 00:00:00 2001 From: Fabian Freund Date: Tue, 6 Jun 2023 23:56:19 +0200 Subject: [PATCH 240/271] Added support for named arguments in `enum` classes (dart-lang/code_builder#421) Add `namedArguments` field to `EnumValue` and emit the arguments in the visitor. --- pkgs/code_builder/CHANGELOG.md | 4 ++ pkgs/code_builder/lib/src/emitter.dart | 14 ++++- pkgs/code_builder/lib/src/specs/enum.dart | 6 +++ pkgs/code_builder/lib/src/specs/enum.g.dart | 32 ++++++++++-- pkgs/code_builder/pubspec.yaml | 2 +- pkgs/code_builder/test/specs/enum_test.dart | 58 +++++++++++++++++++++ 6 files changed, 109 insertions(+), 7 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 6065403ca..0099280f5 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.6.0-wip + +* Add support for named arguments in `enum` classes + ## 4.5.0 * Require Dart 2.19 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 21f680d2d..972381e78 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -800,8 +800,9 @@ class DartEmitter extends Object out.write('.${v.constructorName}'); } visitTypeParameters(v.types.map((r) => r.type), out); - final takesArguments = - v.constructorName != null || v.arguments.isNotEmpty; + final takesArguments = v.constructorName != null || + v.arguments.isNotEmpty || + v.namedArguments.isNotEmpty; if (takesArguments) { out.write('('); } @@ -809,6 +810,15 @@ class DartEmitter extends Object out.writeAll( v.arguments.map((arg) => arg.accept(this)), ', '); } + if (v.arguments.isNotEmpty && v.namedArguments.isNotEmpty) { + out.write(', '); + } + visitAll(v.namedArguments.keys, out, (name) { + out + ..write(name) + ..write(': '); + v.namedArguments[name]!.accept(this, out); + }); if (takesArguments) { out.write(')'); } diff --git a/pkgs/code_builder/lib/src/specs/enum.dart b/pkgs/code_builder/lib/src/specs/enum.dart index 632eb8fb7..c58f92cb0 100644 --- a/pkgs/code_builder/lib/src/specs/enum.dart +++ b/pkgs/code_builder/lib/src/specs/enum.dart @@ -105,6 +105,9 @@ abstract class EnumValue extends Object /// Arguments to the constructor. BuiltList get arguments; + + /// Named arguments to the constructor. + BuiltMap get namedArguments; } abstract class EnumValueBuilder extends Object @@ -130,4 +133,7 @@ abstract class EnumValueBuilder extends Object /// Arguments to the constructor. ListBuilder arguments = ListBuilder(); + + /// Named arguments to the constructor. + MapBuilder namedArguments = MapBuilder(); } diff --git a/pkgs/code_builder/lib/src/specs/enum.g.dart b/pkgs/code_builder/lib/src/specs/enum.g.dart index 050885b3e..651cc610a 100644 --- a/pkgs/code_builder/lib/src/specs/enum.g.dart +++ b/pkgs/code_builder/lib/src/specs/enum.g.dart @@ -331,6 +331,8 @@ class _$EnumValue extends EnumValue { final BuiltList types; @override final BuiltList arguments; + @override + final BuiltMap namedArguments; factory _$EnumValue([void Function(EnumValueBuilder)? updates]) => (new EnumValueBuilder()..update(updates)).build() as _$EnumValue; @@ -341,7 +343,8 @@ class _$EnumValue extends EnumValue { required this.docs, this.constructorName, required this.types, - required this.arguments}) + required this.arguments, + required this.namedArguments}) : super._() { BuiltValueNullFieldError.checkNotNull(name, r'EnumValue', 'name'); BuiltValueNullFieldError.checkNotNull( @@ -349,6 +352,8 @@ class _$EnumValue extends EnumValue { BuiltValueNullFieldError.checkNotNull(docs, r'EnumValue', 'docs'); BuiltValueNullFieldError.checkNotNull(types, r'EnumValue', 'types'); BuiltValueNullFieldError.checkNotNull(arguments, r'EnumValue', 'arguments'); + BuiltValueNullFieldError.checkNotNull( + namedArguments, r'EnumValue', 'namedArguments'); } @override @@ -367,7 +372,8 @@ class _$EnumValue extends EnumValue { docs == other.docs && constructorName == other.constructorName && types == other.types && - arguments == other.arguments; + arguments == other.arguments && + namedArguments == other.namedArguments; } @override @@ -379,6 +385,7 @@ class _$EnumValue extends EnumValue { _$hash = $jc(_$hash, constructorName.hashCode); _$hash = $jc(_$hash, types.hashCode); _$hash = $jc(_$hash, arguments.hashCode); + _$hash = $jc(_$hash, namedArguments.hashCode); _$hash = $jf(_$hash); return _$hash; } @@ -391,7 +398,8 @@ class _$EnumValue extends EnumValue { ..add('docs', docs) ..add('constructorName', constructorName) ..add('types', types) - ..add('arguments', arguments)) + ..add('arguments', arguments) + ..add('namedArguments', namedArguments)) .toString(); } } @@ -471,6 +479,18 @@ class _$EnumValueBuilder extends EnumValueBuilder { super.arguments = arguments; } + @override + MapBuilder get namedArguments { + _$this; + return super.namedArguments; + } + + @override + set namedArguments(MapBuilder namedArguments) { + _$this; + super.namedArguments = namedArguments; + } + _$EnumValueBuilder() : super._(); EnumValueBuilder get _$this { @@ -482,6 +502,7 @@ class _$EnumValueBuilder extends EnumValueBuilder { super.constructorName = $v.constructorName; super.types = $v.types.toBuilder(); super.arguments = $v.arguments.toBuilder(); + super.namedArguments = $v.namedArguments.toBuilder(); _$v = null; } return this; @@ -512,7 +533,8 @@ class _$EnumValueBuilder extends EnumValueBuilder { docs: docs.build(), constructorName: constructorName, types: types.build(), - arguments: arguments.build()); + arguments: arguments.build(), + namedArguments: namedArguments.build()); } catch (_) { late String _$failedField; try { @@ -525,6 +547,8 @@ class _$EnumValueBuilder extends EnumValueBuilder { types.build(); _$failedField = 'arguments'; arguments.build(); + _$failedField = 'namedArguments'; + namedArguments.build(); } catch (e) { throw new BuiltValueNestedFieldError( r'EnumValue', _$failedField, e.toString()); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index c19943156..9ddf19080 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.5.0 +version: 4.6.0-wip description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/enum_test.dart b/pkgs/code_builder/test/specs/enum_test.dart index 1025e66dd..5a0b19a27 100644 --- a/pkgs/code_builder/test/specs/enum_test.dart +++ b/pkgs/code_builder/test/specs/enum_test.dart @@ -381,4 +381,62 @@ void main() { } ''')); }); + + test('should create an enum which named and unnamed constructor parameters', + () { + final myEnum = Enum((b) => b + ..name = 'MyEnum' + ..constructors.add(Constructor((c) => c + ..constant = true + ..requiredParameters.addAll([ + Parameter((p) => p + ..toThis = true + ..name = 'myInt') + ]) + ..optionalParameters.addAll([ + Parameter((p) => p + ..toThis = true + ..named = true + ..required = true + ..name = 'myString') + ]))) + ..fields.addAll([ + Field((f) => f + ..modifier = FieldModifier.final$ + ..type = refer('int?') + ..name = 'myInt'), + Field((f) => f + ..modifier = FieldModifier.final$ + ..type = refer('String?') + ..name = 'myString') + ]) + ..values.addAll([ + EnumValue((v) => v..name = 'a'), + EnumValue((v) => v + ..name = 'b' + ..arguments.addAll([ + literalNum(1), + ]) + ..namedArguments.addAll({ + 'myString': literalString('abc'), + })), + EnumValue((v) => v..name = 'c'), + ])); + expect(myEnum, equalsDart(''' + enum MyEnum { + a, + b(1, myString: 'abc'), + c; + + const MyEnum( + this.myInt, + {required this.myString, } + ); + + final int? myInt; + + final String? myString; + } + ''')); + }); } From b99939429138d217360dc4b2bb90472b6f0b8ee7 Mon Sep 17 00:00:00 2001 From: Snehal Singh <53808476+Snehal-Singh174@users.noreply.github.com> Date: Thu, 22 Jun 2023 22:59:23 +0530 Subject: [PATCH 241/271] Add support for external keyword on fields (dart-lang/code_builder#422) Add `external` field to `FieldBuilder` and emit the keyword in the visitor. --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/emitter.dart | 3 +++ pkgs/code_builder/lib/src/specs/field.dart | 6 ++++++ pkgs/code_builder/lib/src/specs/field.g.dart | 22 ++++++++++++++++++++ pkgs/code_builder/test/specs/field_test.dart | 14 +++++++++++++ 5 files changed, 46 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 0099280f5..0d14fcbfd 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ ## 4.6.0-wip * Add support for named arguments in `enum` classes +* Add support for external keyword on fields. ## 4.5.0 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 972381e78..2a84a0b35 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -386,6 +386,9 @@ class DartEmitter extends Object if (spec.late && _useNullSafetySyntax) { output.write('late '); } + if (spec.external) { + output.write('external '); + } switch (spec.modifier) { case FieldModifier.var$: if (spec.type == null) { diff --git a/pkgs/code_builder/lib/src/specs/field.dart b/pkgs/code_builder/lib/src/specs/field.dart index 9bdf01a1e..7930bf6fa 100644 --- a/pkgs/code_builder/lib/src/specs/field.dart +++ b/pkgs/code_builder/lib/src/specs/field.dart @@ -41,6 +41,9 @@ abstract class Field extends Object /// Whether this field should be prefixed with `late`. bool get late; + /// Whether the field should be prefixed with `external`. + bool get external; + /// Name of the field. String get name; @@ -86,6 +89,9 @@ abstract class FieldBuilder extends Object /// Whether this field should be prefixed with `late`. bool late = false; + /// Whether the field should be prefixed with `external`. + bool external = false; + /// Name of the field. String? name; diff --git a/pkgs/code_builder/lib/src/specs/field.g.dart b/pkgs/code_builder/lib/src/specs/field.g.dart index c8e9f05b0..d15f1c7dc 100644 --- a/pkgs/code_builder/lib/src/specs/field.g.dart +++ b/pkgs/code_builder/lib/src/specs/field.g.dart @@ -18,6 +18,8 @@ class _$Field extends Field { @override final bool late; @override + final bool external; + @override final String name; @override final Reference? type; @@ -33,6 +35,7 @@ class _$Field extends Field { this.assignment, required this.static, required this.late, + required this.external, required this.name, this.type, required this.modifier}) @@ -41,6 +44,7 @@ class _$Field extends Field { BuiltValueNullFieldError.checkNotNull(docs, r'Field', 'docs'); BuiltValueNullFieldError.checkNotNull(static, r'Field', 'static'); BuiltValueNullFieldError.checkNotNull(late, r'Field', 'late'); + BuiltValueNullFieldError.checkNotNull(external, r'Field', 'external'); BuiltValueNullFieldError.checkNotNull(name, r'Field', 'name'); BuiltValueNullFieldError.checkNotNull(modifier, r'Field', 'modifier'); } @@ -61,6 +65,7 @@ class _$Field extends Field { assignment == other.assignment && static == other.static && late == other.late && + external == other.external && name == other.name && type == other.type && modifier == other.modifier; @@ -74,6 +79,7 @@ class _$Field extends Field { _$hash = $jc(_$hash, assignment.hashCode); _$hash = $jc(_$hash, static.hashCode); _$hash = $jc(_$hash, late.hashCode); + _$hash = $jc(_$hash, external.hashCode); _$hash = $jc(_$hash, name.hashCode); _$hash = $jc(_$hash, type.hashCode); _$hash = $jc(_$hash, modifier.hashCode); @@ -89,6 +95,7 @@ class _$Field extends Field { ..add('assignment', assignment) ..add('static', static) ..add('late', late) + ..add('external', external) ..add('name', name) ..add('type', type) ..add('modifier', modifier)) @@ -159,6 +166,18 @@ class _$FieldBuilder extends FieldBuilder { super.late = late; } + @override + bool get external { + _$this; + return super.external; + } + + @override + set external(bool external) { + _$this; + super.external = external; + } + @override String? get name { _$this; @@ -205,6 +224,7 @@ class _$FieldBuilder extends FieldBuilder { super.assignment = $v.assignment; super.static = $v.static; super.late = $v.late; + super.external = $v.external; super.name = $v.name; super.type = $v.type; super.modifier = $v.modifier; @@ -239,6 +259,8 @@ class _$FieldBuilder extends FieldBuilder { static, r'Field', 'static'), late: BuiltValueNullFieldError.checkNotNull(late, r'Field', 'late'), + external: BuiltValueNullFieldError.checkNotNull( + external, r'Field', 'external'), name: BuiltValueNullFieldError.checkNotNull(name, r'Field', 'name'), type: type, diff --git a/pkgs/code_builder/test/specs/field_test.dart b/pkgs/code_builder/test/specs/field_test.dart index 90cc65aa0..3d53687bc 100644 --- a/pkgs/code_builder/test/specs/field_test.dart +++ b/pkgs/code_builder/test/specs/field_test.dart @@ -96,4 +96,18 @@ void main() { '''), ); }); + + test('should create a external field', () { + expect( + Field((b) => b + ..name = 'value' + ..external = true + ..type = refer('double') + ..annotations.addAll([refer('Float').call([])])), + equalsDart(r''' + @Float() + external double value; + '''), + ); + }); } From 6cfff6fa41c27353e0ebeafaae445e5a09cd5389 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 17:20:05 +0000 Subject: [PATCH 242/271] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/code_builder#423) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 8e2b0507b..64822e2ae 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 321344404008bc47ef59fa2aba035e666e3a8126 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 7 Aug 2023 09:05:54 -0700 Subject: [PATCH 243/271] Add Expression.parenthesized (dart-lang/code_builder#425) We use `ParenthesizedExpression` internally in a few places where it's know that they are required, but some corners of the syntax require extra parenthesis in ways that are not feasible to detect in this library. Allow for explicit manual parenthesis. --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/code_builder.dart | 1 + pkgs/code_builder/lib/src/specs/expression.dart | 3 +++ pkgs/code_builder/test/specs/code/expression_test.dart | 9 +++++++++ 4 files changed, 14 insertions(+) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 0d14fcbfd..0c5f78d3d 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -2,6 +2,7 @@ * Add support for named arguments in `enum` classes * Add support for external keyword on fields. +* Add `Expression.parenthesized` to manually wrap an expression in parenthesis. ## 4.5.0 diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 6cfaf6add..c98e19ed7 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -25,6 +25,7 @@ export 'src/specs/expression.dart' InvokeExpressionType, LiteralExpression, LiteralListExpression, + ParenthesizedExpression, ToCodeExpression, declareConst, declareFinal, diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 275404e10..1b925577b 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -331,6 +331,9 @@ abstract class Expression implements Spec { /// May be overridden to support other types implementing [Expression]. @visibleForOverriding Expression get expression => this; + + /// Returns this expression wrapped in parenthesis. + ParenthesizedExpression get parenthesized => ParenthesizedExpression._(this); } /// Declare a const variable named [variableName]. diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 2f2576abc..7e2ee0125 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -731,4 +731,13 @@ void main() { .assign(refer('bar')), equalsDart('late String foo = bar')); }); + + test('should emit a perenthesized epression', () { + expect( + refer('foo').ifNullThen(refer('FormatException') + .newInstance([literalString('missing foo')]) + .thrown + .parenthesized), + equalsDart('foo ?? (throw FormatException(\'missing foo\'))')); + }); } From 07d0ceeab3d44ce15a244d5cabddc15451a00426 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 29 Aug 2023 17:12:20 -0700 Subject: [PATCH 244/271] Prepare to publish (dart-lang/code_builder#426) Drop the version suffix. --- pkgs/code_builder/CHANGELOG.md | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 0c5f78d3d..6926dcc71 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 4.6.0-wip +## 4.6.0 * Add support for named arguments in `enum` classes * Add support for external keyword on fields. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 9ddf19080..2a0938470 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.6.0-wip +version: 4.6.0 description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder From 3b1b97a3bb614ef45885cbb896e4c4dcca289742 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 17:36:43 +0000 Subject: [PATCH 245/271] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/code_builder#428) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 64822e2ae..913b96001 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From a868026697d1aae17a9bdf6dea5372cd4b751db8 Mon Sep 17 00:00:00 2001 From: Moritz Date: Mon, 25 Sep 2023 13:50:35 +0200 Subject: [PATCH 246/271] Update emitter.dart (dart-lang/code_builder#429) * Update emitter.dart Add a newline after lambdas. * Rev version * Fix typo --- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/lib/src/emitter.dart | 2 +- pkgs/code_builder/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 6926dcc71..862931db9 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.7.0 + +* Add a newline after lambdas. + ## 4.6.0 * Add support for named arguments in `enum` classes diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 2a84a0b35..79b0e0db7 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -164,7 +164,7 @@ class DartEmitter extends Object for (var m in spec.methods) { visitMethod(m, out); if (_isLambdaMethod(m)) { - out.write(';'); + out.writeln(';'); } out.writeln(); } diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 2a0938470..03ba27cf7 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.6.0 +version: 4.7.0 description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder From 8f0288374ad144fb8f4998c6e7a739a3d02b775b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 17:19:21 +0000 Subject: [PATCH 247/271] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/code_builder#431) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.0&new-version=1.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 913b96001..8bf07ddd7 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -46,7 +46,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From 7138fff60e4621c3e1eb609851ca88558bee69f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:38:41 +0000 Subject: [PATCH 248/271] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/code_builder#432) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 8bf07ddd7..67a6b0850 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 48e368fc2b4d6c990893a25b848f7cf2abf94ffb Mon Sep 17 00:00:00 2001 From: Klemen Tusar Date: Mon, 2 Oct 2023 22:51:18 +0100 Subject: [PATCH 249/271] Add missing operator and assignment expressions (dart-lang/code_builder#427) Add operators - `operatorIntDivide` - `operatorUnaryPrefixIncrement` - `operatorUnaryPostfixIncrement` - `operatorUnaryMinus` - `operatorUnaryPrefixDecrement` - `operatorUnaryPostfixDecrement` - `operatorBitwiseAnd` - `operatorBitwiseOr` - `operatorBitwiseXor` - `operatorUnaryBitwiseComplement` - `operatorShiftLeft` - `operatorShiftRight` - `operatorShiftRightUnsigned` Add compound assignments - `addAssign` - `subtractAssign` - `multiplyAssign` - `divideAssign` - `intDivideAssign` - `euclideanModuloAssign` - `shiftLeftAssign` - `shiftRightAssign` - `shiftRightUnsignedAssign` - `bitwiseAndAssign` - `bitwiseXorAssign` - `bitwiseOrAssign` Deprecate misnamed `operatorSubstract` method, add `operatorSubtract`. --- pkgs/code_builder/CHANGELOG.md | 30 ++++ .../lib/src/specs/expression.dart | 106 ++++++++++- pkgs/code_builder/pubspec.yaml | 2 +- .../test/specs/code/expression_test.dart | 166 ++++++++++++++++++ 4 files changed, 301 insertions(+), 3 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 862931db9..9a6c3101c 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,33 @@ +## 4.8.0-wip + +* Add `Expression.operatorSubtract` +* Deprecate `Expression.operatorSubstract` +* Add `Expression.operatorIntDivide` +* Add `Expression.operatorUnaryPrefixIncrement` +* Add `Expression.operatorUnaryPostfixIncrement` +* Add `Expression.operatorUnaryMinus` +* Add `Expression.operatorUnaryPrefixDecrement` +* Add `Expression.operatorUnaryPostfixDecrement` +* Add `Expression.operatorBitwiseAnd` +* Add `Expression.operatorBitwiseOr` +* Add `Expression.operatorBitwiseXor` +* Add `Expression.operatorUnaryBitwiseComplement` +* Add `Expression.operatorShiftLeft` +* Add `Expression.operatorShiftRight` +* Add `Expression.operatorShiftRightUnsigned` +* Add `Expression.addAssign` +* Add `Expression.subtractAssign` +* Add `Expression.multiplyAssign` +* Add `Expression.divideAssign` +* Add `Expression.intDivideAssign` +* Add `Expression.euclideanModuloAssign` +* Add `Expression.shiftLeftAssign` +* Add `Expression.shiftRightAssign` +* Add `Expression.shiftRightUnsignedAssign` +* Add `Expression.bitwiseAndAssign` +* Add `Expression.bitwiseXorAssign` +* Add `Expression.bitwiseOrAssign` + ## 4.7.0 * Add a newline after lambdas. diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 1b925577b..093362740 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -147,13 +147,15 @@ abstract class Expression implements Spec { ); /// Returns the result of `this` `-` [other]. - // TODO(kevmoo): create a function spelled correctly and deprecate this one! - Expression operatorSubstract(Expression other) => BinaryExpression._( + Expression operatorSubtract(Expression other) => BinaryExpression._( expression, other, '-', ); + @Deprecated('Use `operatorSubtract` instead') + Expression operatorSubstract(Expression other) => operatorSubtract(other); + /// Returns the result of `this` `/` [other]. Expression operatorDivide(Expression other) => BinaryExpression._( expression, @@ -175,6 +177,10 @@ abstract class Expression implements Spec { '%', ); + /// Returns the result of `this` `~/` [other]. + Expression operatorIntDivide(Expression other) => + BinaryExpression._(expression, other, '~/'); + Expression conditional(Expression whenTrue, Expression whenFalse) => BinaryExpression._( expression, @@ -189,10 +195,106 @@ abstract class Expression implements Spec { 'await', ); + /// Returns the result of `++this`. + Expression operatorUnaryPrefixIncrement() => + BinaryExpression._(_empty, expression, '++', addSpace: false); + + /// Return the result of `this++`. + Expression operatorUnaryPostfixIncrement() => + BinaryExpression._(expression, _empty, '++', addSpace: false); + + /// Returns the result of `-this`. + Expression operatorUnaryMinus() => + BinaryExpression._(_empty, expression, '-', addSpace: false); + + /// Returns the result of `--this`. + Expression operatorUnaryPrefixDecrement() => + BinaryExpression._(_empty, expression, '--', addSpace: false); + + /// Return the result of `this--`. + Expression operatorUnaryPostfixDecrement() => + BinaryExpression._(expression, _empty, '--', addSpace: false); + + /// Returns the result of `this` `&` [other]. + Expression operatorBitwiseAnd(Expression other) => + BinaryExpression._(expression, other, '&'); + + /// Returns the result of `this` `|` [other]. + Expression operatorBitwiseOr(Expression other) => + BinaryExpression._(expression, other, '|'); + + /// Returns the result of `this` `^` [other]. + Expression operatorBitwiseXor(Expression other) => + BinaryExpression._(expression, other, '^'); + + /// Returns the result of `~this`. + Expression operatorUnaryBitwiseComplement() => + BinaryExpression._(_empty, expression, '~', addSpace: false); + + /// Returns the result of `this` `<<` [other]. + Expression operatorShiftLeft(Expression other) => + BinaryExpression._(expression, other, '<<'); + + /// Returns the result of `this` `>>` [other]. + Expression operatorShiftRight(Expression other) => + BinaryExpression._(expression, other, '>>'); + + /// Returns the result of `this` `>>>` [other]. + Expression operatorShiftRightUnsigned(Expression other) => + BinaryExpression._(expression, other, '>>>'); + /// Return `{this} = {other}`. Expression assign(Expression other) => BinaryExpression._(this, other, '=', isConst: isConst); + /// Return `this` += [other]. + Expression addAssign(Expression other) => + BinaryExpression._(this, other, '+='); + + /// Return `this` -= [other]. + Expression subtractAssign(Expression other) => + BinaryExpression._(this, other, '-='); + + /// Return `this` *= [other]. + Expression multiplyAssign(Expression other) => + BinaryExpression._(this, other, '*='); + + /// Return `this` /= [other]. + Expression divideAssign(Expression other) => + BinaryExpression._(this, other, '/='); + + /// Return `this` ~/= [other]. + Expression intDivideAssign(Expression other) => + BinaryExpression._(this, other, '~/='); + + /// Return `this` %= [other]. + Expression euclideanModuloAssign(Expression other) => + BinaryExpression._(this, other, '%='); + + /// Return `this` <<= [other]. + Expression shiftLeftAssign(Expression other) => + BinaryExpression._(this, other, '<<='); + + /// Return `this` >>= [other]. + Expression shiftRightAssign(Expression other) => + BinaryExpression._(this, other, '>>='); + + /// Return `this` >>>= [other]. + Expression shiftRightUnsignedAssign(Expression other) => + BinaryExpression._(this, other, '>>>='); + + /// Return `this` &= [other]. + Expression bitwiseAndAssign(Expression other) => + BinaryExpression._(this, other, '&='); + + /// Return `this` ^= [other]. + Expression bitwiseXorAssign(Expression other) => + BinaryExpression._(this, other, '^='); + + /// Return `this` |= [other]. + Expression bitwiseOrAssign(Expression other) => + BinaryExpression._(this, other, '|='); + /// Return `{this} ?? {other}`. Expression ifNullThen(Expression other) => BinaryExpression._( this, diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 03ba27cf7..6d490c109 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.7.0 +version: 4.8.0-wip description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 7e2ee0125..16b52aec6 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -650,8 +650,14 @@ void main() { }); test('should emit an operator subtract call', () { + // ignore: deprecated_member_use_from_same_package expect(refer('foo').operatorSubstract(refer('foo2')), equalsDart('foo - foo2')); + + expect( + refer('foo').operatorSubtract(refer('foo2')), + equalsDart('foo - foo2'), + ); }); test('should emit an operator divide call', () { @@ -669,6 +675,82 @@ void main() { equalsDart('foo % foo2')); }); + test('should emit an operator int divide call', () { + expect( + refer('foo').operatorIntDivide(refer('foo2')), + equalsDart('foo ~/ foo2'), + ); + }); + + test('should emit a unary prefix increment operator call', () { + expect(refer('foo').operatorUnaryPrefixIncrement(), equalsDart('++foo')); + }); + + test('should emit a unary postfix increment operator call', () { + expect(refer('foo').operatorUnaryPostfixIncrement(), equalsDart('foo++')); + }); + + test('should emit a unary prefix minus operator call', () { + expect(refer('foo').operatorUnaryMinus(), equalsDart('-foo')); + }); + + test('should emit a unary prefix decrement operator call', () { + expect(refer('foo').operatorUnaryPrefixDecrement(), equalsDart('--foo')); + }); + + test('should emit a unary postfix decrement operator call', () { + expect(refer('foo').operatorUnaryPostfixDecrement(), equalsDart('foo--')); + }); + + test('should emit a bitwise AND operator call', () { + expect( + refer('foo').operatorBitwiseAnd(refer('foo2')), + equalsDart('foo & foo2'), + ); + }); + + test('should emit a bitwise OR operator call', () { + expect( + refer('foo').operatorBitwiseOr(refer('foo2')), + equalsDart('foo | foo2'), + ); + }); + + test('should emit a bitwise XOR operator call', () { + expect( + refer('foo').operatorBitwiseXor(refer('foo2')), + equalsDart('foo ^ foo2'), + ); + }); + + test('should emit a unary bitwise complement operator call', () { + expect( + refer('foo').operatorUnaryBitwiseComplement(), + equalsDart('~foo'), + ); + }); + + test('should emit a shift left operator call', () { + expect( + refer('foo').operatorShiftLeft(refer('foo2')), + equalsDart('foo << foo2'), + ); + }); + + test('should emit a shift right operator call', () { + expect( + refer('foo').operatorShiftRight(refer('foo2')), + equalsDart('foo >> foo2'), + ); + }); + + test('should emit a shift right unsigned operator call', () { + expect( + refer('foo').operatorShiftRightUnsigned(refer('foo2')), + equalsDart('foo >>> foo2'), + ); + }); + test('should emit a const variable declaration', () { expect(declareConst('foo').assign(refer('bar')), equalsDart('const foo = bar')); @@ -740,4 +822,88 @@ void main() { .parenthesized), equalsDart('foo ?? (throw FormatException(\'missing foo\'))')); }); + + test('should emit an addition assigment expression', () { + expect( + refer('foo').addAssign(refer('bar')), + equalsDart('foo += bar'), + ); + }); + + test('should emit a subtraction assigment expression', () { + expect( + refer('foo').subtractAssign(refer('bar')), + equalsDart('foo -= bar'), + ); + }); + + test('should emit a multiplication assigment expression', () { + expect( + refer('foo').multiplyAssign(refer('bar')), + equalsDart('foo *= bar'), + ); + }); + + test('should emit a division assigment expression', () { + expect( + refer('foo').divideAssign(refer('bar')), + equalsDart('foo /= bar'), + ); + }); + + test('should emit an int division assigment expression', () { + expect( + refer('foo').intDivideAssign(refer('bar')), + equalsDart('foo ~/= bar'), + ); + }); + + test('should emit a euclidean modulo assigment expression', () { + expect( + refer('foo').euclideanModuloAssign(refer('bar')), + equalsDart('foo %= bar'), + ); + }); + + test('should emit a shift left assigment expression', () { + expect( + refer('foo').shiftLeftAssign(refer('bar')), + equalsDart('foo <<= bar'), + ); + }); + + test('should emit a shift right assigment expression', () { + expect( + refer('foo').shiftRightAssign(refer('bar')), + equalsDart('foo >>= bar'), + ); + }); + + test('should emit a shift right unsigned assigment expression', () { + expect( + refer('foo').shiftRightUnsignedAssign(refer('bar')), + equalsDart('foo >>>= bar'), + ); + }); + + test('should emit a bitwise AND assigment expression', () { + expect( + refer('foo').bitwiseAndAssign(refer('bar')), + equalsDart('foo &= bar'), + ); + }); + + test('should emit a bitwise XOR assigment expression', () { + expect( + refer('foo').bitwiseXorAssign(refer('bar')), + equalsDart('foo ^= bar'), + ); + }); + + test('should emit a bitwise OR assigment expression', () { + expect( + refer('foo').bitwiseOrAssign(refer('bar')), + equalsDart('foo |= bar'), + ); + }); } From b7d6b21337beec9e3bba871a2e4be7b945109ac6 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 5 Oct 2023 12:14:41 -0700 Subject: [PATCH 250/271] Allow passing an `Expression` through `literal` (dart-lang/code_builder#433) The `LiteralListExpression` allows a mix of Dart values which could be passed to `literal` and values which are already a `Spec` (typically an `Expression`). Both types are handled by `_acceptLiteral` in the visitor implementation. https://github.com/dart-lang/code_builder/blob/48e368fc2b4d6c990893a25b848f7cf2abf94ffb/lib/src/specs/expression.dart#L622-L628 The `toString()` for `LiteralListExpression` calls `literal` on each value in the list, which previously would throw if it was passed an `Expression`. Some tests for builders and their implementation details use `.toString()` in their user facing failure messages. When there is an exception creating the message for a failure, it can mask the cause of the failure. Allow more flexibility for this `toString` by allowing `Expression` instances to flow through `literal` unchanged. This still does not handle non-expression `Spec` instances, but those are not likely to come up in practice. Collapse the conditional returns in `literal` to a single line each. The pattern is easier to read with less vertical space. Add tests for `literal` passing each type it accepts, and a test for the error behavior. Add a regression test for the `toString` of a list literal not throwing when one of the values of the list is an `Expression`. --- pkgs/code_builder/CHANGELOG.md | 1 + .../lib/src/specs/expression/literal.dart | 37 ++++++--------- .../test/specs/code/expression_test.dart | 46 +++++++++++++++++++ 3 files changed, 60 insertions(+), 24 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 9a6c3101c..5db7a2f8a 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -27,6 +27,7 @@ * Add `Expression.bitwiseAndAssign` * Add `Expression.bitwiseXorAssign` * Add `Expression.bitwiseOrAssign` +* Allow passing an `Expression` through `literal` without an exception. ## 4.7.0 diff --git a/pkgs/code_builder/lib/src/specs/expression/literal.dart b/pkgs/code_builder/lib/src/specs/expression/literal.dart index a305fa623..ced6cf90f 100644 --- a/pkgs/code_builder/lib/src/specs/expression/literal.dart +++ b/pkgs/code_builder/lib/src/specs/expression/literal.dart @@ -6,32 +6,21 @@ part of '../expression.dart'; /// Converts a runtime Dart [literal] value into an [Expression]. /// +/// Supported Dart types are translated into literal expressions. +/// If the [literal] is already an [Expression] it is returned without change to +/// allow operating on a collection of mixed simple literals and more complex +/// expressions. /// Unsupported inputs invoke the [onError] callback. Expression literal(Object? literal, {Expression Function(Object)? onError}) { - if (literal is bool) { - return literalBool(literal); - } - if (literal is num) { - return literalNum(literal); - } - if (literal is String) { - return literalString(literal); - } - if (literal is List) { - return literalList(literal); - } - if (literal is Set) { - return literalSet(literal); - } - if (literal is Map) { - return literalMap(literal); - } - if (literal == null) { - return literalNull; - } - if (onError != null) { - return onError(literal); - } + if (literal is Expression) return literal; + if (literal is bool) return literalBool(literal); + if (literal is num) return literalNum(literal); + if (literal is String) return literalString(literal); + if (literal is List) return literalList(literal); + if (literal is Set) return literalSet(literal); + if (literal is Map) return literalMap(literal); + if (literal == null) return literalNull; + if (onError != null) return onError(literal); throw UnsupportedError('Not a supported literal type: $literal.'); } diff --git a/pkgs/code_builder/test/specs/code/expression_test.dart b/pkgs/code_builder/test/specs/code/expression_test.dart index 16b52aec6..4ce9ebaf5 100644 --- a/pkgs/code_builder/test/specs/code/expression_test.dart +++ b/pkgs/code_builder/test/specs/code/expression_test.dart @@ -14,6 +14,48 @@ void main() { expect(literalNull, equalsDart('null')); }); + group('literal', () { + test('forwards values that are already expressions', () { + expect(literal(refer('foo')), equalsDart('foo')); + expect(literal([refer('foo')]), equalsDart('[foo]')); + }); + group('wraps', () { + test('bool values', () { + expect(literal(true), equalsDart('true')); + }); + test('numeric values', () { + expect(literal(1), equalsDart('1')); + expect(literal(1.0), equalsDart('1.0')); + }); + test('string values', () { + expect(literal('foo'), equalsDart("'foo'")); + }); + test('list values', () { + expect(literal([1]), equalsDart('[1]')); + }); + test('set values', () { + expect(literal({1}), equalsDart('{1}')); + }); + test('map values', () { + expect(literal({'foo': 1}), equalsDart("{'foo': 1}")); + }); + test('null', () { + expect(literal(null), equalsDart('null')); + }); + }); + test('uses `onError` for unhandled types', () { + expect( + literal(Uri.https('google.com'), onError: (value) { + if (value is Uri) { + return refer('Uri') + .newInstanceNamed('parse', [literalString(value.toString())]); + } + throw UnsupportedError('Not supported: $value'); + }), + equalsDart("Uri.parse('https://google.com')")); + }); + }); + test('should emit a String', () { expect(literalString(r'$monkey'), equalsDart(r"'$monkey'")); }); @@ -126,6 +168,10 @@ void main() { ); }); + test('can toString a list literal with an expression as a value', () { + expect(literalList([refer('foo')]).toString, isNot(throwsA(anything))); + }); + test('should emit a set of other literals and expressions', () { expect( // ignore: prefer_collection_literals From dadaaae6f1a9eba534cef723f26dd122bf1b3ef0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 17:37:44 +0000 Subject: [PATCH 251/271] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/code_builder#434) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 67a6b0850..94513827d 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From b9d06e6236e2677fae5fd4dbacd297b91b84ffef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 17:58:05 +0000 Subject: [PATCH 252/271] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/code_builder#435) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 94513827d..a2666f720 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -46,7 +46,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From baa3ea1463fa0633261fa203db9c61497f0ddf39 Mon Sep 17 00:00:00 2001 From: Srujan Gaddam <58529443+srujzs@users.noreply.github.com> Date: Mon, 20 Nov 2023 12:45:36 -0800 Subject: [PATCH 253/271] Add support for extension types (dart-lang/code_builder#437) Corresponds to the syntax defined in https://github.com/dart-lang/language/blob/main/accepted/future-releases/extension-types/feature-specification.md#syntax. --- .../.github/workflows/test-package.yml | 2 +- pkgs/code_builder/CHANGELOG.md | 4 +- pkgs/code_builder/lib/code_builder.dart | 1 + pkgs/code_builder/lib/src/emitter.dart | 57 ++ .../lib/src/mixins/annotations.dart | 4 +- pkgs/code_builder/lib/src/mixins/dartdoc.dart | 4 +- .../code_builder/lib/src/mixins/generics.dart | 4 +- pkgs/code_builder/lib/src/specs/code.dart | 2 +- .../lib/src/specs/expression.dart | 3 +- .../lib/src/specs/extension_type.dart | 152 +++++ .../lib/src/specs/extension_type.g.dart | 537 ++++++++++++++++++ pkgs/code_builder/lib/src/visitors.dart | 3 + pkgs/code_builder/pubspec.yaml | 6 +- .../test/specs/extension_test.dart | 21 - .../test/specs/extension_type_test.dart | 247 ++++++++ 15 files changed, 1013 insertions(+), 34 deletions(-) create mode 100644 pkgs/code_builder/lib/src/specs/extension_type.dart create mode 100644 pkgs/code_builder/lib/src/specs/extension_type.g.dart create mode 100644 pkgs/code_builder/test/specs/extension_type_test.dart diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index a2666f720..5a327cf2e 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [2.19.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 5db7a2f8a..c216a928d 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,4 +1,4 @@ -## 4.8.0-wip +## 4.8.0 * Add `Expression.operatorSubtract` * Deprecate `Expression.operatorSubstract` @@ -28,6 +28,8 @@ * Add `Expression.bitwiseXorAssign` * Add `Expression.bitwiseOrAssign` * Allow passing an `Expression` through `literal` without an exception. +* Add support for extension types. +* Update SDK version constraints to `>=3.0.0`. ## 4.7.0 diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index c98e19ed7..17a11ef3f 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -48,6 +48,7 @@ export 'src/specs/expression.dart' literalString, literalTrue; export 'src/specs/extension.dart' show Extension, ExtensionBuilder; +export 'src/specs/extension_type.dart' show ExtensionType, ExtensionTypeBuilder; export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; export 'src/specs/library.dart' show Library, LibraryBuilder; export 'src/specs/method.dart' diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 79b0e0db7..591b992cf 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -11,6 +11,7 @@ import 'specs/directive.dart'; import 'specs/enum.dart'; import 'specs/expression.dart'; import 'specs/extension.dart'; +import 'specs/extension_type.dart'; import 'specs/field.dart'; import 'specs/library.dart'; import 'specs/method.dart'; @@ -336,6 +337,62 @@ class DartEmitter extends Object return out; } + @override + StringSink visitExtensionType(ExtensionType spec, [StringSink? output]) { + final out = output ??= StringBuffer(); + spec.docs.forEach(out.writeln); + for (var a in spec.annotations) { + visitAnnotation(a, out); + } + + out.write('extension type '); + if (spec.constant) out.write('const '); + out.write(spec.name); + visitTypeParameters(spec.types.map((r) => r.type), out); + if (spec.primaryConstructorName.isNotEmpty) { + out.write('.${spec.primaryConstructorName}'); + } + out.write('('); + _visitRepresentationDeclaration(spec.representationDeclaration, out); + out.write(')'); + + if (spec.implements.isNotEmpty) { + out + ..write(' implements ') + ..writeAll( + spec.implements.map((m) => m.type.accept(this)), ','); + } + + out.writeln(' {'); + for (var c in spec.constructors) { + visitConstructor(c, spec.name, out); + out.writeln(); + } + for (var f in spec.fields) { + visitField(f, out); + out.writeln(); + } + for (var m in spec.methods) { + visitMethod(m, out); + if (_isLambdaMethod(m)) { + out.writeln(';'); + } + out.writeln(); + } + out.writeln('}'); + return out; + } + + void _visitRepresentationDeclaration( + RepresentationDeclaration spec, StringSink out) { + spec.docs.forEach(out.writeln); + for (var a in spec.annotations) { + visitAnnotation(a, out); + } + spec.declaredRepresentationType.accept(this, out); + out.write(' ${spec.name}'); + } + @override StringSink visitDirective(Directive spec, [StringSink? output]) { output ??= StringBuffer(); diff --git a/pkgs/code_builder/lib/src/mixins/annotations.dart b/pkgs/code_builder/lib/src/mixins/annotations.dart index b4b3be284..7ce6a20b9 100644 --- a/pkgs/code_builder/lib/src/mixins/annotations.dart +++ b/pkgs/code_builder/lib/src/mixins/annotations.dart @@ -7,13 +7,13 @@ import 'package:built_collection/built_collection.dart'; import '../specs/expression.dart'; /// A type of AST node that can have metadata [annotations]. -abstract class HasAnnotations { +abstract mixin class HasAnnotations { /// Annotations as metadata on the node. BuiltList get annotations; } /// Compliment to the [HasAnnotations] mixin for metadata [annotations]. -abstract class HasAnnotationsBuilder { +abstract mixin class HasAnnotationsBuilder { /// Annotations as metadata on the node. abstract ListBuilder annotations; } diff --git a/pkgs/code_builder/lib/src/mixins/dartdoc.dart b/pkgs/code_builder/lib/src/mixins/dartdoc.dart index 52d69c04a..78144f6fd 100644 --- a/pkgs/code_builder/lib/src/mixins/dartdoc.dart +++ b/pkgs/code_builder/lib/src/mixins/dartdoc.dart @@ -4,12 +4,12 @@ import 'package:built_collection/built_collection.dart'; -abstract class HasDartDocs { +abstract mixin class HasDartDocs { /// Dart docs. BuiltList get docs; } -abstract class HasDartDocsBuilder { +abstract mixin class HasDartDocsBuilder { /// Dart docs. abstract ListBuilder docs; } diff --git a/pkgs/code_builder/lib/src/mixins/generics.dart b/pkgs/code_builder/lib/src/mixins/generics.dart index 51aae63f6..b18a858c3 100644 --- a/pkgs/code_builder/lib/src/mixins/generics.dart +++ b/pkgs/code_builder/lib/src/mixins/generics.dart @@ -6,12 +6,12 @@ import 'package:built_collection/built_collection.dart'; import '../specs/reference.dart'; -abstract class HasGenerics { +abstract mixin class HasGenerics { /// Generic type parameters. BuiltList get types; } -abstract class HasGenericsBuilder { +abstract mixin class HasGenericsBuilder { /// Generic type parameters. abstract ListBuilder types; } diff --git a/pkgs/code_builder/lib/src/specs/code.dart b/pkgs/code_builder/lib/src/specs/code.dart index 5cc52f5e7..521eb1fe0 100644 --- a/pkgs/code_builder/lib/src/specs/code.dart +++ b/pkgs/code_builder/lib/src/specs/code.dart @@ -87,7 +87,7 @@ abstract class CodeVisitor implements SpecVisitor { } /// Knowledge of how to write valid Dart code from [CodeVisitor]. -abstract class CodeEmitter implements CodeVisitor { +abstract mixin class CodeEmitter implements CodeVisitor { @protected Allocator get allocator; diff --git a/pkgs/code_builder/lib/src/specs/expression.dart b/pkgs/code_builder/lib/src/specs/expression.dart index 093362740..b9193e6f3 100644 --- a/pkgs/code_builder/lib/src/specs/expression.dart +++ b/pkgs/code_builder/lib/src/specs/expression.dart @@ -526,7 +526,8 @@ abstract class ExpressionVisitor implements SpecVisitor { /// Knowledge of how to write valid Dart code from [ExpressionVisitor]. /// /// **INTERNAL ONLY**. -abstract class ExpressionEmitter implements ExpressionVisitor { +abstract mixin class ExpressionEmitter + implements ExpressionVisitor { @override StringSink visitToCodeExpression(ToCodeExpression expression, [StringSink? output]) { diff --git a/pkgs/code_builder/lib/src/specs/extension_type.dart b/pkgs/code_builder/lib/src/specs/extension_type.dart new file mode 100644 index 000000000..ec3bd3355 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/extension_type.dart @@ -0,0 +1,152 @@ +// Copyright (c) 2023, 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:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; +import 'package:meta/meta.dart'; + +import '../base.dart'; +import '../mixins/annotations.dart'; +import '../mixins/dartdoc.dart'; +import '../mixins/generics.dart'; +import '../visitors.dart'; +import 'constructor.dart'; +import 'expression.dart'; +import 'field.dart'; +import 'method.dart'; +import 'reference.dart'; + +part 'extension_type.g.dart'; + +@immutable +abstract class ExtensionType extends Object + with HasAnnotations, HasDartDocs, HasGenerics + implements Built, Spec { + factory ExtensionType([void Function(ExtensionTypeBuilder)? updates]) = + _$ExtensionType; + + ExtensionType._(); + + @override + BuiltList get annotations; + + @override + BuiltList get docs; + + /// Whether this extension type is declared as `const`. + bool get constant; + + String get name; + + @override + BuiltList get types; + + /// Name of the extension type's primary constructor. An empty string + /// will make it unnamed. + String get primaryConstructorName; + + RepresentationDeclaration get representationDeclaration; + + BuiltList get implements; + + BuiltList get constructors; + + BuiltList get fields; + + BuiltList get methods; + + @override + R accept( + SpecVisitor visitor, [ + R? context, + ]) => + visitor.visitExtensionType(this, context); +} + +abstract class ExtensionTypeBuilder extends Object + with HasAnnotationsBuilder, HasDartDocsBuilder, HasGenericsBuilder + implements Builder { + factory ExtensionTypeBuilder() = _$ExtensionTypeBuilder; + + ExtensionTypeBuilder._(); + + @override + void update(void Function(ExtensionTypeBuilder)? updates) { + updates?.call(this); + } + + @override + ListBuilder annotations = ListBuilder(); + + @override + ListBuilder docs = ListBuilder(); + + /// Whether this extension type is declared as `const`. + bool constant = false; + + String? name; + + @override + ListBuilder types = ListBuilder(); + + /// Name of the extension type's primary constructor. An empty string + /// will make it unnamed. + String primaryConstructorName = ''; + + RepresentationDeclaration? representationDeclaration; + + ListBuilder implements = ListBuilder(); + + ListBuilder constructors = ListBuilder(); + + ListBuilder fields = ListBuilder(); + + ListBuilder methods = ListBuilder(); +} + +abstract class RepresentationDeclaration extends Object + with HasAnnotations, HasDartDocs + implements + Built { + factory RepresentationDeclaration( + [void Function(RepresentationDeclarationBuilder)? updates]) = + _$RepresentationDeclaration; + + RepresentationDeclaration._(); + + @override + BuiltList get annotations; + + @override + BuiltList get docs; + + Reference get declaredRepresentationType; + + String get name; +} + +abstract class RepresentationDeclarationBuilder extends Object + with HasAnnotationsBuilder, HasDartDocsBuilder + implements + Builder { + factory RepresentationDeclarationBuilder() = + _$RepresentationDeclarationBuilder; + + RepresentationDeclarationBuilder._(); + + @override + void update(void Function(RepresentationDeclarationBuilder)? updates) { + updates?.call(this); + } + + @override + ListBuilder annotations = ListBuilder(); + + @override + ListBuilder docs = ListBuilder(); + + Reference? declaredRepresentationType; + + String? name; +} diff --git a/pkgs/code_builder/lib/src/specs/extension_type.g.dart b/pkgs/code_builder/lib/src/specs/extension_type.g.dart new file mode 100644 index 000000000..576984032 --- /dev/null +++ b/pkgs/code_builder/lib/src/specs/extension_type.g.dart @@ -0,0 +1,537 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'extension_type.dart'; + +// ************************************************************************** +// BuiltValueGenerator +// ************************************************************************** + +class _$ExtensionType extends ExtensionType { + @override + final BuiltList annotations; + @override + final BuiltList docs; + @override + final bool constant; + @override + final String name; + @override + final BuiltList types; + @override + final String primaryConstructorName; + @override + final RepresentationDeclaration representationDeclaration; + @override + final BuiltList implements; + @override + final BuiltList constructors; + @override + final BuiltList fields; + @override + final BuiltList methods; + + factory _$ExtensionType([void Function(ExtensionTypeBuilder)? updates]) => + (new ExtensionTypeBuilder()..update(updates)).build() as _$ExtensionType; + + _$ExtensionType._( + {required this.annotations, + required this.docs, + required this.constant, + required this.name, + required this.types, + required this.primaryConstructorName, + required this.representationDeclaration, + required this.implements, + required this.constructors, + required this.fields, + required this.methods}) + : super._() { + BuiltValueNullFieldError.checkNotNull( + annotations, r'ExtensionType', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'ExtensionType', 'docs'); + BuiltValueNullFieldError.checkNotNull( + constant, r'ExtensionType', 'constant'); + BuiltValueNullFieldError.checkNotNull(name, r'ExtensionType', 'name'); + BuiltValueNullFieldError.checkNotNull(types, r'ExtensionType', 'types'); + BuiltValueNullFieldError.checkNotNull( + primaryConstructorName, r'ExtensionType', 'primaryConstructorName'); + BuiltValueNullFieldError.checkNotNull(representationDeclaration, + r'ExtensionType', 'representationDeclaration'); + BuiltValueNullFieldError.checkNotNull( + implements, r'ExtensionType', 'implements'); + BuiltValueNullFieldError.checkNotNull( + constructors, r'ExtensionType', 'constructors'); + BuiltValueNullFieldError.checkNotNull(fields, r'ExtensionType', 'fields'); + BuiltValueNullFieldError.checkNotNull(methods, r'ExtensionType', 'methods'); + } + + @override + ExtensionType rebuild(void Function(ExtensionTypeBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + _$ExtensionTypeBuilder toBuilder() => + new _$ExtensionTypeBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is ExtensionType && + annotations == other.annotations && + docs == other.docs && + constant == other.constant && + name == other.name && + types == other.types && + primaryConstructorName == other.primaryConstructorName && + representationDeclaration == other.representationDeclaration && + implements == other.implements && + constructors == other.constructors && + fields == other.fields && + methods == other.methods; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, constant.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, types.hashCode); + _$hash = $jc(_$hash, primaryConstructorName.hashCode); + _$hash = $jc(_$hash, representationDeclaration.hashCode); + _$hash = $jc(_$hash, implements.hashCode); + _$hash = $jc(_$hash, constructors.hashCode); + _$hash = $jc(_$hash, fields.hashCode); + _$hash = $jc(_$hash, methods.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'ExtensionType') + ..add('annotations', annotations) + ..add('docs', docs) + ..add('constant', constant) + ..add('name', name) + ..add('types', types) + ..add('primaryConstructorName', primaryConstructorName) + ..add('representationDeclaration', representationDeclaration) + ..add('implements', implements) + ..add('constructors', constructors) + ..add('fields', fields) + ..add('methods', methods)) + .toString(); + } +} + +class _$ExtensionTypeBuilder extends ExtensionTypeBuilder { + _$ExtensionType? _$v; + + @override + ListBuilder get annotations { + _$this; + return super.annotations; + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs; + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + @override + bool get constant { + _$this; + return super.constant; + } + + @override + set constant(bool constant) { + _$this; + super.constant = constant; + } + + @override + String? get name { + _$this; + return super.name; + } + + @override + set name(String? name) { + _$this; + super.name = name; + } + + @override + ListBuilder get types { + _$this; + return super.types; + } + + @override + set types(ListBuilder types) { + _$this; + super.types = types; + } + + @override + String get primaryConstructorName { + _$this; + return super.primaryConstructorName; + } + + @override + set primaryConstructorName(String primaryConstructorName) { + _$this; + super.primaryConstructorName = primaryConstructorName; + } + + @override + RepresentationDeclaration? get representationDeclaration { + _$this; + return super.representationDeclaration; + } + + @override + set representationDeclaration( + RepresentationDeclaration? representationDeclaration) { + _$this; + super.representationDeclaration = representationDeclaration; + } + + @override + ListBuilder get implements { + _$this; + return super.implements; + } + + @override + set implements(ListBuilder implements) { + _$this; + super.implements = implements; + } + + @override + ListBuilder get constructors { + _$this; + return super.constructors; + } + + @override + set constructors(ListBuilder constructors) { + _$this; + super.constructors = constructors; + } + + @override + ListBuilder get fields { + _$this; + return super.fields; + } + + @override + set fields(ListBuilder fields) { + _$this; + super.fields = fields; + } + + @override + ListBuilder get methods { + _$this; + return super.methods; + } + + @override + set methods(ListBuilder methods) { + _$this; + super.methods = methods; + } + + _$ExtensionTypeBuilder() : super._(); + + ExtensionTypeBuilder get _$this { + final $v = _$v; + if ($v != null) { + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); + super.constant = $v.constant; + super.name = $v.name; + super.types = $v.types.toBuilder(); + super.primaryConstructorName = $v.primaryConstructorName; + super.representationDeclaration = $v.representationDeclaration; + super.implements = $v.implements.toBuilder(); + super.constructors = $v.constructors.toBuilder(); + super.fields = $v.fields.toBuilder(); + super.methods = $v.methods.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(ExtensionType other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$ExtensionType; + } + + @override + void update(void Function(ExtensionTypeBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + ExtensionType build() => _build(); + + _$ExtensionType _build() { + _$ExtensionType _$result; + try { + _$result = _$v ?? + new _$ExtensionType._( + annotations: annotations.build(), + docs: docs.build(), + constant: BuiltValueNullFieldError.checkNotNull( + constant, r'ExtensionType', 'constant'), + name: BuiltValueNullFieldError.checkNotNull( + name, r'ExtensionType', 'name'), + types: types.build(), + primaryConstructorName: BuiltValueNullFieldError.checkNotNull( + primaryConstructorName, + r'ExtensionType', + 'primaryConstructorName'), + representationDeclaration: BuiltValueNullFieldError.checkNotNull( + representationDeclaration, + r'ExtensionType', + 'representationDeclaration'), + implements: implements.build(), + constructors: constructors.build(), + fields: fields.build(), + methods: methods.build()); + } catch (_) { + late String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + + _$failedField = 'types'; + types.build(); + + _$failedField = 'implements'; + implements.build(); + _$failedField = 'constructors'; + constructors.build(); + _$failedField = 'fields'; + fields.build(); + _$failedField = 'methods'; + methods.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + r'ExtensionType', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +class _$RepresentationDeclaration extends RepresentationDeclaration { + @override + final BuiltList annotations; + @override + final BuiltList docs; + @override + final Reference declaredRepresentationType; + @override + final String name; + + factory _$RepresentationDeclaration( + [void Function(RepresentationDeclarationBuilder)? updates]) => + (new RepresentationDeclarationBuilder()..update(updates)).build() + as _$RepresentationDeclaration; + + _$RepresentationDeclaration._( + {required this.annotations, + required this.docs, + required this.declaredRepresentationType, + required this.name}) + : super._() { + BuiltValueNullFieldError.checkNotNull( + annotations, r'RepresentationDeclaration', 'annotations'); + BuiltValueNullFieldError.checkNotNull( + docs, r'RepresentationDeclaration', 'docs'); + BuiltValueNullFieldError.checkNotNull(declaredRepresentationType, + r'RepresentationDeclaration', 'declaredRepresentationType'); + BuiltValueNullFieldError.checkNotNull( + name, r'RepresentationDeclaration', 'name'); + } + + @override + RepresentationDeclaration rebuild( + void Function(RepresentationDeclarationBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + _$RepresentationDeclarationBuilder toBuilder() => + new _$RepresentationDeclarationBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is RepresentationDeclaration && + annotations == other.annotations && + docs == other.docs && + declaredRepresentationType == other.declaredRepresentationType && + name == other.name; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); + _$hash = $jc(_$hash, declaredRepresentationType.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'RepresentationDeclaration') + ..add('annotations', annotations) + ..add('docs', docs) + ..add('declaredRepresentationType', declaredRepresentationType) + ..add('name', name)) + .toString(); + } +} + +class _$RepresentationDeclarationBuilder + extends RepresentationDeclarationBuilder { + _$RepresentationDeclaration? _$v; + + @override + ListBuilder get annotations { + _$this; + return super.annotations; + } + + @override + set annotations(ListBuilder annotations) { + _$this; + super.annotations = annotations; + } + + @override + ListBuilder get docs { + _$this; + return super.docs; + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + + @override + Reference? get declaredRepresentationType { + _$this; + return super.declaredRepresentationType; + } + + @override + set declaredRepresentationType(Reference? declaredRepresentationType) { + _$this; + super.declaredRepresentationType = declaredRepresentationType; + } + + @override + String? get name { + _$this; + return super.name; + } + + @override + set name(String? name) { + _$this; + super.name = name; + } + + _$RepresentationDeclarationBuilder() : super._(); + + RepresentationDeclarationBuilder get _$this { + final $v = _$v; + if ($v != null) { + super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); + super.declaredRepresentationType = $v.declaredRepresentationType; + super.name = $v.name; + _$v = null; + } + return this; + } + + @override + void replace(RepresentationDeclaration other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$RepresentationDeclaration; + } + + @override + void update(void Function(RepresentationDeclarationBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + RepresentationDeclaration build() => _build(); + + _$RepresentationDeclaration _build() { + _$RepresentationDeclaration _$result; + try { + _$result = _$v ?? + new _$RepresentationDeclaration._( + annotations: annotations.build(), + docs: docs.build(), + declaredRepresentationType: BuiltValueNullFieldError.checkNotNull( + declaredRepresentationType, + r'RepresentationDeclaration', + 'declaredRepresentationType'), + name: BuiltValueNullFieldError.checkNotNull( + name, r'RepresentationDeclaration', 'name')); + } catch (_) { + late String _$failedField; + try { + _$failedField = 'annotations'; + annotations.build(); + _$failedField = 'docs'; + docs.build(); + } catch (e) { + throw new BuiltValueNestedFieldError( + r'RepresentationDeclaration', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/pkgs/code_builder/lib/src/visitors.dart b/pkgs/code_builder/lib/src/visitors.dart index 0075bd7a6..10fe0d815 100644 --- a/pkgs/code_builder/lib/src/visitors.dart +++ b/pkgs/code_builder/lib/src/visitors.dart @@ -11,6 +11,7 @@ import 'specs/directive.dart'; import 'specs/enum.dart'; import 'specs/expression.dart'; import 'specs/extension.dart'; +import 'specs/extension_type.dart'; import 'specs/field.dart'; import 'specs/library.dart'; import 'specs/method.dart'; @@ -33,6 +34,8 @@ abstract class SpecVisitor { T visitExtension(Extension spec, [T? context]); + T visitExtensionType(ExtensionType spec, [T? context]); + T visitEnum(Enum spec, [T? context]); T visitConstructor(Constructor spec, String clazz, [T? context]); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 6d490c109..0d26965f1 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,11 +1,11 @@ name: code_builder -version: 4.8.0-wip +version: 4.8.0 description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder environment: - sdk: '>=2.19.0 <3.0.0' + sdk: '>=3.0.0 <4.0.0' dependencies: built_collection: ^5.0.0 @@ -19,6 +19,6 @@ dev_dependencies: build_runner: ^2.0.3 built_value_generator: ^8.0.0 dart_flutter_team_lints: ^1.0.0 - dart_style: ^2.0.0 + dart_style: ^2.3.3 source_gen: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/code_builder/test/specs/extension_test.dart b/pkgs/code_builder/test/specs/extension_test.dart index 6c34ebea5..b45fa6580 100644 --- a/pkgs/code_builder/test/specs/extension_test.dart +++ b/pkgs/code_builder/test/specs/extension_test.dart @@ -134,25 +134,4 @@ void main() { '''), ); }); - - test('should create an extension with a method', () { - expect( - Extension((b) => b - ..name = 'Foo' - ..on = TypeReference((b) => b.symbol = 'Bar') - ..methods.add(Method((b) => b - ..name = 'parseInt' - ..returns = refer('int') - ..body = Code.scope( - (a) => 'return int.parse(this);', - )))), - equalsDart(r''' - extension Foo on Bar { - int parseInt() { - return int.parse(this); - } - } - '''), - ); - }); } diff --git a/pkgs/code_builder/test/specs/extension_type_test.dart b/pkgs/code_builder/test/specs/extension_type_test.dart new file mode 100644 index 000000000..fbe3c2ea2 --- /dev/null +++ b/pkgs/code_builder/test/specs/extension_type_test.dart @@ -0,0 +1,247 @@ +// Copyright (c) 2023, 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:code_builder/src/specs/extension_type.dart'; +import 'package:test/test.dart'; + +// import '../common.dart'; + +void main() { + // TODO(srujzs): Uncomment this and the import once we have dart_style 2.3.4. + // When 2.3.4 is published, extension type formatting will be enabled and + // these expectations will start failing. To avoid that, we don't use dart + // format temporarily. Once 2.3.4 is published, we can update the expectations + // in this file and re-enable dart format. + // useDartfmt(); + + test('minimum extension type', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'int') + ..name = 'bar')), + equalsDart(r''' + extension type Foo(int bar) { } + '''), + ); + }); + + test('const extension type', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..constant = true + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'int') + ..name = 'bar')), + equalsDart(r''' + extension type const Foo(int bar) { } + '''), + ); + }); + + test('extension type with metadata', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'int') + ..name = 'bar') + ..docs.add( + '/// My favorite extension type.', + ) + ..annotations.addAll([ + refer('deprecated'), + refer('Deprecated') + .call([literalString('This is an old extension type')]) + ])), + equalsDart(r''' + /// My favorite extension type. + @deprecated + @Deprecated('This is an old extension type') + extension type Foo(int bar) { } + '''), + ); + }); + + test('extension type with generics', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..types.addAll([ + TypeReference((b) => b..symbol = 'T'), + TypeReference((b) => b..symbol = 'U') + ]) + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'T') + ..name = 'bar')), + equalsDart(r''' + extension type Foo(T bar) { } + '''), + ); + }); + + test('extension type with generics bound', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..types.add(TypeReference((b) => b + ..symbol = 'T' + ..bound = TypeReference((b) => b..symbol = 'num'))) + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'T') + ..name = 'bar')), + equalsDart(r''' + extension type Foo(T bar) { } + '''), + ); + }); + + test('extension type with named primary constructor', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..primaryConstructorName = 'named' + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'int') + ..name = 'bar')), + equalsDart(r''' + extension type Foo.named(int bar) { } + '''), + ); + }); + + test('extension type with metadata on field', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'int') + ..name = 'bar' + ..docs.add( + '/// My favorite representation declaration.', + ) + ..annotations.addAll([ + refer('deprecated'), + refer('Deprecated').call( + [literalString('This is an old representation declaration')]) + ]))), + equalsDart(r''' + extension type Foo(/// My favorite representation declaration. + @deprecated + @Deprecated('This is an old representation declaration') + int bar) { } + '''), + ); + }); + + test('extension type with implements', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..implements.add(TypeReference((b) => b.symbol = 'num')) + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'int') + ..name = 'bar')), + equalsDart(r''' + extension type Foo(int bar) implements num { } + '''), + ); + }); + + test('extension type with multiple implements', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..implements.addAll([ + TypeReference((b) => b.symbol = 'num'), + TypeReference((b) => b.symbol = 'Object') + ]) + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'int') + ..name = 'bar')), + equalsDart(r''' + extension type Foo(int bar) implements num,Object { } + '''), + ); + }); + + test('extension type with constructors', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..primaryConstructorName = '_' + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'int') + ..name = 'bar') + ..constructors.addAll([ + Constructor((b) => b.requiredParameters.add(Parameter((b) => b + ..toThis = true + ..name = 'bar'))), + Constructor((b) => b + ..name = 'named' + ..factory = true + ..requiredParameters.add(Parameter((b) => b + ..type = TypeReference((b) => b.symbol = 'int') + ..name = 'baz')) + ..body = const Code('return Foo(baz);')) + ])), + equalsDart(r''' + extension type Foo._(int bar) { + Foo(this.bar); + factory Foo.named(int baz) { return Foo(baz); } + } + '''), + ); + }); + + test('extension type with external field', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'int') + ..name = 'bar') + ..fields.add(Field((b) => b + ..external = true + ..type = TypeReference((b) => b.symbol = 'int') + ..name = 'property'))), + equalsDart(r''' + extension type Foo(int bar) { + external int property; + } + '''), + ); + }); + + test('extension type with methods', () { + expect( + ExtensionType((b) => b + ..name = 'Foo' + ..representationDeclaration = RepresentationDeclaration((b) => b + ..declaredRepresentationType = TypeReference((b) => b.symbol = 'int') + ..name = 'bar') + ..methods.addAll([ + Method((b) => b + ..type = MethodType.getter + ..returns = TypeReference((b) => b.symbol = 'int') + ..name = 'value' + ..body = const Code('return this.bar;')), + Method((b) => b + ..returns = TypeReference((b) => b.symbol = 'int') + ..name = 'getValue' + ..lambda = true + ..body = const Code('this.bar')) + ])), + equalsDart(r''' + extension type Foo(int bar) { + int get value { return this.bar; } + int getValue() => this.bar; + } + '''), + ); + }); +} From ab32119f8888bdf3b565c8be7ea5b85da441d3a8 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 12 Dec 2023 09:09:46 -0800 Subject: [PATCH 254/271] Add a new field `Library.generatedByComment` to support emitting 'generated by' comments. (dart-lang/code_builder#441) add a Library.generatedByComment field --- pkgs/code_builder/CHANGELOG.md | 4 ++ pkgs/code_builder/README.md | 4 +- pkgs/code_builder/lib/src/emitter.dart | 6 +++ pkgs/code_builder/lib/src/specs/library.dart | 8 ++++ .../code_builder/lib/src/specs/library.g.dart | 21 ++++++++++ pkgs/code_builder/pubspec.yaml | 2 +- .../code_builder/test/specs/library_test.dart | 41 +++++++++++++++++++ pkgs/code_builder/tool/regenerate.sh | 7 ++++ 8 files changed, 89 insertions(+), 4 deletions(-) create mode 100755 pkgs/code_builder/tool/regenerate.sh diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index c216a928d..ee23d39cf 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.9.0 + +* Add `Library.generatedByComment` to support emitting 'generated by' comments. + ## 4.8.0 * Add `Expression.operatorSubtract` diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 2d77a256e..f149c4ff4 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -103,9 +103,7 @@ run from the snapshot instead of from source to avoid problems with deleted files. These steps must be run without deleting the source files. ```bash -$ dart run build_runner generate-build-script -$ dart compile kernel .dart_tool/build/entrypoint/build.dart -$ dart .dart_tool/build/entrypoint/build.dill build --delete-conflicting-outputs +./tool/regenerate.sh ``` [build_runner]: https://pub.dev/packages/build_runner diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 591b992cf..617cb7bf3 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -483,6 +483,12 @@ class DartEmitter extends Object output.writeln(); } + if (spec.generatedByComment != null) { + output + ..writeln('// ${spec.generatedByComment}') + ..writeln(); + } + if (spec.ignoreForFile.isNotEmpty) { final ignores = spec.ignoreForFile.toList()..sort(); final lines = ['// ignore_for_file: ${ignores.first}']; diff --git a/pkgs/code_builder/lib/src/specs/library.dart b/pkgs/code_builder/lib/src/specs/library.dart index 0e3d7f3f8..69a6dbfb0 100644 --- a/pkgs/code_builder/lib/src/specs/library.dart +++ b/pkgs/code_builder/lib/src/specs/library.dart @@ -30,6 +30,12 @@ abstract class Library /// Line comments to place at the start of the library. BuiltList get comments; + /// A comment indicating the tool this library was generated by. + /// + /// This is typically of the form `Generated by xxx.`; it should exclude + /// leading line comment characters. + String? get generatedByComment; + /// A list of analysis issues to ignore (`ignore_for_file: ...`). BuiltList get ignoreForFile; @@ -59,6 +65,8 @@ abstract class LibraryBuilder ListBuilder directives = ListBuilder(); ListBuilder comments = ListBuilder(); + String? generatedByComment; ListBuilder ignoreForFile = ListBuilder(); + String? name; } diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index 6bf19b309..1858cd6d7 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -16,6 +16,8 @@ class _$Library extends Library { @override final BuiltList comments; @override + final String? generatedByComment; + @override final BuiltList ignoreForFile; @override final String? name; @@ -28,6 +30,7 @@ class _$Library extends Library { required this.directives, required this.body, required this.comments, + this.generatedByComment, required this.ignoreForFile, this.name}) : super._() { @@ -55,6 +58,7 @@ class _$Library extends Library { directives == other.directives && body == other.body && comments == other.comments && + generatedByComment == other.generatedByComment && ignoreForFile == other.ignoreForFile && name == other.name; } @@ -66,6 +70,7 @@ class _$Library extends Library { _$hash = $jc(_$hash, directives.hashCode); _$hash = $jc(_$hash, body.hashCode); _$hash = $jc(_$hash, comments.hashCode); + _$hash = $jc(_$hash, generatedByComment.hashCode); _$hash = $jc(_$hash, ignoreForFile.hashCode); _$hash = $jc(_$hash, name.hashCode); _$hash = $jf(_$hash); @@ -79,6 +84,7 @@ class _$Library extends Library { ..add('directives', directives) ..add('body', body) ..add('comments', comments) + ..add('generatedByComment', generatedByComment) ..add('ignoreForFile', ignoreForFile) ..add('name', name)) .toString(); @@ -136,6 +142,18 @@ class _$LibraryBuilder extends LibraryBuilder { super.comments = comments; } + @override + String? get generatedByComment { + _$this; + return super.generatedByComment; + } + + @override + set generatedByComment(String? generatedByComment) { + _$this; + super.generatedByComment = generatedByComment; + } + @override ListBuilder get ignoreForFile { _$this; @@ -169,6 +187,7 @@ class _$LibraryBuilder extends LibraryBuilder { super.directives = $v.directives.toBuilder(); super.body = $v.body.toBuilder(); super.comments = $v.comments.toBuilder(); + super.generatedByComment = $v.generatedByComment; super.ignoreForFile = $v.ignoreForFile.toBuilder(); super.name = $v.name; _$v = null; @@ -199,6 +218,7 @@ class _$LibraryBuilder extends LibraryBuilder { directives: directives.build(), body: body.build(), comments: comments.build(), + generatedByComment: generatedByComment, ignoreForFile: ignoreForFile.build(), name: name); } catch (_) { @@ -212,6 +232,7 @@ class _$LibraryBuilder extends LibraryBuilder { body.build(); _$failedField = 'comments'; comments.build(); + _$failedField = 'ignoreForFile'; ignoreForFile.build(); } catch (e) { diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 0d26965f1..f088adfe9 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.8.0 +version: 4.9.0 description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index 3c5502ec7..a2974fede 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -53,6 +53,23 @@ void main() { ); }); + test('should emit a source file with a generated-by comment', () { + expect( + Library( + (b) => b + ..generatedByComment = 'Generated by fooBar.' + ..body.add( + Class((b) => b..name = 'Foo'), + ), + ), + equalsDart(r''' + // Generated by fooBar. + + class Foo { } + ''', DartEmitter(allocator: Allocator())), + ); + }); + test('should emit a source file with ignore comments', () { expect( Library( @@ -93,6 +110,30 @@ void main() { ); }); + test('should emit with line comments, generated-by, and ignore-for-file', + () { + expect( + Library( + (b) => b + ..comments.add('Generic copyright statement.') + ..generatedByComment = 'Generated by fooBar.' + ..ignoreForFile.add('sort_constructors_first') + ..body.add( + Class((b) => b..name = 'Foo'), + ), + ), + equalsDart(r''' + // Generic copyright statement. + + // Generated by fooBar. + + // ignore_for_file: sort_constructors_first + + class Foo { } + ''', DartEmitter(allocator: Allocator())), + ); + }); + test('should emit a source file with manual imports', () { expect( Library((b) => b diff --git a/pkgs/code_builder/tool/regenerate.sh b/pkgs/code_builder/tool/regenerate.sh new file mode 100755 index 000000000..722e98aed --- /dev/null +++ b/pkgs/code_builder/tool/regenerate.sh @@ -0,0 +1,7 @@ +# Copyright (c) 2023, 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. + +dart run build_runner generate-build-script +dart compile kernel .dart_tool/build/entrypoint/build.dart +dart .dart_tool/build/entrypoint/build.dill build --delete-conflicting-outputs From 7ec7f52662bc55e80ac0a8193779a4b8a401517a Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 13 Dec 2023 08:13:42 -0800 Subject: [PATCH 255/271] Support annotations on unnamed libraries; 4.9.0 (dart-lang/code_builder#440) --- pkgs/code_builder/CHANGELOG.md | 1 + pkgs/code_builder/lib/src/emitter.dart | 11 ++++++---- .../code_builder/test/specs/library_test.dart | 22 ++++++++++--------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index ee23d39cf..1fc26c744 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ ## 4.9.0 * Add `Library.generatedByComment` to support emitting 'generated by' comments. +* Support emitting an unnamed library with annotations. ## 4.8.0 diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 617cb7bf3..99c91e4bf 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -512,13 +512,16 @@ class DartEmitter extends Object } } + for (var a in spec.annotations) { + visitAnnotation(a, output); + } if (spec.name != null) { - for (var a in spec.annotations) { - visitAnnotation(a, output); - } output.write('library ${spec.name!};'); } else if (spec.annotations.isNotEmpty) { - throw StateError('a library name is required for annotations'); + // An explicit _unnamed_ library directive is only required if there are + // annotations or doc comments on the library (though doc comments are not + // currently supported in code_builder). + output.write('library;'); } final directives = [...allocator.imports, ...spec.directives]; diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index a2974fede..6b7fdeafc 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -277,17 +277,19 @@ void main() { ); }); - test('should error on unnamed library with annotations', () { + test('should emit an unnamed library source file with annotations', () { expect( - () { - Library( - (b) => b - ..annotations.add( - refer('JS', 'package:js/js.dart').call([]), - ), - ).accept(DartEmitter()); - }, - throwsStateError, + Library( + (b) => b + ..annotations.add( + refer('JS', 'package:js/js.dart').call([]), + ), + ), + equalsDart(r''' + @JS() + library; + import 'package:js/js.dart'; + ''', DartEmitter(allocator: Allocator())), ); }); }); From 2edf94e9200bae0fa2963a005bbc09693eaa8766 Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis <25266387+Leptopoda@users.noreply.github.com> Date: Fri, 29 Dec 2023 00:52:24 +0100 Subject: [PATCH 256/271] feat: support docs for libraries (dart-lang/code_builder#444) Signed-off-by: Nikolas Rimikis Co-authored-by: Nikolas Rimikis --- pkgs/code_builder/AUTHORS | 3 ++- pkgs/code_builder/CHANGELOG.md | 4 ++++ pkgs/code_builder/lib/src/emitter.dart | 6 ++--- pkgs/code_builder/lib/src/specs/library.dart | 11 +++++++-- .../code_builder/lib/src/specs/library.g.dart | 23 +++++++++++++++++++ pkgs/code_builder/pubspec.yaml | 2 +- .../code_builder/test/specs/library_test.dart | 17 ++++++++++++++ 7 files changed, 59 insertions(+), 7 deletions(-) diff --git a/pkgs/code_builder/AUTHORS b/pkgs/code_builder/AUTHORS index 609e0dce0..a904f0c02 100644 --- a/pkgs/code_builder/AUTHORS +++ b/pkgs/code_builder/AUTHORS @@ -3,4 +3,5 @@ # # Name/Organization -Google Inc. \ No newline at end of file +Nikolas Rimikis +Google Inc. diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 1fc26c744..8e51fab74 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.10.0-wip + +* Add `Library.docs` to support emitting doc comments on libraries. + ## 4.9.0 * Add `Library.generatedByComment` to support emitting 'generated by' comments. diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart index 99c91e4bf..12109cc38 100644 --- a/pkgs/code_builder/lib/src/emitter.dart +++ b/pkgs/code_builder/lib/src/emitter.dart @@ -512,15 +512,15 @@ class DartEmitter extends Object } } + spec.docs.forEach(output.writeln); for (var a in spec.annotations) { visitAnnotation(a, output); } if (spec.name != null) { output.write('library ${spec.name!};'); - } else if (spec.annotations.isNotEmpty) { + } else if (spec.annotations.isNotEmpty || spec.docs.isNotEmpty) { // An explicit _unnamed_ library directive is only required if there are - // annotations or doc comments on the library (though doc comments are not - // currently supported in code_builder). + // annotations or doc comments on the library. output.write('library;'); } diff --git a/pkgs/code_builder/lib/src/specs/library.dart b/pkgs/code_builder/lib/src/specs/library.dart index 69a6dbfb0..bbfbf3f86 100644 --- a/pkgs/code_builder/lib/src/specs/library.dart +++ b/pkgs/code_builder/lib/src/specs/library.dart @@ -8,6 +8,7 @@ import 'package:meta/meta.dart'; import '../base.dart'; import '../mixins/annotations.dart'; +import '../mixins/dartdoc.dart'; import '../visitors.dart'; import 'directive.dart'; import 'expression.dart'; @@ -16,7 +17,7 @@ part 'library.g.dart'; @immutable abstract class Library - with HasAnnotations + with HasAnnotations, HasDartDocs implements Built, Spec { factory Library([void Function(LibraryBuilder) updates]) = _$Library; Library._(); @@ -24,6 +25,9 @@ abstract class Library @override BuiltList get annotations; + @override + BuiltList get docs; + BuiltList get directives; BuiltList get body; @@ -53,7 +57,7 @@ abstract class Library } abstract class LibraryBuilder - with HasAnnotationsBuilder + with HasAnnotationsBuilder, HasDartDocsBuilder implements Builder { factory LibraryBuilder() = _$LibraryBuilder; LibraryBuilder._(); @@ -61,6 +65,9 @@ abstract class LibraryBuilder @override ListBuilder annotations = ListBuilder(); + @override + ListBuilder docs = ListBuilder(); + ListBuilder body = ListBuilder(); ListBuilder directives = ListBuilder(); diff --git a/pkgs/code_builder/lib/src/specs/library.g.dart b/pkgs/code_builder/lib/src/specs/library.g.dart index 1858cd6d7..63cfc200b 100644 --- a/pkgs/code_builder/lib/src/specs/library.g.dart +++ b/pkgs/code_builder/lib/src/specs/library.g.dart @@ -10,6 +10,8 @@ class _$Library extends Library { @override final BuiltList annotations; @override + final BuiltList docs; + @override final BuiltList directives; @override final BuiltList body; @@ -27,6 +29,7 @@ class _$Library extends Library { _$Library._( {required this.annotations, + required this.docs, required this.directives, required this.body, required this.comments, @@ -36,6 +39,7 @@ class _$Library extends Library { : super._() { BuiltValueNullFieldError.checkNotNull( annotations, r'Library', 'annotations'); + BuiltValueNullFieldError.checkNotNull(docs, r'Library', 'docs'); BuiltValueNullFieldError.checkNotNull(directives, r'Library', 'directives'); BuiltValueNullFieldError.checkNotNull(body, r'Library', 'body'); BuiltValueNullFieldError.checkNotNull(comments, r'Library', 'comments'); @@ -55,6 +59,7 @@ class _$Library extends Library { if (identical(other, this)) return true; return other is Library && annotations == other.annotations && + docs == other.docs && directives == other.directives && body == other.body && comments == other.comments && @@ -67,6 +72,7 @@ class _$Library extends Library { int get hashCode { var _$hash = 0; _$hash = $jc(_$hash, annotations.hashCode); + _$hash = $jc(_$hash, docs.hashCode); _$hash = $jc(_$hash, directives.hashCode); _$hash = $jc(_$hash, body.hashCode); _$hash = $jc(_$hash, comments.hashCode); @@ -81,6 +87,7 @@ class _$Library extends Library { String toString() { return (newBuiltValueToStringHelper(r'Library') ..add('annotations', annotations) + ..add('docs', docs) ..add('directives', directives) ..add('body', body) ..add('comments', comments) @@ -106,6 +113,18 @@ class _$LibraryBuilder extends LibraryBuilder { super.annotations = annotations; } + @override + ListBuilder get docs { + _$this; + return super.docs; + } + + @override + set docs(ListBuilder docs) { + _$this; + super.docs = docs; + } + @override ListBuilder get directives { _$this; @@ -184,6 +203,7 @@ class _$LibraryBuilder extends LibraryBuilder { final $v = _$v; if ($v != null) { super.annotations = $v.annotations.toBuilder(); + super.docs = $v.docs.toBuilder(); super.directives = $v.directives.toBuilder(); super.body = $v.body.toBuilder(); super.comments = $v.comments.toBuilder(); @@ -215,6 +235,7 @@ class _$LibraryBuilder extends LibraryBuilder { _$result = _$v ?? new _$Library._( annotations: annotations.build(), + docs: docs.build(), directives: directives.build(), body: body.build(), comments: comments.build(), @@ -226,6 +247,8 @@ class _$LibraryBuilder extends LibraryBuilder { try { _$failedField = 'annotations'; annotations.build(); + _$failedField = 'docs'; + docs.build(); _$failedField = 'directives'; directives.build(); _$failedField = 'body'; diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index f088adfe9..03f2edab7 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.9.0 +version: 4.10.0-wip description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder diff --git a/pkgs/code_builder/test/specs/library_test.dart b/pkgs/code_builder/test/specs/library_test.dart index 6b7fdeafc..8ea4c5811 100644 --- a/pkgs/code_builder/test/specs/library_test.dart +++ b/pkgs/code_builder/test/specs/library_test.dart @@ -292,5 +292,22 @@ void main() { ''', DartEmitter(allocator: Allocator())), ); }); + + test('should emit an unnamed library source file with documentation', () { + expect( + Library( + (b) => b + ..docs.addAll( + const [ + '/// My favorite library.', + ], + ), + ), + equalsDart(r''' + /// My favorite library. + library; + '''), + ); + }); }); } From 6ec6eebbc790609d903b1e9daacb739efab5b80d Mon Sep 17 00:00:00 2001 From: Srujan Gaddam <58529443+srujzs@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:42:34 -0800 Subject: [PATCH 257/271] Export representation declaration types, upgrade dart_style to 2.3.4, and publish 4.10.0 (dart-lang/code_builder#445) RepresentationDeclaration and RepresentationDeclarationBuilder were never exported in 4.8.0. This also cleans up a TODO to use dart format for extension type tests and preps for publish. --- pkgs/code_builder/CHANGELOG.md | 5 ++++- pkgs/code_builder/lib/code_builder.dart | 7 ++++++- pkgs/code_builder/pubspec.yaml | 4 ++-- pkgs/code_builder/test/specs/extension_type_test.dart | 10 ++-------- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 8e51fab74..4991b56b2 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,9 @@ -## 4.10.0-wip +## 4.10.0 * Add `Library.docs` to support emitting doc comments on libraries. +* Export `RepresentationDeclaration` and `RepresentationDeclarationBuilder` so + they can be used when generating extension types. +* Upgrade to `dart_style` 2.3.4. ## 4.9.0 diff --git a/pkgs/code_builder/lib/code_builder.dart b/pkgs/code_builder/lib/code_builder.dart index 17a11ef3f..9cd15b958 100644 --- a/pkgs/code_builder/lib/code_builder.dart +++ b/pkgs/code_builder/lib/code_builder.dart @@ -48,7 +48,12 @@ export 'src/specs/expression.dart' literalString, literalTrue; export 'src/specs/extension.dart' show Extension, ExtensionBuilder; -export 'src/specs/extension_type.dart' show ExtensionType, ExtensionTypeBuilder; +export 'src/specs/extension_type.dart' + show + ExtensionType, + ExtensionTypeBuilder, + RepresentationDeclaration, + RepresentationDeclarationBuilder; export 'src/specs/field.dart' show Field, FieldBuilder, FieldModifier; export 'src/specs/library.dart' show Library, LibraryBuilder; export 'src/specs/method.dart' diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 03f2edab7..f76a6c9b9 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.10.0-wip +version: 4.10.0 description: >- A fluent, builder-based library for generating valid Dart code repository: https://github.com/dart-lang/code_builder @@ -19,6 +19,6 @@ dev_dependencies: build_runner: ^2.0.3 built_value_generator: ^8.0.0 dart_flutter_team_lints: ^1.0.0 - dart_style: ^2.3.3 + dart_style: ^2.3.4 source_gen: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/code_builder/test/specs/extension_type_test.dart b/pkgs/code_builder/test/specs/extension_type_test.dart index fbe3c2ea2..6dad132c6 100644 --- a/pkgs/code_builder/test/specs/extension_type_test.dart +++ b/pkgs/code_builder/test/specs/extension_type_test.dart @@ -3,18 +3,12 @@ // BSD-style license that can be found in the LICENSE file. import 'package:code_builder/code_builder.dart'; -import 'package:code_builder/src/specs/extension_type.dart'; import 'package:test/test.dart'; -// import '../common.dart'; +import '../common.dart'; void main() { - // TODO(srujzs): Uncomment this and the import once we have dart_style 2.3.4. - // When 2.3.4 is published, extension type formatting will be enabled and - // these expectations will start failing. To avoid that, we don't use dart - // format temporarily. Once 2.3.4 is published, we can update the expectations - // in this file and re-enable dart format. - // useDartfmt(); + useDartfmt(); test('minimum extension type', () { expect( From 1520d62c37719a293508a32e8819fcf079df4e82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:17:49 +0000 Subject: [PATCH 258/271] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/code_builder#449) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 5a327cf2e..c095b8afe 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -46,7 +46,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 96444f93211c151a0ad01930c09b4f132b527864 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 11 Mar 2024 13:00:21 -0700 Subject: [PATCH 259/271] fix a test expectation for extension types (dart-lang/code_builder#450) --- pkgs/code_builder/CHANGELOG.md | 2 ++ pkgs/code_builder/pubspec.yaml | 9 ++++----- pkgs/code_builder/test/common.dart | 2 +- pkgs/code_builder/test/specs/extension_type_test.dart | 5 ++++- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 4991b56b2..3c89c79f7 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,3 +1,5 @@ +## 4.10.1-wip + ## 4.10.0 * Add `Library.docs` to support emitting doc comments on libraries. diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index f76a6c9b9..edaf04a20 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,11 +1,10 @@ name: code_builder -version: 4.10.0 -description: >- - A fluent, builder-based library for generating valid Dart code +version: 4.10.1-wip +description: A fluent, builder-based library for generating valid Dart code. repository: https://github.com/dart-lang/code_builder environment: - sdk: '>=3.0.0 <4.0.0' + sdk: ^3.0.0 dependencies: built_collection: ^5.0.0 @@ -18,7 +17,7 @@ dev_dependencies: build: ^2.0.0 build_runner: ^2.0.3 built_value_generator: ^8.0.0 - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 dart_style: ^2.3.4 source_gen: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/code_builder/test/common.dart b/pkgs/code_builder/test/common.dart index 70a4a6600..9bfed5458 100644 --- a/pkgs/code_builder/test/common.dart +++ b/pkgs/code_builder/test/common.dart @@ -9,7 +9,7 @@ final DartFormatter _dartfmt = DartFormatter(); String _format(String source) { try { return _dartfmt.format(source); - } on FormatException catch (_) { + } on FormatterException catch (_) { return _dartfmt.formatStatement(source); } } diff --git a/pkgs/code_builder/test/specs/extension_type_test.dart b/pkgs/code_builder/test/specs/extension_type_test.dart index 6dad132c6..cc510468f 100644 --- a/pkgs/code_builder/test/specs/extension_type_test.dart +++ b/pkgs/code_builder/test/specs/extension_type_test.dart @@ -186,7 +186,10 @@ void main() { equalsDart(r''' extension type Foo._(int bar) { Foo(this.bar); - factory Foo.named(int baz) { return Foo(baz); } + + factory Foo.named(int baz) { + return Foo(baz); + } } '''), ); From 0fabe0f9cb89f76bf9f028fc53081b09bb7c74dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 17:33:01 +0000 Subject: [PATCH 260/271] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/code_builder#453) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index c095b8afe..847f0d035 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From bbdc77733ab6eb0f65c927119cda2a424d389e18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 17:59:05 +0000 Subject: [PATCH 261/271] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/code_builder#454) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 847f0d035..50227d2d9 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -46,7 +46,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 5ff5de05087646141bcc08338f23cf0b398d9116 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 19:14:10 +0000 Subject: [PATCH 262/271] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/code_builder#455) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 50227d2d9..5739bae18 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From c00214c1c5efbc7692f99e4fcd4463a13b88922e Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 3 May 2024 15:07:27 -0700 Subject: [PATCH 263/271] blast_repo fixes (dart-lang/code_builder#456) dependabot --- pkgs/code_builder/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/code_builder/.github/dependabot.yml b/pkgs/code_builder/.github/dependabot.yml index e802353f4..5843b9091 100644 --- a/pkgs/code_builder/.github/dependabot.yml +++ b/pkgs/code_builder/.github/dependabot.yml @@ -10,3 +10,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From b0a049a96b154b4dac749d57b6f329e75e404276 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 26 May 2024 08:04:27 -0700 Subject: [PATCH 264/271] bump lints dep and fix (dart-lang/code_builder#460) --- .../.github/workflows/test-package.yml | 2 +- pkgs/code_builder/CHANGELOG.md | 2 ++ pkgs/code_builder/analysis_options.yaml | 5 ----- pkgs/code_builder/lib/src/specs/class.dart | 15 +++++---------- pkgs/code_builder/pubspec.yaml | 4 ++-- 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 5739bae18..a17a4ddfe 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [3.0.0, dev] + sdk: [3.1.0, dev] steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 3c89c79f7..0fedf73bd 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,5 +1,7 @@ ## 4.10.1-wip +* Require Dart `^3.1.0` + ## 4.10.0 * Add `Library.docs` to support emitting doc comments on libraries. diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml index 23e98e8d4..589c326aa 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/analysis_options.yaml @@ -13,19 +13,14 @@ linter: - avoid_unused_constructor_parameters - cancel_subscriptions - cascade_invocations - - comment_references - join_return_with_assignment - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - package_api_docs - - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - - prefer_relative_imports - - test_types_in_equals - unnecessary_await_in_return - use_string_buffers - - use_super_parameters diff --git a/pkgs/code_builder/lib/src/specs/class.dart b/pkgs/code_builder/lib/src/specs/class.dart index 6636d9423..4c1915eaf 100644 --- a/pkgs/code_builder/lib/src/specs/class.dart +++ b/pkgs/code_builder/lib/src/specs/class.dart @@ -74,16 +74,11 @@ enum ClassModifier { final$, interface; - String get name { - switch (this) { - case ClassModifier.base: - return 'base'; - case ClassModifier.final$: - return 'final'; - case ClassModifier.interface: - return 'interface'; - } - } + String get name => switch (this) { + ClassModifier.base => 'base', + ClassModifier.final$ => 'final', + ClassModifier.interface => 'interface' + }; } abstract class ClassBuilder extends Object diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index edaf04a20..23a7b9ac1 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -4,7 +4,7 @@ description: A fluent, builder-based library for generating valid Dart code. repository: https://github.com/dart-lang/code_builder environment: - sdk: ^3.0.0 + sdk: ^3.1.0 dependencies: built_collection: ^5.0.0 @@ -17,7 +17,7 @@ dev_dependencies: build: ^2.0.0 build_runner: ^2.0.3 built_value_generator: ^8.0.0 - dart_flutter_team_lints: ^2.0.0 + dart_flutter_team_lints: ^3.0.0 dart_style: ^2.3.4 source_gen: ^1.0.0 test: ^1.16.0 From 3a3dd35421695d6ba11bfddc8bfbc352b016fa43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 17:45:24 +0000 Subject: [PATCH 265/271] Bump actions/checkout from 4.1.4 to 4.1.6 in the github-actions group (dart-lang/code_builder#462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index a17a4ddfe..8e3b41b4d 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [3.1.0, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 3b9fe2a5d957730e1c39d331f484206b4551ec33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:17:53 +0000 Subject: [PATCH 266/271] Bump the github-actions group with 2 updates (dart-lang/code_builder#464) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/code_builder#118: dart-lang/setup-dartdart-lang/code_builder#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/code_builder#118: dart-lang/setup-dartdart-lang/code_builder#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/code_builder/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 8e3b41b4d..6534952ab 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -45,8 +45,8 @@ jobs: os: [ubuntu-latest] sdk: [3.1.0, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From faf9ea12800c4126069ad69faf0e2517ef3fac24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:48:19 +0000 Subject: [PATCH 267/271] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/code_builder#465) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 6534952ab..0578b2ba1 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -45,7 +45,7 @@ jobs: os: [ubuntu-latest] sdk: [3.1.0, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From e4785f742abd30ae36e3666f221ea3f2ab1aee7c Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Wed, 23 Oct 2024 12:29:39 -0700 Subject: [PATCH 268/271] Update dart_style to pass in a language version to DartFormatter. (dart-lang/code_builder#466) * Update dart_style to pass in a language version to DartFormatter. We're in [the process of](https://github.com/dart-lang/dart_style/issues/1403) moving dart_style to [a new formatting style](https://github.com/dart-lang/dart_style/issues/1253). That involves making the formatter [aware of the language version of what it's formatting](https://github.com/dart-lang/dart_style/issues/1402). That in turn means that the library API now lets you pass in a language version. In dart_style 2.3.7 [you can pass in a language version but the parameter is optional](https://pub.dev/documentation/dart_style/latest/dart_style/DartFormatter/DartFormatter.html). In the forthcoming 3.0.0 release, that parameter will become mandatory. This updates every call to `DartFormatter()` to pass in the latest language version. * Update CHANGELOG and analysis_options.yaml. * Require Dart SDK 3.5.0. --- pkgs/code_builder/.github/workflows/test-package.yml | 4 ++-- pkgs/code_builder/CHANGELOG.md | 3 ++- pkgs/code_builder/README.md | 12 +++++++++--- pkgs/code_builder/analysis_options.yaml | 1 - pkgs/code_builder/example/example.dart | 4 +++- pkgs/code_builder/pubspec.yaml | 4 ++-- pkgs/code_builder/test/common.dart | 9 ++++++--- 7 files changed, 24 insertions(+), 13 deletions(-) diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/pkgs/code_builder/.github/workflows/test-package.yml index 0578b2ba1..7016c4a6c 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/pkgs/code_builder/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ env: jobs: # Check code formatting and static analysis on a single OS (linux) - # against Dart dev and 2.12.0. + # against Dart dev and an earlier stable version. analyze: runs-on: ubuntu-latest strategy: @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [3.1.0, dev] + sdk: [3.5.0, dev] steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 0fedf73bd..00525f36b 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,6 +1,7 @@ ## 4.10.1-wip -* Require Dart `^3.1.0` +* Require Dart `^3.5.0` +* Upgrade to `dart_style` 2.3.7. ## 4.10.0 diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index f149c4ff4..22d06f80d 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -25,7 +25,10 @@ void main() { ..name = 'eat' ..body = const Code("print('Yum!');")))); final emitter = DartEmitter(); - print(DartFormatter().format('${animal.accept(emitter)}')); + print( + DartFormatter(languageVersion: DartFormatter.latestLanguageVersion) + .format('${animal.accept(emitter)}'), + ); } ``` @@ -57,7 +60,10 @@ void main() { ..returns = refer('Other', 'package:b/b.dart')), ])); final emitter = DartEmitter.scoped(); - print(DartFormatter().format('${library.accept(emitter)}')); + print( + DartFormatter(languageVersion: DartFormatter.latestLanguageVersion) + .format('${library.accept(emitter)}'), + ); } ``` @@ -103,7 +109,7 @@ run from the snapshot instead of from source to avoid problems with deleted files. These steps must be run without deleting the source files. ```bash -./tool/regenerate.sh +./tool/regenerate.sh ``` [build_runner]: https://pub.dev/packages/build_runner diff --git a/pkgs/code_builder/analysis_options.yaml b/pkgs/code_builder/analysis_options.yaml index 589c326aa..d052c68a8 100644 --- a/pkgs/code_builder/analysis_options.yaml +++ b/pkgs/code_builder/analysis_options.yaml @@ -18,7 +18,6 @@ linter: - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - package_api_docs - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals diff --git a/pkgs/code_builder/example/example.dart b/pkgs/code_builder/example/example.dart index 6d8584fa6..6f73598e9 100644 --- a/pkgs/code_builder/example/example.dart +++ b/pkgs/code_builder/example/example.dart @@ -5,7 +5,9 @@ import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; -final _dartfmt = DartFormatter(); +final _dartfmt = DartFormatter( + languageVersion: DartFormatter.latestLanguageVersion, +); void main() { print('animalClass():\n${'=' * 40}\n${animalClass()}'); diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 23a7b9ac1..80b722849 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -4,7 +4,7 @@ description: A fluent, builder-based library for generating valid Dart code. repository: https://github.com/dart-lang/code_builder environment: - sdk: ^3.1.0 + sdk: ^3.5.0 dependencies: built_collection: ^5.0.0 @@ -18,6 +18,6 @@ dev_dependencies: build_runner: ^2.0.3 built_value_generator: ^8.0.0 dart_flutter_team_lints: ^3.0.0 - dart_style: ^2.3.4 + dart_style: ^2.3.7 source_gen: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/code_builder/test/common.dart b/pkgs/code_builder/test/common.dart index 9bfed5458..b1db8d025 100644 --- a/pkgs/code_builder/test/common.dart +++ b/pkgs/code_builder/test/common.dart @@ -5,12 +5,15 @@ import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; -final DartFormatter _dartfmt = DartFormatter(); String _format(String source) { + final formatter = DartFormatter( + languageVersion: DartFormatter.latestLanguageVersion, + ); + try { - return _dartfmt.format(source); + return formatter.format(source); } on FormatterException catch (_) { - return _dartfmt.formatStatement(source); + return formatter.formatStatement(source); } } From e9ce1f20943d68548253068bf426a3badff68ed5 Mon Sep 17 00:00:00 2001 From: Moritz Date: Fri, 25 Oct 2024 12:08:48 +0200 Subject: [PATCH 269/271] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/code_builder.md | 5 ++++ pkgs/code_builder/CONTRIBUTING.md | 33 -------------------------- pkgs/code_builder/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 34 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/code_builder.md delete mode 100644 pkgs/code_builder/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE/code_builder.md b/.github/ISSUE_TEMPLATE/code_builder.md new file mode 100644 index 000000000..6c4217f7f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/code_builder.md @@ -0,0 +1,5 @@ +--- +name: "package:code_builder" +about: "Create a bug or file a feature request against package:code_builder." +labels: "package:code_builder" +--- \ No newline at end of file diff --git a/pkgs/code_builder/CONTRIBUTING.md b/pkgs/code_builder/CONTRIBUTING.md deleted file mode 100644 index 0dfd0f763..000000000 --- a/pkgs/code_builder/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at -the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. - -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. - -### File headers -All files in the project must start with the following header. - - // 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. - -### The small print -Contributions made by corporations are covered by a different agreement than the -one above, the -[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). \ No newline at end of file diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 80b722849..1c56a8635 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,7 +1,7 @@ name: code_builder version: 4.10.1-wip description: A fluent, builder-based library for generating valid Dart code. -repository: https://github.com/dart-lang/code_builder +repository: https://github.com/dart-lang/tools/tree/main/pkgs/code_builder environment: sdk: ^3.5.0 From 8237cc8eb8632b0c3837f967e0d8d1a2e5d6f9bc Mon Sep 17 00:00:00 2001 From: Moritz Date: Fri, 25 Oct 2024 12:16:28 +0200 Subject: [PATCH 270/271] Moving fixes --- .github/labeler.yml | 4 +++ .../workflows/code_builder.yaml | 17 +++++++-- README.md | 1 + pkgs/code_builder/.github/dependabot.yml | 16 --------- .../.github/workflows/publish.yaml | 17 --------- pkgs/code_builder/CHANGELOG.md | 3 +- pkgs/code_builder/README.md | 9 +++-- pkgs/code_builder/docs/Getting-Started.md | 35 +++++++++++++++++++ pkgs/code_builder/docs/Home.md | 6 ++++ pkgs/code_builder/pubspec.yaml | 2 +- 10 files changed, 67 insertions(+), 43 deletions(-) rename pkgs/code_builder/.github/workflows/test-package.yml => .github/workflows/code_builder.yaml (83%) delete mode 100644 pkgs/code_builder/.github/dependabot.yml delete mode 100644 pkgs/code_builder/.github/workflows/publish.yaml create mode 100644 pkgs/code_builder/docs/Getting-Started.md create mode 100644 pkgs/code_builder/docs/Home.md diff --git a/.github/labeler.yml b/.github/labeler.yml index c3d5de0b9..572f11d16 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -12,6 +12,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/cli_config/**' +'package:code_builder': + - changed-files: + - any-glob-to-any-file: 'pkgs/code_builder/**' + 'package:coverage': - changed-files: - any-glob-to-any-file: 'pkgs/coverage/**' diff --git a/pkgs/code_builder/.github/workflows/test-package.yml b/.github/workflows/code_builder.yaml similarity index 83% rename from pkgs/code_builder/.github/workflows/test-package.yml rename to .github/workflows/code_builder.yaml index 7016c4a6c..eb6592297 100644 --- a/pkgs/code_builder/.github/workflows/test-package.yml +++ b/.github/workflows/code_builder.yaml @@ -1,17 +1,28 @@ -name: Dart CI +name: package:code_builder on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/code_builder.yml' + - 'pkgs/code_builder/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/code_builder.yml' + - 'pkgs/code_builder/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github + +defaults: + run: + working-directory: pkgs/code_builder/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev and an earlier stable version. diff --git a/README.md b/README.md index ac4edf204..7a7c71fa8 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ don't naturally belong to other topic monorepos (like | --- | --- | --- | | [boolean_selector](pkgs/boolean_selector/) | A flexible syntax for boolean expressions, based on a simplified version of Dart's expression syntax. | [![pub package](https://img.shields.io/pub/v/boolean_selector.svg)](https://pub.dev/packages/boolean_selector) | | [cli_config](pkgs/cli_config/) | A library to take config values from configuration files, CLI arguments, and environment variables. | [![pub package](https://img.shields.io/pub/v/cli_config.svg)](https://pub.dev/packages/cli_config) | +| [code_builder](pkgs/code_builder/) | A fluent, builder-based library for generating valid Dart code. | [![pub package](https://img.shields.io/pub/v/code_builder.svg)](https://pub.dev/packages/code_builder) | | [coverage](pkgs/coverage/) | Coverage data manipulation and formatting. | [![pub package](https://img.shields.io/pub/v/coverage.svg)](https://pub.dev/packages/coverage) | | [extension_discovery](pkgs/extension_discovery/) | A convention and utilities for package extension discovery. | [![pub package](https://img.shields.io/pub/v/extension_discovery.svg)](https://pub.dev/packages/extension_discovery) | | [file](pkgs/file/) | A pluggable, mockable file system abstraction for Dart. | [![pub package](https://img.shields.io/pub/v/file.svg)](https://pub.dev/packages/file) | diff --git a/pkgs/code_builder/.github/dependabot.yml b/pkgs/code_builder/.github/dependabot.yml deleted file mode 100644 index 5843b9091..000000000 --- a/pkgs/code_builder/.github/dependabot.yml +++ /dev/null @@ -1,16 +0,0 @@ -# Set update schedule for GitHub Actions -# See https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot - -version: 2 -updates: - -- package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/code_builder/.github/workflows/publish.yaml b/pkgs/code_builder/.github/workflows/publish.yaml deleted file mode 100644 index 1af8f47dc..000000000 --- a/pkgs/code_builder/.github/workflows/publish.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ master ] - types: [opened, synchronize, reopened, labeled, unlabeled] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+*' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main - with: - sdk: dev diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md index 00525f36b..5e5521cfb 100644 --- a/pkgs/code_builder/CHANGELOG.md +++ b/pkgs/code_builder/CHANGELOG.md @@ -1,7 +1,8 @@ -## 4.10.1-wip +## 4.10.1 * Require Dart `^3.5.0` * Upgrade to `dart_style` 2.3.7. +* Move to `dart-lang/tools` monorepo. ## 4.10.0 diff --git a/pkgs/code_builder/README.md b/pkgs/code_builder/README.md index 22d06f80d..86decb594 100644 --- a/pkgs/code_builder/README.md +++ b/pkgs/code_builder/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/code_builder/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/code_builder/actions/workflows/test-package.yml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/code_builder.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/code_builder.yaml) [![Pub package](https://img.shields.io/pub/v/code_builder.svg)](https://pub.dev/packages/code_builder) [![package publisher](https://img.shields.io/pub/publisher/code_builder.svg)](https://pub.dev/packages/code_builder/publisher) [![Gitter chat](https://badges.gitter.im/dart-lang/build.svg)](https://gitter.im/dart-lang/build) @@ -79,7 +79,7 @@ _i2.Other doOther() {} ## Contributing -- Read and help us document common patterns over [at the wiki][wiki]. +- Read and help us document common patterns over [in the docs][docs]. - Is there a _bug_ in the code? [File an issue][issue]. If a feature is missing (the Dart language is always evolving) or you'd like an @@ -94,9 +94,8 @@ will be on a best-effort basis. > $ dart run dart_style:format -w . > ``` -[wiki]: https://github.com/dart-lang/code_builder/wiki -[issue]: https://github.com/dart-lang/code_builder/issues -[pull]: https://github.com/dart-lang/code_builder/pulls +[issue]: https://github.com/dart-lang/tools/issues +[pull]: https://github.com/dart-lang/tools/pulls ### Updating generated (`.g.dart`) files diff --git a/pkgs/code_builder/docs/Getting-Started.md b/pkgs/code_builder/docs/Getting-Started.md new file mode 100644 index 000000000..b82da6cfc --- /dev/null +++ b/pkgs/code_builder/docs/Getting-Started.md @@ -0,0 +1,35 @@ +# Common patterns + +## Classes + +### Creating a simple class + +> ```dart +> class Animal {} +> ``` + +```dart +new ClassBuilder( + 'Animal', +) +``` + +### Creating an abstract class with a method + +> ```dart +> abstract class Animal { +> void eat(); +> } +> ``` + +```dart +new ClassBuilder( + 'Animal', + asAbstract: true, +)..addMethod( + new MethodBuilder.returnVoid( + 'eat', + asAbstract: true, + ), +) +``` \ No newline at end of file diff --git a/pkgs/code_builder/docs/Home.md b/pkgs/code_builder/docs/Home.md new file mode 100644 index 000000000..72e87a8d7 --- /dev/null +++ b/pkgs/code_builder/docs/Home.md @@ -0,0 +1,6 @@ +The [`code_builder`][code_builder] package helps generate valid [Dart][] source code programmatically, usually as part of a build process or generation step. Most of the API currently takes a little exploring to get used to, it's recommended to read the [API documentation][docs], or read the [getting started][] guide. + +[code_builder]: pub.dartlang.org/packages/code_builder +[Dart]: https://www.dartlang.org/ +[docs]: https://www.dartdocs.org/documentation/code_builder/latest +[getting started]: Getting-Started diff --git a/pkgs/code_builder/pubspec.yaml b/pkgs/code_builder/pubspec.yaml index 1c56a8635..50302ec4e 100644 --- a/pkgs/code_builder/pubspec.yaml +++ b/pkgs/code_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: code_builder -version: 4.10.1-wip +version: 4.10.1 description: A fluent, builder-based library for generating valid Dart code. repository: https://github.com/dart-lang/tools/tree/main/pkgs/code_builder From 8ae2f9fbacf53247bf415909c232c11573c749d1 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 29 Oct 2024 16:09:42 +0100 Subject: [PATCH 271/271] Rename folder --- pkgs/code_builder/{docs => doc}/Getting-Started.md | 0 pkgs/code_builder/{docs => doc}/Home.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename pkgs/code_builder/{docs => doc}/Getting-Started.md (100%) rename pkgs/code_builder/{docs => doc}/Home.md (100%) diff --git a/pkgs/code_builder/docs/Getting-Started.md b/pkgs/code_builder/doc/Getting-Started.md similarity index 100% rename from pkgs/code_builder/docs/Getting-Started.md rename to pkgs/code_builder/doc/Getting-Started.md diff --git a/pkgs/code_builder/docs/Home.md b/pkgs/code_builder/doc/Home.md similarity index 100% rename from pkgs/code_builder/docs/Home.md rename to pkgs/code_builder/doc/Home.md