container@1.0.0
This commit is contained in:
parent
d0efa81089
commit
bdf8e79d1d
9 changed files with 4946 additions and 147 deletions
3
angel_container/analysis_options.yaml
Normal file
3
angel_container/analysis_options.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
analyzer:
|
||||
strong-mode:
|
||||
implicit-casts: false
|
|
@ -86,7 +86,7 @@ class Container {
|
|||
return reflectedType.newInstance(
|
||||
isDefault(constructor.name) ? '' : constructor.name,
|
||||
positional,
|
||||
named, []).reflectee;
|
||||
named, []).reflectee as T;
|
||||
} else {
|
||||
throw new ReflectionException(
|
||||
'$type is not a class, and therefore cannot be instantiated.');
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
3
angel_container_generator/analysis_options.yaml
Normal file
3
angel_container_generator/analysis_options.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
analyzer:
|
||||
#strong-mode:
|
||||
#implicit-casts: false
|
|
@ -15,7 +15,8 @@ class ContainedReflectable extends Reflectable {
|
|||
newInstanceCapability,
|
||||
reflectedTypeCapability,
|
||||
typeRelationsCapability,
|
||||
typeCapability);
|
||||
typeCapability,
|
||||
);
|
||||
}
|
||||
|
||||
/// A [Reflector] instance that uses a [Reflectable] to reflect upon data.
|
||||
|
@ -74,8 +75,9 @@ class GeneratedReflector implements Reflector {
|
|||
|
||||
class _GeneratedReflectedInstance extends ReflectedInstance {
|
||||
final InstanceMirror mirror;
|
||||
final GeneratedReflector reflector;
|
||||
|
||||
_GeneratedReflectedInstance(this.mirror, Reflector reflector)
|
||||
_GeneratedReflectedInstance(this.mirror, this.reflector)
|
||||
: super(null, new _GeneratedReflectedClass(mirror.type, reflector),
|
||||
mirror.reflectee);
|
||||
|
||||
|
@ -84,7 +86,9 @@ class _GeneratedReflectedInstance extends ReflectedInstance {
|
|||
|
||||
@override
|
||||
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;
|
||||
|
||||
_GeneratedReflectedClass(this.mirror, this.reflector)
|
||||
: super(
|
||||
mirror.simpleName,
|
||||
mirror.typeVariables.map(_convertTypeVariable).toList(),
|
||||
null,
|
||||
_constructorsOf(mirror.declarations, reflector),
|
||||
_declarationsOf(mirror.declarations, reflector),
|
||||
mirror.reflectedType);
|
||||
: super(mirror.simpleName, null, null, null, null, mirror.reflectedType);
|
||||
|
||||
@override
|
||||
List<ReflectedTypeParameter> get typeParameters =>
|
||||
mirror.typeVariables.map(_convertTypeVariable).toList();
|
||||
|
||||
@override
|
||||
List<ReflectedFunction> get constructors =>
|
||||
_constructorsOf(mirror.declarations, reflector);
|
||||
|
||||
@override
|
||||
List<ReflectedDeclaration> get declarations =>
|
||||
_declarationsOf(mirror.declarations, reflector);
|
||||
|
||||
@override
|
||||
List<ReflectedInstance> get annotations =>
|
||||
|
@ -120,6 +130,7 @@ class _GeneratedReflectedClass extends ReflectedClass {
|
|||
ReflectedInstance newInstance(
|
||||
String constructorName, List positionalArguments,
|
||||
[Map<String, dynamic> namedArguments, List<Type> typeArguments]) {
|
||||
namedArguments ??= {};
|
||||
var result = mirror.newInstance(constructorName, positionalArguments,
|
||||
namedArguments.map((k, v) => new MapEntry(new Symbol(k), v)));
|
||||
return reflector.reflectInstance(result);
|
||||
|
@ -130,10 +141,11 @@ class _GeneratedReflectedType extends ReflectedType {
|
|||
final TypeMirror mirror;
|
||||
|
||||
_GeneratedReflectedType(this.mirror)
|
||||
: super(
|
||||
mirror.simpleName,
|
||||
mirror.typeVariables.map(_convertTypeVariable).toList(),
|
||||
mirror.reflectedType);
|
||||
: super(mirror.simpleName, null, mirror.reflectedType);
|
||||
|
||||
@override
|
||||
List<ReflectedTypeParameter> get typeParameters =>
|
||||
mirror.typeVariables.map(_convertTypeVariable).toList();
|
||||
|
||||
@override
|
||||
bool isAssignableTo(ReflectedType other) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: angel_container_generator
|
||||
version: 1.0.0-alpha
|
||||
version: 1.0.0
|
||||
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
|
||||
environment:
|
||||
sdk: ">=2.0.0-dev <3.0.0"
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
import 'package:angel_container/angel_container.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 'reflector_test.reflectable.dart';
|
||||
|
||||
void main() {
|
||||
initializeReflectable();
|
||||
var artist = new Artist();
|
||||
var reflector = const GeneratedReflector();
|
||||
Container container;
|
||||
|
||||
setUp(() {
|
||||
container = new Container(reflector);
|
||||
container.registerSingleton(artist);
|
||||
//container.registerSingleton(new Artist(name: 'Tobe Osakwe'));
|
||||
container.registerSingleton(new Artist(name: 'Stevie Wonder'));
|
||||
});
|
||||
|
||||
group('reflectClass', () {
|
||||
|
@ -26,19 +29,136 @@ void main() {
|
|||
test('inject constructor parameters', () {
|
||||
var album = container.make<Album>();
|
||||
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
|
||||
class Artist {
|
||||
//final String name;
|
||||
class LowerPokemon {
|
||||
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 {
|
||||
//return name.toLowerCase();
|
||||
return hashCode.toString().toLowerCase();
|
||||
return name.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,3 +170,13 @@ class Album {
|
|||
|
||||
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
Loading…
Reference in a new issue