Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refined Interface Handling #2627

Merged
merged 8 commits into from
Nov 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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);
}
}
Original file line number Diff line number Diff line change
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;
}
}
}
Original file line number Diff line number Diff line change
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);
}
}
}
}
}