swift_composer 0.2.0

  • Readme
  • Changelog
  • Example
  • Installing
  • new42

swift_composer #

- warning: this module is experimental and under development. It's API is subjected to change

Swift Composer aims to turn dart modules into plugable application parts.

It uses source_gen to generate final application logic depending on imported modules and configuration hence no boilerplate code is created.

This module powers 'swift.shop' app engine. It is used to generate plugable client and server side routing, auto-serializable data models, configurable layouts and widgets system and more.

Installation #

  1. add swift_composer to your dependencies in pubspec.yaml:
dependencies:
  swift_composer: any
  1. declare a compiled part in your final application code:
import 'package:swift_composer/swift_composer.dart';

import 'package:some_plugin';

part 'main.c.dart';

void main() {
  $om.some_compiled_entrypoint.run();
}
  1. build .c.dart part
pub run build_runner build

If you are creating a web package the build will be executed automatically with webdev serve/build.

Features #

Requirements #

For any class to use swift composer features it needs to be declared as abstract and decorated with @Compose annotation. This allows code generator to generate a final class with compiled methods, plugins and dependency injections.

@Compose
abstract class Foo {

}

Class Names #

@Compose
abstract class Foo {

  @InjectClassName
  String get className;

  @InjectClassNames
  List<String> get classNames;

}

All instances of Test and its subtypes will have className field populated with this class full name and classNames populated with full class hierarchy path.

Above is useful for serialization as this field will contain source class name even after compilation to *.js etc.

Dependency Injection #

@Compose
abstract class Bar {

  @Require
  String barRequiredField;

}

@Compose
abstract class Test {

  @Inject
  Foo get injectedFoo;

  @Factory
  Foo createFoo();

  @Factory
  Bar createBar(String barRequiredField);

}

Methods decorated with Factory will create a compiled subtype of return type. Exact type returned will defined by imported modules and DI configuration. For classes without any dependencies required for creation you can use Inject annotation to generate shared instance.

Finding Class Subtypes

@Compose
abstract class Test {

@InjectInstances
Map<String, Foo> get instances;

@SubtypeFactory
Foo createFoo(String className);

}

Method decorated with SubtypeFactory will return a subtype of Foo depending on passed className parameter. A getter decorated with InjectInstances will contain a map indexed with class names of all requirements free subtypes of Foo.

Class Fields info and Compiled methods. #

Swift Composer adds tools to generate info of final class fields that can be used for example to generate JSON serialization.

const JsonField = true;

@Compose
abstract class TestSerializable {

  @InjectClassName
  String get className;

  @JsonField
  String foo;

  @JsonField
  String bar;

  Map toJson() {
      Map ret = new Map();
      ret['className'] = className;
      this.fieldsToJson(ret);
      return ret;
  }

  @Compile
  void fieldsToJson(Map target);

  @CompileFieldsOfType
  @AnnotatedWith(JsonField)
  void _fieldsToJsonString(Map target, String name, String field) {
    target[name] = field;
  }

  @CompileFieldsOfType
  @AnnotatedWith(JsonField)
  void _fieldsToJsonInt(Map target, String name, int field) {
    target[name] = field;
  }

}

In above example, all subtypes of TestSerializable will have toJson that will return all fields decorated with @JsonField serialized. Dart tree shaking algorithms will clear compiled code out of unused stubs.

Type Plugins #

Type plugins can modify objects data and behavior. Fields compilation method works with plugins and will also compile plugin fields so we can add a plugin for TestSerializable from previous example.

abstract class TestPlugin extends TypePlugin<TestSerializable> {

  @Field
  String extraField = 'test';

}

Now, calling toJson should return something like:

{
  'className' : 'TestSerializable',
  'foo' : 'something',
  'bar' : 10,
  'testPlugin.extraField': 'test'
}

We can also extend / change decorated classes behaviors using MethodPlugin annotations.

Every public method in parent class:

  bool validate(int foo, int bar) {
    return foo > bar;
  }

Plugin class can customize behavior of such methods:

  @MethodPlugin
  List<dynamic> beforeValidate(int foo, int bar) {
    bar = bar + 1;
    return [foo, bar];
  }

  @MethodPlugin
  bool afterValidate(bool ret) {
    return !ret;
  }

Development Info #

Running tests:

pub run build_runner build && dart test/swift_composer_test.dart

0.2.0 #

added @MethodPlugin

0.1.0 #

initial release

example/main.dart

