container@1.0.0

This commit is contained in:
Tobe O 2018-11-30 09:23:34 -05:00
parent d0efa81089
commit bdf8e79d1d
9 changed files with 4946 additions and 147 deletions

View file

@ -0,0 +1,3 @@
analyzer:
strong-mode:
implicit-casts: false

View file

@ -86,7 +86,7 @@ class Container {
return reflectedType.newInstance( return reflectedType.newInstance(
isDefault(constructor.name) ? '' : constructor.name, isDefault(constructor.name) ? '' : constructor.name,
positional, positional,
named, []).reflectee; named, []).reflectee as T;
} else { } else {
throw new ReflectionException( throw new ReflectionException(
'$type is not a class, and therefore cannot be instantiated.'); '$type is not a class, and therefore cannot be instantiated.');

View file

@ -0,0 +1,3 @@
analyzer:
#strong-mode:
#implicit-casts: false

View file

@ -8,14 +8,15 @@ const Reflectable contained = const ContainedReflectable();
class ContainedReflectable extends Reflectable { class ContainedReflectable extends Reflectable {
const ContainedReflectable() const ContainedReflectable()
: super( : super(
declarationsCapability, declarationsCapability,
instanceInvokeCapability, instanceInvokeCapability,
invokingCapability, invokingCapability,
metadataCapability, metadataCapability,
newInstanceCapability, newInstanceCapability,
reflectedTypeCapability, reflectedTypeCapability,
typeRelationsCapability, typeRelationsCapability,
typeCapability); typeCapability,
);
} }
/// A [Reflector] instance that uses a [Reflectable] to reflect upon data. /// A [Reflector] instance that uses a [Reflectable] to reflect upon data.
@ -74,8 +75,9 @@ class GeneratedReflector implements Reflector {
class _GeneratedReflectedInstance extends ReflectedInstance { class _GeneratedReflectedInstance extends ReflectedInstance {
final InstanceMirror mirror; final InstanceMirror mirror;
final GeneratedReflector reflector;
_GeneratedReflectedInstance(this.mirror, Reflector reflector) _GeneratedReflectedInstance(this.mirror, this.reflector)
: super(null, new _GeneratedReflectedClass(mirror.type, reflector), : super(null, new _GeneratedReflectedClass(mirror.type, reflector),
mirror.reflectee); mirror.reflectee);
@ -84,7 +86,9 @@ class _GeneratedReflectedInstance extends ReflectedInstance {
@override @override
ReflectedInstance getField(String name) { ReflectedInstance getField(String name) {
return mirror.invokeGetter(name); var result = mirror.invokeGetter(name);
var instance = reflector.reflectable.reflect(result);
return new _GeneratedReflectedInstance(instance, reflector);
} }
} }
@ -93,13 +97,19 @@ class _GeneratedReflectedClass extends ReflectedClass {
final Reflector reflector; final Reflector reflector;
_GeneratedReflectedClass(this.mirror, this.reflector) _GeneratedReflectedClass(this.mirror, this.reflector)
: super( : super(mirror.simpleName, null, null, null, null, mirror.reflectedType);
mirror.simpleName,
mirror.typeVariables.map(_convertTypeVariable).toList(), @override
null, List<ReflectedTypeParameter> get typeParameters =>
_constructorsOf(mirror.declarations, reflector), mirror.typeVariables.map(_convertTypeVariable).toList();
_declarationsOf(mirror.declarations, reflector),
mirror.reflectedType); @override
List<ReflectedFunction> get constructors =>
_constructorsOf(mirror.declarations, reflector);
@override
List<ReflectedDeclaration> get declarations =>
_declarationsOf(mirror.declarations, reflector);
@override @override
List<ReflectedInstance> get annotations => List<ReflectedInstance> get annotations =>
@ -120,6 +130,7 @@ class _GeneratedReflectedClass extends ReflectedClass {
ReflectedInstance newInstance( ReflectedInstance newInstance(
String constructorName, List positionalArguments, String constructorName, List positionalArguments,
[Map<String, dynamic> namedArguments, List<Type> typeArguments]) { [Map<String, dynamic> namedArguments, List<Type> typeArguments]) {
namedArguments ??= {};
var result = mirror.newInstance(constructorName, positionalArguments, var result = mirror.newInstance(constructorName, positionalArguments,
namedArguments.map((k, v) => new MapEntry(new Symbol(k), v))); namedArguments.map((k, v) => new MapEntry(new Symbol(k), v)));
return reflector.reflectInstance(result); return reflector.reflectInstance(result);
@ -130,10 +141,11 @@ class _GeneratedReflectedType extends ReflectedType {
final TypeMirror mirror; final TypeMirror mirror;
_GeneratedReflectedType(this.mirror) _GeneratedReflectedType(this.mirror)
: super( : super(mirror.simpleName, null, mirror.reflectedType);
mirror.simpleName,
mirror.typeVariables.map(_convertTypeVariable).toList(), @override
mirror.reflectedType); List<ReflectedTypeParameter> get typeParameters =>
mirror.typeVariables.map(_convertTypeVariable).toList();
@override @override
bool isAssignableTo(ReflectedType other) { bool isAssignableTo(ReflectedType other) {

View file

@ -1,7 +1,7 @@
name: angel_container_generator name: angel_container_generator
version: 1.0.0-alpha version: 1.0.0
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
description: Code generator that generates `Reflector` subclasses. Use this to run Angel applications on Flutter, where reflection via `dart:mirrors` is disallowed. description: Codegen support for using pkg:reflectable with pkg:angel_container.
homepage: https://github.com/angel-dart/container.git homepage: https://github.com/angel-dart/container.git
environment: environment:
sdk: ">=2.0.0-dev <3.0.0" sdk: ">=2.0.0-dev <3.0.0"

View file

@ -1,18 +1,21 @@
import 'package:angel_container/angel_container.dart'; import 'package:angel_container/angel_container.dart';
import 'package:angel_container_generator/angel_container_generator.dart'; import 'package:angel_container_generator/angel_container_generator.dart';
@GlobalQuantifyCapability(
r'^dart\.core\.(Iterable|List|String|int|Object)', contained)
import 'package:reflectable/reflectable.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'reflector_test.reflectable.dart'; import 'reflector_test.reflectable.dart';
void main() { void main() {
initializeReflectable(); initializeReflectable();
var artist = new Artist();
var reflector = const GeneratedReflector(); var reflector = const GeneratedReflector();
Container container; Container container;
setUp(() { setUp(() {
container = new Container(reflector); container = new Container(reflector);
container.registerSingleton(artist); container.registerSingleton(new Artist(name: 'Stevie Wonder'));
//container.registerSingleton(new Artist(name: 'Tobe Osakwe'));
}); });
group('reflectClass', () { group('reflectClass', () {
@ -26,19 +29,136 @@ void main() {
test('inject constructor parameters', () { test('inject constructor parameters', () {
var album = container.make<Album>(); var album = container.make<Album>();
print(album.title); print(album.title);
expect(album.title, 'flowers by ${artist.lowerName}'); expect(album.title, 'flowers by stevie wonder');
});
testReflector(reflector);
}
@contained
void returnVoidFromAFunction(int x) {}
void testReflector(Reflector reflector) {
var blaziken = new Pokemon('Blaziken', PokemonType.fire);
Container container;
setUp(() {
container = new Container(reflector);
container.registerSingleton(blaziken);
});
test('get field', () {
var blazikenMirror = reflector.reflectInstance(blaziken);
expect(blazikenMirror.getField('type').reflectee, blaziken.type);
});
/*
group('reflectFunction', () {
var mirror = reflector.reflectFunction(returnVoidFromAFunction);
test('void return type returns dynamic', () {
expect(mirror.returnType, reflector.reflectType(dynamic));
});
test('counts parameters', () {
expect(mirror.parameters, hasLength(1));
});
test('counts types parameters', () {
expect(mirror.typeParameters, isEmpty);
});
test('correctly reflects parameter types', () {
var p = mirror.parameters[0];
expect(p.name, 'x');
expect(p.isRequired, true);
expect(p.isNamed, false);
expect(p.annotations, isEmpty);
expect(p.type, reflector.reflectType(int));
});
}, skip: 'pkg:reflectable cannot reflect on closures at all (yet)');
*/
test('make on singleton type returns singleton', () {
expect(container.make(Pokemon), blaziken);
});
test('make with generic returns same as make with explicit type', () {
expect(container.make<Pokemon>(), blaziken);
});
test('make on aliased singleton returns singleton', () {
container.registerSingleton(blaziken, as: StateError);
expect(container.make(StateError), blaziken);
});
test('constructor injects singleton', () {
var lower = container.make<LowerPokemon>();
expect(lower.lowercaseName, blaziken.name.toLowerCase());
});
test('newInstance works', () {
var type = container.reflector.reflectType(Pokemon);
var instance =
type.newInstance('changeName', [blaziken, 'Charizard']).reflectee
as Pokemon;
print(instance);
expect(instance.name, 'Charizard');
expect(instance.type, PokemonType.fire);
});
test('isAssignableTo', () {
var pokemonType = container.reflector.reflectType(Pokemon);
var kantoPokemonType = container.reflector.reflectType(KantoPokemon);
expect(kantoPokemonType.isAssignableTo(pokemonType), true);
expect(
kantoPokemonType
.isAssignableTo(container.reflector.reflectType(String)),
false);
}); });
} }
@contained @contained
class Artist { class LowerPokemon {
//final String name; final Pokemon pokemon;
//Artist({this.name}); LowerPokemon(this.pokemon);
String get lowercaseName => pokemon.name.toLowerCase();
}
@contained
class Pokemon {
final String name;
final PokemonType type;
Pokemon(this.name, this.type);
factory Pokemon.changeName(Pokemon other, String name) {
return new Pokemon(name, other.type);
}
@override
String toString() => 'NAME: $name, TYPE: $type';
}
@contained
class KantoPokemon extends Pokemon {
KantoPokemon(String name, PokemonType type) : super(name, type);
}
@contained
enum PokemonType { water, fire, grass, ice, poison, flying }
@contained
class Artist {
final String name;
Artist({this.name});
String get lowerName { String get lowerName {
//return name.toLowerCase(); return name.toLowerCase();
return hashCode.toString().toLowerCase();
} }
} }
@ -50,3 +170,13 @@ class Album {
String get title => 'flowers by ${artist.lowerName}'; String get title => 'flowers by ${artist.lowerName}';
} }
@contained
class AlbumLength {
final Artist artist;
final Album album;
AlbumLength(this.artist, this.album);
int get totalLength => artist.name.length + album.title.length;
}

File diff suppressed because it is too large Load diff