Skip to content

Commit

Permalink
Refined Interface Handling (#2627)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib committed Nov 21, 2020
1 parent de376f2 commit 0379ff6
Show file tree
Hide file tree
Showing 44 changed files with 518 additions and 175 deletions.
Expand Up @@ -5,8 +5,7 @@

namespace HotChocolate.Configuration
{
public class TypeInterceptor
: ITypeInitializationInterceptor
public class TypeInterceptor : ITypeInitializationInterceptor
{
public virtual bool TriggerAggregations => false;

Expand All @@ -23,7 +22,7 @@ public class TypeInterceptor
IDictionary<string, object?> contextData)
{
}

public virtual void OnTypesInitialized(
IReadOnlyCollection<ITypeDiscoveryContext> discoveryContexts)
{
Expand Down
Expand Up @@ -110,7 +110,7 @@ private void VisitObject(ObjectType type)
{
VisitDirectives(type);

foreach (InterfaceType interfaceType in type.Interfaces)
foreach (InterfaceType interfaceType in type.Implements)
{
VisitInterface(interfaceType);
}
Expand Down
Expand Up @@ -55,9 +55,9 @@ internal static class ComplexOutputTypeValidationHelper
IComplexOutputType type,
ICollection<ISchemaError> errors)
{
if (type.Interfaces.Count > 0)
if (type.Implements.Count > 0)
{
foreach (IInterfaceType implementedType in type.Interfaces)
foreach (IInterfaceType implementedType in type.Implements)
{
ValidateImplementation(type, implementedType, errors);
}
Expand Down Expand Up @@ -131,7 +131,7 @@ internal static class ComplexOutputTypeValidationHelper
IComplexOutputType type,
IInterfaceType implementedType)
{
foreach (var interfaceType in implementedType.Interfaces)
foreach (var interfaceType in implementedType.Implements)
{
if (!type.IsImplementing(interfaceType))
{
Expand Down
Expand Up @@ -25,7 +25,7 @@ internal class InterfaceHasAtLeastOneImplementationRule

foreach (ObjectType objectType in typeSystemObjects.OfType<ObjectType>())
{
foreach (InterfaceType interfaceType in objectType.Interfaces)
foreach (InterfaceType interfaceType in objectType.Implements)
{
interfaceTypes.Remove(interfaceType);
}
Expand Down
Expand Up @@ -25,7 +25,7 @@ public static class TypeDependencyHelper

context.RegisterDependencyRange(
definition.Interfaces,
TypeDependencyKind.Default);
TypeDependencyKind.Completed);

RegisterAdditionalDependencies(context, definition);
RegisterDirectiveDependencies(context, definition);
Expand Down Expand Up @@ -79,7 +79,7 @@ public static class TypeDependencyHelper

context.RegisterDependencyRange(
definition.Interfaces,
TypeDependencyKind.Default);
TypeDependencyKind.Completed);

RegisterAdditionalDependencies(context, definition);
RegisterDirectiveDependencies(context, definition);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/HotChocolate/Core/src/Types/Properties/TypeResources.resx
Expand Up @@ -668,4 +668,7 @@ Type: `{0}`</value>
<data name="SpecifiedByDirectiveType_UrlDescription" xml:space="preserve">
<value>The specifiedBy URL points to a human-readable specification. This field will only read a result for scalar types.</value>
</data>
<data name="NodeType_TypeDescription" xml:space="preserve">
<value>The node interface is implemented by entities that have a global unique identifier.</value>
</data>
</root>
50 changes: 22 additions & 28 deletions src/HotChocolate/Core/src/Types/SchemaBuilder.cs
Expand Up @@ -18,29 +18,23 @@ public partial class SchemaBuilder : ISchemaBuilder
{
private delegate ITypeReference CreateRef(ITypeInspector typeInspector);

private readonly Dictionary<string, object> _contextData =
new Dictionary<string, object>();
private readonly List<FieldMiddleware> _globalComponents =
new List<FieldMiddleware>();
private readonly List<LoadSchemaDocument> _documents =
new List<LoadSchemaDocument>();
private readonly List<CreateRef> _types = new List<CreateRef>();
private readonly List<Type> _resolverTypes = new List<Type>();
private readonly Dictionary<OperationType, CreateRef> _operations =
new Dictionary<OperationType, CreateRef>();
private readonly Dictionary<FieldReference, FieldResolver> _resolvers =
new Dictionary<FieldReference, FieldResolver>();
private readonly Dictionary<(Type, string), List<CreateConvention>> _conventions =
new Dictionary<(Type, string), List<CreateConvention>>();
private readonly Dictionary<Type, (CreateRef, CreateRef)> _clrTypes =
new Dictionary<Type, (CreateRef, CreateRef)>();
private readonly List<object> _schemaInterceptors = new List<object>();
private readonly List<object> _typeInterceptors = new List<object>
private readonly Dictionary<string, object> _contextData = new();
private readonly List<FieldMiddleware> _globalComponents = new();
private readonly List<LoadSchemaDocument> _documents = new();
private readonly List<CreateRef> _types = new();
private readonly List<Type> _resolverTypes = new();
private readonly Dictionary<OperationType, CreateRef> _operations = new();
private readonly Dictionary<FieldReference, FieldResolver> _resolvers = new();
private readonly Dictionary<(Type, string), List<CreateConvention>> _conventions = new();
private readonly Dictionary<Type, (CreateRef, CreateRef)> _clrTypes = new();
private readonly List<object> _schemaInterceptors = new();
private readonly List<object> _typeInterceptors = new()
{
typeof(IntrospectionTypeInterceptor)
typeof(IntrospectionTypeInterceptor),
typeof(InterfaceCompletionTypeInterceptor)
};
private readonly IBindingCompiler _bindingCompiler = new BindingCompiler();
private SchemaOptions _options = new SchemaOptions();
private SchemaOptions _options = new();
private IsOfTypeFallback _isOfType;
private IServiceProvider _services;
private CreateRef _schema;
Expand Down Expand Up @@ -74,7 +68,7 @@ public ISchemaBuilder SetSchema(ISchema schema)

if (schema is TypeSystemObjectBase)
{
_schema = ti => new SchemaTypeReference(schema);
_schema = _ => new SchemaTypeReference(schema);
}
else
{
Expand All @@ -92,7 +86,7 @@ public ISchemaBuilder SetSchema(Action<ISchemaTypeDescriptor> configure)
throw new ArgumentNullException(nameof(configure));
}

_schema = ti => new SchemaTypeReference(new Schema(configure));
_schema = _ => new SchemaTypeReference(new Schema(configure));
return this;
}

Expand Down Expand Up @@ -255,7 +249,7 @@ public ISchemaBuilder AddType(INamedType type)
throw new ArgumentNullException(nameof(type));
}

_types.Add(ti => TypeReference.Create(type));
_types.Add(_ => TypeReference.Create(type));
return this;
}

Expand All @@ -266,7 +260,7 @@ public ISchemaBuilder AddType(INamedTypeExtension type)
throw new ArgumentNullException(nameof(type));
}

_types.Add(ti => TypeReference.Create(type));
_types.Add(_ => TypeReference.Create(type));
return this;
}

Expand All @@ -277,7 +271,7 @@ public ISchemaBuilder AddDirectiveType(DirectiveType type)
throw new ArgumentNullException(nameof(type));
}

_types.Add(ti => TypeReference.Create(type));
_types.Add(_ => TypeReference.Create(type));
return this;
}

