diff --git a/lib/generator.dart b/lib/generator.dart index 6214057..04aeb72 100644 --- a/lib/generator.dart +++ b/lib/generator.dart @@ -17,6 +17,7 @@ import 'package:analyzer/src/generated/sdk.dart' show DartSdk; import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk; import 'package:analyzer/src/generated/element.dart'; import 'package:analyzer/src/generated/engine.dart'; +import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:path/path.dart' as path; import 'dart:io'; @@ -148,16 +149,19 @@ void process_classes(Iterable classes, StringBuffer keys, throw 'Unable to find default constructor for ' '$clazz in ${clazz.source}'; }); - var args = new List.generate(constr.parameters.length, (i) => 'a$i').join(', '); + Iterable parameters = + constr.parameters.where((p) => p.parameterKind != ParameterKind.NAMED); + + var args = new List.generate(parameters.length, (i) => 'a$i').join(', '); factory.write('${resolveClassIdentifier(clazz.type)}: ($args) => ' 'new ${resolveClassIdentifier(clazz.type)}($args),\n'); paramList.write('${resolveClassIdentifier(clazz.type)}: '); - if (constr.parameters.isEmpty){ + if (parameters.isEmpty){ paramList.write('const ['); } else { paramList.write('['); - paramList.write(constr.parameters.map((param) { + paramList.write(parameters.map((param) { if (param.type.element is! ClassElement) { throw 'Unable to resolve type for constructor parameter ' '"${param.name}" for type "$clazz" in ${clazz.source}'; diff --git a/lib/src/reflector_dynamic.dart b/lib/src/reflector_dynamic.dart index 550f64e..dc7a847 100644 --- a/lib/src/reflector_dynamic.dart +++ b/lib/src/reflector_dynamic.dart @@ -41,7 +41,7 @@ class DynamicTypeFactories extends TypeReflector { Function _generateFactory(Type type) { ClassMirror classMirror = _reflectClass(type); MethodMirror ctor = classMirror.declarations[classMirror.simpleName]; - int length = ctor.parameters.length; + int length = ctor.parameters.where((p) => !p.isNamed).length; Function create = classMirror.newInstance; Symbol name = ctor.constructorName; Function factory; @@ -184,9 +184,7 @@ class DynamicTypeFactories extends TypeReflector { List _generateParameterKeys(Type type) { ClassMirror classMirror = _reflectClass(type); MethodMirror ctor = classMirror.declarations[classMirror.simpleName]; - - return new List.generate(ctor.parameters.length, (int pos) { - ParameterMirror p = ctor.parameters[pos]; + return new List.from(ctor.parameters.where((p) => !p.isNamed).map((ParameterMirror p) { if (p.type.qualifiedName == #dynamic) { var name = MirrorSystem.getName(p.simpleName); throw new DynamicReflectorError("Error getting params for '$type': " @@ -198,7 +196,7 @@ class DynamicTypeFactories extends TypeReflector { } if (p.metadata.length > 1) { throw new DynamicReflectorError( - "Constructor '${classMirror.simpleName}' parameter $pos of type " + "Constructor '${classMirror.simpleName}' parameter of type " "'${p.type}' can have only zero on one annotation, but it has " "'${p.metadata}'."); } @@ -210,7 +208,7 @@ class DynamicTypeFactories extends TypeReflector { } var annotationType = p.metadata.isNotEmpty ? p.metadata.first.type.reflectedType : null; return new Key(pType, annotationType); - }, growable:false); + }), growable:false); } ClassMirror _reflectClass(Type type) { diff --git a/lib/transformer/injector_generator.dart b/lib/transformer/injector_generator.dart index a524fa7..e7f8adf 100644 --- a/lib/transformer/injector_generator.dart +++ b/lib/transformer/injector_generator.dart @@ -3,6 +3,7 @@ library di.transformer.injector_generator; import 'dart:async'; import 'package:analyzer/src/generated/ast.dart'; import 'package:analyzer/src/generated/element.dart'; +import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:barback/barback.dart'; import 'package:code_transformers/resolver.dart'; import 'package:path/path.dart' as path; @@ -281,10 +282,6 @@ class _Processor { String _generateInjectLibrary(Iterable constructors) { var prefixes = {}; - var ctorTypes = constructors.map((ctor) => ctor.enclosingElement).toSet(); - var paramTypes = constructors.expand((ctor) => ctor.parameters) - .map((param) => param.type.element).toSet(); - var usedLibs = new Set(); String resolveClassName(ClassElement type) { var library = type.library; @@ -308,13 +305,15 @@ class _Processor { for (var ctor in constructors) { var type = ctor.enclosingElement; var typeName = resolveClassName(type); + Iterable parameters = + ctor.parameters.where((p) => p.parameterKind != ParameterKind.NAMED); - String args = new List.generate(ctor.parameters.length, (i) => 'a${i+1}').join(', '); + String args = new List.generate(parameters.length, (i) => 'a${i+1}').join(', '); factoriesBuffer.write(' $typeName: ($args) => new $typeName($args),\n'); paramsBuffer.write(' $typeName: '); - paramsBuffer.write(ctor.parameters.isEmpty ? 'const[' : '['); - var params = ctor.parameters.map((param) { + paramsBuffer.write(parameters.isEmpty ? 'const[' : '['); + var params = parameters.map((param) { var typeName = resolveClassName(param.type.element); Iterable annotations = []; if (param.metadata.isNotEmpty) { diff --git a/test/main.dart b/test/main.dart index f3d1886..4c27836 100644 --- a/test/main.dart +++ b/test/main.dart @@ -200,6 +200,20 @@ class SameEngine { SameEngine(this.engine); } +@Injectable() +class OptionalParam { + Engine engine; + OptionalParam([this.engine]); +} + +@Injectable() +class NamedParam { + Engine engine; + NamedParam({Engine e}) { + engine = e; + } +} + const String STATIC_NAME = 'Static ModuleInjector'; const String DYNAMIC_NAME = 'Dynamic ModuleInjector'; @@ -574,6 +588,28 @@ createInjectorSpec(String injectorName, ModuleFactory moduleFactory) { }); + it('should inject optional parameters', () { + var module = moduleFactory() + ..bind(Engine) + ..bind(OptionalParam); + var injector = new ModuleInjector([module]); + + var optional = injector.get(OptionalParam); + expect(optional.engine).toBeNotNull(); + }); + + + it('should not inject named parameters', () { + var module = moduleFactory() + ..bind(Engine) + ..bind(NamedParam); + var injector = new ModuleInjector([module]); + + var named = injector.get(NamedParam); + expect(named.engine).toBeNull(); + }); + + it('should inject a typedef', () { var module = moduleFactory()..bind(CompareInt, toValue: compareIntAsc); diff --git a/test/transformer_test.dart b/test/transformer_test.dart index dde949f..0b40199 100644 --- a/test/transformer_test.dart +++ b/test/transformer_test.dart @@ -541,6 +541,41 @@ main() { ]); }); + it('ignores named parameters', () { + return generates(phases, + inputs: { + 'a|web/main.dart': ''' + import "package:inject/inject.dart"; + class Car { + Engine engine; + + @inject + Car({Engine e}) { + engine = e; + } + } + + class Engine { + @inject + Engine(); + } + + main() {} + ''' + }, + imports: [ + "import 'main.dart' as import_0;", + ], + factories: [ + 'import_0.Car: () => new import_0.Car(),', + 'import_0.Engine: () => new import_0.Engine(),', + ], + paramKeys: [ + 'import_0.Car: const[],', + 'import_0.Engine: const[],', + ]); + }); + it('supports injectableTypes argument', () { return generates(phases, inputs: {