diff --git a/angel_graphql/example/main.dart b/angel_graphql/example/main.dart index 06310af2..2982df7e 100644 --- a/angel_graphql/example/main.dart +++ b/angel_graphql/example/main.dart @@ -61,10 +61,15 @@ main() async { print('Access graphiql at $graphiqlUri'); } +@GraphQLDocumentation(description: 'Any object with a .text (String) property.') +abstract class HasText { + String get text; +} + @serializable @GraphQLDocumentation( description: 'A task that might not be completed yet. **Yay! Markdown!**') -class Todo extends Model { +class Todo extends Model implements HasText { String text; @GraphQLDocumentation(deprecationReason: 'Use `completion_status` instead.') diff --git a/graphql_server/lib/introspection.dart b/graphql_server/lib/introspection.dart index a2582b1d..fcdbe37b 100644 --- a/graphql_server/lib/introspection.dart +++ b/graphql_server/lib/introspection.dart @@ -427,12 +427,8 @@ List _fetchAllTypesFromObject(GraphQLObjectType objectType) { } } - for (var type in objectType.interfaces) { - types.addAll(_fetchAllTypesFromObject(type)); - } - - for (var type in objectType.possibleTypes) { - types.addAll(_fetchAllTypesFromObject(type)); + for (var i in objectType.interfaces) { + types.addAll(_fetchAllTypesFromObject(i)); } return types; diff --git a/graphql_server/lib/mirrors.dart b/graphql_server/lib/mirrors.dart index 51006114..21bfb2be 100644 --- a/graphql_server/lib/mirrors.dart +++ b/graphql_server/lib/mirrors.dart @@ -56,22 +56,71 @@ GraphQLType _objectTypeFromDartType(Type type, [List typeArguments]) { GraphQLObjectType objectTypeFromClassMirror(ClassMirror mirror) { var fields = []; - for (var name in mirror.instanceMembers.keys) { - var methodMirror = mirror.instanceMembers[name]; - var exclude = _getExclude(name, methodMirror); - var canAdd = name != #hashCode && - name != #runtimeType && - !methodMirror.isPrivate && - exclude?.canSerialize != true; - if (methodMirror.isGetter && canAdd) { - fields.add(fieldFromGetter(name, methodMirror, exclude, mirror)); + void walkMap(Map map) { + for (var name in map.keys) { + var methodMirror = map[name]; + var exclude = _getExclude(name, methodMirror); + var canAdd = name != #hashCode && + name != #runtimeType && + !methodMirror.isPrivate && + exclude?.canSerialize != true; + if (methodMirror.isGetter && canAdd) { + fields.add(fieldFromGetter(name, methodMirror, exclude, mirror)); + } } } + walkMap(mirror.instanceMembers); + + if (mirror.isAbstract) { + var decls = {}; + + mirror.declarations.forEach((name, decl) { + if (decl is MethodMirror) { + decls[name] = decl; + } + }); + + walkMap(decls); + } + + var inheritsFrom = []; + var primitiveTypes = const [ + String, + bool, + num, + int, + double, + Object, + dynamic, + Null, + Type, + Symbol + ]; + + void walk(ClassMirror parent) { + if (!primitiveTypes.contains(parent.reflectedType)) { + if (parent.isAbstract) { + var obj = convertDartType(parent.reflectedType); + + if (obj is GraphQLObjectType && !inheritsFrom.contains(obj)) { + inheritsFrom.add(obj); + } + } + + walk(parent.superclass); + parent.superinterfaces.forEach(walk); + } + } + + walk(mirror.superclass); + mirror.superinterfaces.forEach(walk); + return objectType( MirrorSystem.getName(mirror.simpleName), fields: fields, isInterface: mirror.isAbstract, + interfaces: inheritsFrom, description: _getDescription(mirror.metadata), ); } @@ -85,9 +134,7 @@ GraphQLEnumType enumTypeFromClassMirror(ClassMirror mirror) { values.add( new GraphQLEnumValue( MirrorSystem.getName(name), - mirror - .getField(name) - .reflectee, + mirror.getField(name).reflectee, description: _getDescription(methodMirror.metadata), deprecationReason: _getDeprecationReason(methodMirror.metadata), ),