Skip to content
This repository was archived by the owner on Dec 6, 2017. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions example/web/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:di/di.dart';
import 'package:di/di_dynamic.dart';
import 'dart:html';

@Injectable()
Expand All @@ -10,7 +9,6 @@ class Application {
}

main() {
setupModuleTypeReflector();
Module module = new Module();
module.bind(Application);
new ModuleInjector([module]).get(Application).run();
Expand Down
40 changes: 40 additions & 0 deletions lib/module_transformer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
library di.transformer.export_transformer;

import 'dart:async';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/resolver.dart';
import 'package:path/path.dart' as path;

/**
* Pub transformer that changes reflector in Module to null instead of importing
* the dynamic reflector which imports mirrors. InjectorGenerator in transformer.dart
* will change DEFAULT_REFLECTOR back to static (it is run by the app, whereas this is run by DI).
*/
class ModuleTransformerGroup implements TransformerGroup {
final Iterable<Iterable> phases;

ModuleTransformerGroup.asPlugin(BarbackSettings settings)
: phases = [[new ModuleTransformer()]];
}

class ModuleTransformer extends Transformer {

ModuleTransformer();

isPrimary(AssetId id) {
return new Future.value(id == new AssetId.parse("di|lib/src/module.dart"));
}

Future apply(Transform transform) {
var id = transform.primaryInput.id;
return transform.primaryInput.readAsString().then((code) {
// Note: this rewrite is coupled with how module.dart is
// written. Make sure both are updated in sync.
transform.addOutput(new Asset.fromString(id, code
.replaceAll(new RegExp('import "reflector_dynamic.dart";'),
'import "reflector_null.dart";')));
});
}
}
3 changes: 2 additions & 1 deletion lib/src/module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ library di.module;
import "../key.dart";
import "../check_bind_args.dart" show checkBindArgs;
import "reflector.dart";
import "reflector_dynamic.dart";

DEFAULT_VALUE(_) => null;
IDENTITY(p) => p;
Expand Down Expand Up @@ -53,7 +54,7 @@ bool isNotSet(val) => identical(val, DEFAULT_VALUE);
* no effect on that injector.
*/
class Module {
static TypeReflector DEFAULT_REFLECTOR = new NullReflector();
static TypeReflector DEFAULT_REFLECTOR = getReflector();
final TypeReflector reflector;

Module(): reflector = DEFAULT_REFLECTOR;
Expand Down
15 changes: 0 additions & 15 deletions lib/src/reflector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,3 @@ abstract class TypeReflector {
void addAll(Map<Type, Function> factories, Map<Type, List<Key>> parameterKeys);
void add(Type type, Function factory, List<Key> parameterKeys);
}

class NullReflector extends TypeReflector {
factoryFor(Type type) => throw new NullReflectorError();
parameterKeysFor(Type type) => throw new NullReflectorError();
addAll(Map<Type, Function> factories, Map<Type, List<Key>> parameterKeys) =>
throw new NullReflectorError();
add(Type type, Function factory, List<Key> parameterKeys) =>
throw new NullReflectorError();
}

class NullReflectorError extends BaseError {
NullReflectorError()
: super("Module.DEFAULT_REFLECTOR not initialized for dependency injection."
"http://goo.gl/XFXx9G");
}
8 changes: 4 additions & 4 deletions lib/di_dynamic.dart → lib/src/reflector_dynamic.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
library di.dynamic_type_factories;
library di.reflector_dynamic;

import 'di.dart';
import 'src/mirrors.dart';
import '../di.dart';
import 'mirrors.dart';

TypeReflector setupModuleTypeReflector() => Module.DEFAULT_REFLECTOR = new DynamicTypeFactories();
TypeReflector getReflector() => new DynamicTypeFactories();

class DynamicTypeFactories extends TypeReflector {
/// caches of results calculated from mirroring
Expand Down
22 changes: 22 additions & 0 deletions lib/src/reflector_null.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
library di.reflector_null;

import '../key.dart';
import 'reflector.dart';
import 'errors.dart';

TypeReflector getReflector() => new NullReflector();

class NullReflector extends TypeReflector {
factoryFor(Type type) => throw new NullReflectorError();
parameterKeysFor(Type type) => throw new NullReflectorError();
addAll(Map<Type, Function> factories, Map<Type, List<Key>> parameterKeys) =>
throw new NullReflectorError();
add(Type type, Function factory, List<Key> parameterKeys) =>
throw new NullReflectorError();
}

class NullReflectorError extends BaseError {
NullReflectorError()
: super("Module.DEFAULT_REFLECTOR not initialized for dependency injection."
"http://goo.gl/XFXx9G");
}
4 changes: 2 additions & 2 deletions lib/di_static.dart → lib/src/reflector_static.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
library di.generated_type_factories;
library di.reflector_static;

import 'di.dart';
import '../di.dart';

class GeneratedTypeFactories extends TypeReflector {

Expand Down
14 changes: 6 additions & 8 deletions lib/transformer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@
* and outputted to a file [entry_point_name]_generated_type_factory_maps.dart. Multiple
* entry points (main functions) is not supported.
*
* The import in main is also modified to use import di_static.dart instead
* of di_dynamic.dart.
* This transformer also sets up the static reflector, since the dynamic version will have
* been erased by ModuleTransformer.
*
* All of the above is taken care of by the transformer. The user needs to call
* setupModuleTypeReflector in main, before any modules are initialized. User must also
* annotate types for the transformer to add them to the generated type factories file,
* in addition to enabling the transformer in pubspec.yaml.
* User must annotate types for the transformer to add them to the generated type factories file,
* and enable the transformer in pubspec.yaml.
*
* Types which are considered injectable can be annotated in the following ways:
*
Expand Down Expand Up @@ -90,10 +88,10 @@ class DependencyInjectorTransformerGroup implements TransformerGroup {
final Iterable<Iterable> phases;

DependencyInjectorTransformerGroup(TransformOptions options)
: phases = _createPhases(options);
: phases = _createPhases(options);

DependencyInjectorTransformerGroup.asPlugin(BarbackSettings settings)
: this(_parseSettings(settings.configuration));
: this(_parseSettings(settings.configuration));
}

TransformOptions _parseSettings(Map args) {
Expand Down
39 changes: 22 additions & 17 deletions lib/transformer/injector_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class _Processor {
transform.addOutput(
new Asset.fromString(_generatedAssetId, injectLibContents));

_editImport();
_editMain();
}

/** Resolves the classes for the injectable annotations in the current AST. */
Expand Down Expand Up @@ -350,7 +350,7 @@ class _Processor {
outputBuffer.write('};\nfinal Map<Type, List<Key>> parameterKeys = {\n');
outputBuffer.write(paramsBuffer);
outputBuffer.write('};\n');
outputBuffer.write('setupModuleTypeReflector() => '
outputBuffer.write('setStaticReflectorAsDefault() => '
'Module.DEFAULT_REFLECTOR = '
'new GeneratedTypeFactories(typeFactories, parameterKeys);\n');

Expand All @@ -362,26 +362,31 @@ class _Processor {
span: resolver.getSourceSpan(element));
}

/// edits out di_dynamic import and replace with generated_type_factory_maps
void _editImport() {
/// import generated_type_factory_maps and call initialize
void _editMain() {
AssetId id = transform.primaryInput.id;
var lib = resolver.getLibrary(id);
var unit = lib.definingCompilationUnit.node;
var transaction = resolver.createTextEditTransaction(lib);

var imports = unit.directives.where((d) => d is ImportDirective);
var dir = imports.where((ImportDirective d) =>
d.uriContent == 'package:di/di_dynamic.dart');
var begin, end;
if (dir.isNotEmpty) {
begin = dir.first.offset;
end = dir.first.end;
} else {
begin = imports.last.end;
end = imports.last.end;
}
transaction.edit(begin, end, (begin == end ? "\n" : "") + 'import '
transaction.edit(imports.last.end, imports.last.end, '\nimport '
"'${path.url.basenameWithoutExtension(id.path)}"
"_generated_type_factory_maps.dart' show setupModuleTypeReflector;");
"_generated_type_factory_maps.dart' show setStaticReflectorAsDefault;");

FunctionExpression main = unit.declarations.where((d) =>
d is FunctionDeclaration && d.name.toString() == 'main')
.first.functionExpression;
var body = main.body;
if (body is BlockFunctionBody) {
var location = body.beginToken.end;
transaction.edit(location, location, '\n setStaticReflectorAsDefault();');
} else if (body is ExpressionFunctionBody) {
transaction.edit(body.beginToken.offset, body.endToken.end,
"{\n setStaticReflectorAsDefault();\n"
" return ${body.expression};\n}");
} // EmptyFunctionBody can only appear as abstract methods and constructors.

var printer = transaction.commit();
var url = id.path.startsWith('lib/') ?
'package:${id.package}/${id.path.substring(4)}' : id.path;
Expand All @@ -397,7 +402,7 @@ void _writeHeader(AssetId id, StringSink sink) {
library ${id.package}.$libName.generated_type_factory_maps;

import 'package:di/di.dart';
import 'package:di/di_static.dart';
import 'package:di/src/reflector_static.dart';

''');
}
16 changes: 8 additions & 8 deletions lib/transformer/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ class TransformOptions {
final String sdkDirectory;

TransformOptions({EntryFilter entryFilter, String sdkDirectory,
List<String> injectableAnnotations, List<String> injectedTypes})
: entryFilter = entryFilter != null ? entryFilter : isPossibleDartEntry,
sdkDirectory = sdkDirectory,
injectableAnnotations =
(injectableAnnotations != null ? injectableAnnotations : [])
..addAll(DEFAULT_INJECTABLE_ANNOTATIONS),
injectedTypes =
new Set.from(injectedTypes != null ? injectedTypes : []) {
List<String> injectableAnnotations, List<String> injectedTypes})
: entryFilter = entryFilter != null ? entryFilter : isPossibleDartEntry,
sdkDirectory = sdkDirectory,
injectableAnnotations =
(injectableAnnotations != null ? injectableAnnotations : [])
..addAll(DEFAULT_INJECTABLE_ANNOTATIONS),
injectedTypes =
new Set.from(injectedTypes != null ? injectedTypes : []) {
if (sdkDirectory == null)
throw new ArgumentError('sdkDirectory must be provided.');
}
Expand Down
4 changes: 3 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: di
version: 2.0.0-alpha.7
version: 2.0.0-alpha.9
authors:
- Vojta Jina <vojta.jina@gmail.com>
- Pavel Jbanov <pavelgj@gmail.com>
Expand All @@ -18,3 +18,5 @@ dev_dependencies:
benchmark_harness: ">=1.0.4 <2.0.0"
browser: ">=0.10.0 <0.11.0"
guinness: ">=0.1.10 <0.2.0"
transformers:
- di/module_transformer
4 changes: 2 additions & 2 deletions test/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import 'package:guinness/guinness.dart';
import 'package:matcher/matcher.dart' as matcher;
import 'package:di/di.dart';
import 'package:di/annotations.dart';
import 'package:di/di_static.dart';
import 'package:di/di_dynamic.dart';
import 'package:di/src/reflector_static.dart';
import 'package:di/src/reflector_dynamic.dart';
import 'package:di/check_bind_args.dart';
import 'package:di/src/module.dart';

Expand Down
10 changes: 4 additions & 6 deletions test/transformer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -677,21 +677,19 @@ main() {
'a|web/main.dart': '''
library main;
import 'package:di/di.dart';
import 'package:di/di_dynamic.dart';

main() {
setupModuleTypeReflector();
print('abc');
}'''
},
results: {
'a|web/main.dart': '''
library main;
import 'package:di/di.dart';
import 'main_generated_type_factory_maps.dart' show setupModuleTypeReflector;
import 'main_generated_type_factory_maps.dart' show setStaticReflectorAsDefault;

main() {
setupModuleTypeReflector();
setStaticReflectorAsDefault();
print('abc');
}'''
});
Expand Down Expand Up @@ -723,7 +721,7 @@ final Map<Type, Function> typeFactories = <Type, Function>{
${factories.join('')}};
final Map<Type, List<Key>> parameterKeys = {
${paramKeys.join('')}};
setupModuleTypeReflector() => Module.DEFAULT_REFLECTOR = new GeneratedTypeFactories(typeFactories, parameterKeys);
setStaticReflectorAsDefault() => Module.DEFAULT_REFLECTOR = new GeneratedTypeFactories(typeFactories, parameterKeys);
''',
},
messages: messages);
Expand All @@ -733,7 +731,7 @@ const String IMPORTS = '''
library a.web.main.generated_type_factory_maps;

import 'package:di/di.dart';
import 'package:di/di_static.dart';
import 'package:di/src/reflector_static.dart';
''';

const String CLASS_ENGINE = '''
Expand Down