Skip to content
This repository has been archived by the owner on Dec 6, 2017. It is now read-only.

fix(reflector): do not attempt to inject named params #153

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
10 changes: 7 additions & 3 deletions lib/generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -148,16 +149,19 @@ void process_classes(Iterable<ClassElement> 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<ParameterElement> 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}';
Expand Down
10 changes: 4 additions & 6 deletions lib/src/reflector_dynamic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -184,9 +184,7 @@ class DynamicTypeFactories extends TypeReflector {
List<Key> _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': "
Expand All @@ -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}'.");
}
Expand All @@ -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) {
Expand Down
13 changes: 6 additions & 7 deletions lib/transformer/injector_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -281,10 +282,6 @@ class _Processor {
String _generateInjectLibrary(Iterable<ConstructorElement> constructors) {
var prefixes = <LibraryElement, String>{};

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<LibraryElement>();
String resolveClassName(ClassElement type) {
var library = type.library;
Expand All @@ -308,13 +305,15 @@ class _Processor {
for (var ctor in constructors) {
var type = ctor.enclosingElement;
var typeName = resolveClassName(type);
Iterable<ParameterElement> 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<ClassElement> annotations = [];
if (param.metadata.isNotEmpty) {
Expand Down
36 changes: 36 additions & 0 deletions test/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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);

Expand Down
35 changes: 35 additions & 0 deletions test/transformer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down