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
|
|
@ -4,4 +4,4 @@ export 'src/container.dart';
|
||||||
export 'src/empty/empty.dart';
|
export 'src/empty/empty.dart';
|
||||||
export 'src/static/static.dart';
|
export 'src/static/static.dart';
|
||||||
export 'src/exception.dart';
|
export 'src/exception.dart';
|
||||||
export 'src/reflector.dart';
|
export 'src/reflector.dart';
|
||||||
|
|
|
@ -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.');
|
||||||
|
|
|
@ -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
|
|
@ -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) {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
Loading…
Reference in a new issue