Expand Down Expand Up @@ -345,8 +339,8 @@ public ISchemaBuilder AddDirectiveType(DirectiveType type)
}

SchemaTypeReference reference = TypeReference.Create(type);
_operations.Add(operation, ti => reference);
_types.Add(ti => reference);
_operations.Add(operation, _ => reference);
_types.Add(_ => reference);
return this;
}

Expand Down Expand Up @@ -491,6 +485,6 @@ public ISchemaBuilder TryAddSchemaInterceptor(ISchemaInterceptor interceptor)
return this;
}

public static SchemaBuilder New() => new SchemaBuilder();
public static SchemaBuilder New() => new();
}
}
8 changes: 6 additions & 2 deletions src/HotChocolate/Core/src/Types/SchemaSerializer.cs
Expand Up @@ -196,7 +196,7 @@ namedType switch
.Select(SerializeDirective)
.ToList();

var interfaces = objectType.Interfaces
var interfaces = objectType.Implements
.Select(SerializeNamedType)
.ToList();

Expand All @@ -223,6 +223,10 @@ namedType switch
.Select(SerializeDirective)
.ToList();

var interfaces = interfaceType.Implements
.Select(SerializeNamedType)
.ToList();

var fields = interfaceType.Fields
.Select(SerializeObjectField)
.ToList();
Expand All @@ -233,7 +237,7 @@ namedType switch
new NameNode(interfaceType.Name),
SerializeDescription(interfaceType.Description),
directives,
Array.Empty<NamedTypeNode>(),
interfaces,
fields
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/HotChocolate/Core/src/Types/SchemaTypes.cs
Expand Up @@ -101,7 +101,7 @@ public bool TryGetClrType(NameString typeName, out Type clrType)
{
possibleTypes[objectType.Name] = new List<ObjectType> { objectType };

foreach (InterfaceType interfaceType in objectType.Interfaces)
foreach (InterfaceType interfaceType in objectType.Implements)
{
if (!possibleTypes.TryGetValue(interfaceType.Name, out List<ObjectType> pt))
{
Expand Down
Expand Up @@ -13,7 +13,7 @@ public interface IComplexOutputType
/// <summary>
/// Gets the interfaces that are implemented by this type.
/// </summary>
IReadOnlyList<IInterfaceType> Interfaces { get; }
IReadOnlyList<IInterfaceType> Implements { get; }

/// <summary>
/// Gets the field that this type exposes.
Expand Down
Expand Up @@ -7,6 +7,8 @@ namespace HotChocolate.Types.Descriptors.Definitions
{
public interface IComplexOutputTypeDefinition
{
NameString Name { get; }

Type RuntimeType { get; }

IList<Type> KnownClrTypes { get; }
Expand Down
Expand Up @@ -24,6 +24,8 @@ public override Type RuntimeType

public IsOfType IsOfType { get; set; }

public bool IsExtension { get; set; }

public IList<ITypeReference> Interfaces { get; } =
new List<ITypeReference>();

Expand Down
Expand Up @@ -21,11 +21,7 @@ public virtual Type RuntimeType
get => _clrType;
set
{
if (value is null)
{
throw new ArgumentNullException(nameof(value));
}
_clrType = value;
_clrType = value ?? throw new ArgumentNullException(nameof(value));
}
}

Expand Down
Expand Up @@ -349,38 +349,37 @@ public IObjectTypeDescriptor Directive<T>()

public static ObjectTypeDescriptor New(
IDescriptorContext context) =>
new ObjectTypeDescriptor(context);
new(context);

public static ObjectTypeDescriptor New(
IDescriptorContext context,
Type clrType) =>
new ObjectTypeDescriptor(context, clrType);
new(context, clrType);

public static ObjectTypeDescriptor<T> New<T>(
IDescriptorContext context) =>
new ObjectTypeDescriptor<T>(context);
new(context);

public static ObjectTypeExtensionDescriptor<T> NewExtension<T>(
IDescriptorContext context) =>
new ObjectTypeExtensionDescriptor<T>(context);
new(context);

public static ObjectTypeDescriptor FromSchemaType(
IDescriptorContext context,
Type schemaType)
{
var descriptor = new ObjectTypeDescriptor(context, schemaType);
descriptor.Definition.RuntimeType = typeof(object);
return descriptor;
}
Type schemaType) =>
new ObjectTypeDescriptor(context, schemaType)
{
Definition = { RuntimeType = typeof(object) }
};

public static ObjectTypeDescriptor From(
IDescriptorContext context,
ObjectTypeDefinition definition) =>
new ObjectTypeDescriptor(context, definition);
new(context, definition);

public static ObjectTypeDescriptor<T> From<T>(
IDescriptorContext context,
ObjectTypeDefinition definition) =>
new ObjectTypeDescriptor<T>(context, definition);
new(context, definition);
}
}
Expand Up @@ -12,6 +12,7 @@ protected internal ObjectTypeExtensionDescriptor(IDescriptorContext context)
Definition.Description = context.Naming.GetTypeDescription(typeof(T), TypeKind.Object);
Definition.Fields.BindingBehavior = context.Options.DefaultBindingBehavior;
Definition.FieldBindingType = typeof(T);
Definition.IsExtension = true;
}
}
}
Expand Up @@ -13,29 +13,14 @@ namespace HotChocolate.Types
{
internal static class CompleteInterfacesHelper
{
public static void Complete(
public static void CompleteInterfaces(
ITypeCompletionContext context,
IComplexOutputTypeDefinition definition,
Type clrType,
ICollection<InterfaceType> interfaces,
ITypeSystemObject interfaceOrObject,
ISyntaxNode? node)
{
if (clrType != typeof(object))
{
TryInferInterfaceUsageFromClrType(context, clrType, interfaces);
}

if (definition.KnownClrTypes.Count > 0)
{
definition.KnownClrTypes.Remove(typeof(object));

foreach (Type type in definition.KnownClrTypes.Distinct())
{
TryInferInterfaceUsageFromClrType(context, type, interfaces);
}
}

foreach (ITypeReference interfaceRef in definition.Interfaces)
{
if (!context.TryGetType(interfaceRef, out InterfaceType type))
Expand All @@ -51,23 +36,5 @@ internal static class CompleteInterfacesHelper
}
}
}

private static void TryInferInterfaceUsageFromClrType(
ITypeCompletionContext context,
Type clrType,
ICollection<InterfaceType> interfaces)
{
foreach (Type interfaceType in clrType.GetInterfaces())
{
if (context.TryGetType(
context.DescriptorContext.TypeInspector.GetTypeRef(
interfaceType, TypeContext.Output),
out InterfaceType type) &&
!interfaces.Contains(type))
{
interfaces.Add(type);
}
}
}
}
}

0 comments on commit 0379ff6

Please sign in to comment.