import 'package:swift_composer/swift_composer.dart';
import 'module_fruits.dart' as module_fruit;
import 'module_banana.dart' as module_banana;
import 'module_price.dart' as module_price;
import 'module_discount.dart' as module_discount;

part 'main.c.dart';

void main() {

  List<module_fruit.Fruit> fruits = [];

  fruits.addAll([
    $om.module_fruit_AllAvailableFruits.createFruit('module_fruit.Fruit', "Fruit 1"),
    $om.module_fruit_AllAvailableFruits.createFruit('module_fruit.Fruit', "Fruit 2")
      ..width = 50
      ..height = 10,
    $om.module_fruit_AllAvailableFruits.createFruit('module_banana.Banana', "Banana 1"),
    $om.module_fruit_AllAvailableFruits.createFruit('module_banana.Banana', "Banana 2")
      ..weight = 100
  ]);

  fruits.forEach((fruit){
    print(fruit.toJson());
  });
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  swift_composer: ^0.2.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:swift_composer/swift_composer.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
0
Health:
Code health derived from static analysis. [more]
81
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
42
Learn more about scoring.

We analyzed this package on Mar 31, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6

Health suggestions

Fix lib/swift_generator.dart. (-18.98 points)

Analysis of lib/swift_generator.dart reported 42 hints, including:

line 46 col 21: 'name' is deprecated and shouldn't be used. Check element, or use getDisplayString().

line 55 col 41: 'instantiate' is deprecated and shouldn't be used. Use ClassElement.instantiate().

line 66 col 14: 'displayName' is deprecated and shouldn't be used. Use getDisplayString instead.

line 177 col 23: Unnecessary new keyword.

line 188 col 28: Unnecessary new keyword.

Maintenance issues and suggestions

Make sure dartdoc successfully runs on your package's source files. (-10 points)

exitCode: 255 stdout: parsing /tmp/pub-dartlang-dartdocRPHKCZ/pkg/lib/swift_generator.dart... parsing /tmp/pub-dartlang-dartdocRPHKCZ/pkg/lib/swift_composer.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/source_gen-0.9.5/lib/source_gen.dart... parsing /dart-sdk/lib/core/core.dart... parsing /dart-sdk/lib/collection/collection.dart... parsing /dart-sdk/lib/internal/internal.dart... parsing /dart-sdk/lib/async/async.dart... parsing /dart-sdk/lib/convert/convert.dart... parsing /dart-sdk/lib/typed_data/typed_data.dart... parsing /dart-sdk/lib/math/math.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/source_gen-0.9.5/lib/src/builder.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/dart/element/element.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/dart/analysis/session.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/dart/analysis/analysis_context.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/dart/analysis/context_root.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/file_system/file_system.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/src/generated/source.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/src/context/source.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/exception/exception.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/src/generated/engine.dart... [...] parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/src/generated/sdk_io.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/src/source/custom_resolver.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/src/source/path_filter.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/analyzer-0.39.4/lib/src/util/glob.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/package_config-1.9.3/lib/src/packages_io_impl.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/package_config-1.9.3/lib/src/util_io.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/package_config-1.9.3/lib/src/discovery.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/package_config-1.9.3/lib/src/package_config_io.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/package_config-1.9.3/lib/src/package_config_impl.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/package_config-1.9.3/lib/src/package_config.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/package_config-1.9.3/lib/src/package_config_json.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/package_config-1.9.3/lib/src/packages_file.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/args-1.6.0/lib/src/help_command.dart... parsing /tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/args-1.6.0/lib/src/usage_exception.dart... Initialized dartdoc with 617 libraries in 69.8 seconds documenting swift_composer Generating docs for library swift_composer from package:swift_composer/swift_generator.dart... Generating docs for library swift_composer from package:swift_composer/swift_composer.dart... Validating docs... Documented 2 public libraries in 4.7 seconds stderr: Documenting swift_composer... warning: swift_composer has no library level documentation comments, from swift_composer: (file:///tmp/pub-dartlang-dartdocRPHKCZ/pkg/lib/swift_generator.dart:1:9) warning: no canonical library found for swift_composer.CompiledOmGenerator.hashCode, not linking, from swift_composer.CompiledOmGenerator.hashCode: (file:///dart-sdk/lib/core/object.dart:94:20) warning: no canonical library found for swift_composer.CompiledOmGenerator.runtimeType, not linking, from swift_composer.CompiledOmGenerator.runtimeType: (file:///dart-sdk/lib/core/object.dart:116:21) warning: no canonical library found for swift_composer.CompiledOmGenerator.noSuchMethod, not linking, from swift_composer.CompiledOmGenerator.noSuchMethod: (file:///dart-sdk/lib/core/object.dart:111:20) warning: no canonical library found for swift_composer.CompiledOmGenerator.toString, not linking, from swift_composer.CompiledOmGenerator.toString: (file:///dart-sdk/lib/core/object.dart:99:19) warning: no canonical library found for swift_composer.CompiledOmGenerator.==, not linking, from swift_composer.CompiledOmGenerator.==: (file:///dart-sdk/lib/core/object.dart:62:26) warning: no canonical library found for swift_composer.SwiftGenerator.toString, not linking, from swift_composer.SwiftGenerator.toString: (file:///tmp/pub-cache-dirGPSKJQ/hosted/pub.dartlang.org/source_gen-0.9.5/lib/src/generator.dart:28:10) warning: swift_composer has no library level documentation comments, from swift_composer: (file:///tmp/pub-dartlang-dartdocRPHKCZ/pkg/lib/swift_composer.dart:1:9) error: failed to write file at: swift_composer/swift_composer-library.html for symbol swift_composer: (file:///tmp/pub-dartlang-dartdocRPHKCZ/pkg/lib/swift_composer.dart:1:9) conflicting with file already generated by swift_composer: (file:///tmp/pub-dartlang-dartdocRPHKCZ/pkg/lib/swift_generator.dart:1:9) Dartdoc generates a path and filename to write to for each symbol. swift_composer conflicts with another symbol in the generated path, and therefore can not be written out. Changing the name, library name, or class name (if appropriate) of one of the conflicting items can resolve the conflict. Alternatively, use the @nodoc tag in one symbol's documentation comments to hide it. warning: dartdoc generated a broken link to: swift_composer/CompiledOmGenerator-class.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/CompiledOmGenerator/CompiledOmGenerator.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/CompiledOmGenerator/config.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/CompiledOmGenerator/generate.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/CompiledOmGenerator/generateObjectManager.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/CompiledOmGenerator/getClassConfig.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/CompiledOmGenerator/typeMap.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/MergeMap.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/MergeMap/merge.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/MethodElementSource.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/MethodElementSource/getSourceCode.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/SwiftGenerator-class.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/SwiftGenerator/SwiftGenerator.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/SwiftGenerator/generate.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo-class.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/TypeInfo.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/allFields.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/allMethods.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/allRequiredFields.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/canBeSingleton.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/classPath.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/creatorName.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/decorators.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/displayName.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/element.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/elementInjectionType.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/flatName.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/TypeInfo.fromType.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/fullName.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/generateCompiledConstructorDefinition.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/generateCreator.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/generateInterceptor.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/generateMethodOverride.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/genericElement.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/genericType.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/getFieldAssignmentValue.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/getFieldInitializationValue.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/hasInterceptor.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/plugins.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/type.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/typeArguments.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/typeArgumentsMap.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/typeConfig.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeInfo/typeMap.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap-class.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/TypeMap.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/allTypes.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/allTypesByType.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/generateTypeGetter.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/getBestCandidate.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/getNonAbstractSubtypes.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/getPluginsForType.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/library.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/libraryPrefixes.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/modulesPaths.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/registerElement.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/TypeMap/subtypeInstanes.html (from index.json) warning: dartdoc generated a broken link to: swift_composer/swiftBuilder.html (from index.json) found 66 warnings and 1 error Unhandled exception: dartdoc encountered 1 errors while processing. #0 Dartdoc.generateDocs (package:dartdoc/dartdoc.dart:202:7)

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
analyzer ^0.39.4 0.39.4
build ^1.2.2 1.2.2
build_config ^0.4.1+1 0.4.2
path ^1.6.4 1.6.4
source_gen ^0.9.4 0.9.5
yaml ^2.2.0 2.2.0
Transitive dependencies
_fe_analyzer_shared 1.0.3
args 1.6.0
async 2.4.1
charcode 1.1.3
checked_yaml 1.0.2
collection 1.14.12
convert 2.1.1
crypto 2.1.4
csslib 0.16.1
dart_style 1.3.3
glob 1.2.0
html 0.14.0+3
js 0.6.1+1
json_annotation 3.0.1
logging 0.11.4
meta 1.1.8
node_interop 1.0.3
node_io 1.0.1+2
package_config 1.9.3
pedantic 1.9.0
pub_semver 1.4.4
pubspec_parse 0.1.5
source_span 1.7.0
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
watcher 0.9.7+14
Dev dependencies
build_runner any
test any