Skip to content

Commit

Permalink
Added Support for NodeResolvers with the new Resolver Compiler. (#7185)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Jun 20, 2024
1 parent 7b5dd10 commit 336ffcd
Show file tree
Hide file tree
Showing 43 changed files with 443 additions and 200 deletions.
18 changes: 18 additions & 0 deletions src/HotChocolate/Core/src/Types.Analyzers/Errors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,22 @@ public static class Errors
category: "TypeSystem",
DiagnosticSeverity.Error,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor TooManyNodeResolverArguments =
new(
id: "HCXXXX",
title: "Too Many Arguments.",
messageFormat: "A node resolver can only have a single field argument called `id`.",
category: "TypeSystem",
DiagnosticSeverity.Error,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor InvalidNodeResolverArgumentName =
new(
id: "HCXXXX",
title: "Invalid Argument Name.",
messageFormat: "A node resolver can only have a single field argument called `id`.",
category: "TypeSystem",
DiagnosticSeverity.Error,
isEnabledByDefault: true);
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ public void WriteInitializeMethod(ObjectTypeExtensionInfo objectTypeExtension)
_writer.WriteIndentedLine("| global::{0}.Static;", WellKnownTypes.BindingFlags);
}
}
}

_writer.WriteIndentedLine(
"var thisType = typeof({0});",
objectTypeExtension.Type.ToFullyQualified());
_writer.WriteIndentedLine(
"var thisType = typeof({0});",
objectTypeExtension.Type.ToFullyQualified());
}

if (objectTypeExtension.NodeResolver is not null)
{
Expand All @@ -78,9 +78,10 @@ public void WriteInitializeMethod(ObjectTypeExtensionInfo objectTypeExtension)
{
_writer.WriteIndentedLine(".ImplementsNode()");
_writer.WriteIndentedLine(
".ResolveNodeWith((global::System.Reflection.MethodInfo)" +
"thisType.GetMember(\"{0}\", bindingFlags)[0]);",
objectTypeExtension.NodeResolver.Name);
".ResolveNode({0}Resolvers.{1}_{2});",
objectTypeExtension.Type.ToDisplayString(),
objectTypeExtension.Type.Name,
objectTypeExtension.NodeResolver.Member.Name);
}
}

Expand All @@ -97,22 +98,13 @@ public void WriteInitializeMethod(ObjectTypeExtensionInfo objectTypeExtension)
".Field(thisType.GetMember(\"{0}\", bindingFlags)[0])",
resolver.Member.Name);

if (resolver.IsPure)
{
_writer.WriteIndentedLine(
".Extend().Definition.PureResolver = {0}Resolvers.{1}_{2};",
objectTypeExtension.Type.ToDisplayString(),
objectTypeExtension.Type.Name,
resolver.Member.Name);
}
else
{
_writer.WriteIndentedLine(
".Extend().Definition.Resolver = {0}Resolvers.{1}_{2};",
objectTypeExtension.Type.ToDisplayString(),
objectTypeExtension.Type.Name,
resolver.Member.Name);
}
_writer.WriteIndentedLine(
resolver.IsPure
? ".Extend().Definition.PureResolver = {0}Resolvers.{1}_{2};"
: ".Extend().Definition.Resolver = {0}Resolvers.{1}_{2};",
objectTypeExtension.Type.ToDisplayString(),
objectTypeExtension.Type.Name,
resolver.Member.Name);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Immutable;
using System.Text;
using HotChocolate.Types.Analyzers.Generators;
using HotChocolate.Types.Analyzers.Helpers;
Expand Down Expand Up @@ -46,9 +47,9 @@ public void WriteEndClass()
_writer.WriteIndentedLine("}");
}

public bool AddResolverDeclarations(IEnumerable<Resolver> resolvers)
public bool AddResolverDeclarations(ImmutableArray<Resolver> resolvers)
{
var first = true;
var any = false;

foreach (var resolver in resolvers)
{
Expand All @@ -57,12 +58,7 @@ public bool AddResolverDeclarations(IEnumerable<Resolver> resolvers)
continue;
}

if (!first)
{
_writer.WriteLine();
}

first = false;
any = true;

_writer.WriteIndentedLine(
"private readonly static global::{0}[] _args_{1}_{2} = new global::{0}[{3}];",
Expand All @@ -72,7 +68,7 @@ public bool AddResolverDeclarations(IEnumerable<Resolver> resolvers)
resolver.Parameters.Length);
}

return !first;
return any;
}

public void AddParameterInitializer(IEnumerable<Resolver> resolvers, ILocalTypeLookup typeLookup)
Expand Down Expand Up @@ -174,6 +170,49 @@ public void AddParameterInitializer(IEnumerable<Resolver> resolvers, ILocalTypeL
resolver.Member.Name,
i);
}

if (resolver.IsNodeResolver)
{
_writer.WriteLine();

_writer.WriteIndentedLine("int argumentCount = 0;");

_writer.WriteLine();

using (_writer.WriteForEach("binding", $"_args_{resolver.TypeName}_{resolver.Member.Name}"))
{
using (_writer.WriteIfClause(
"binding.Kind == global::{0}.Argument",
WellKnownTypes.ArgumentKind))
{
_writer.WriteIndentedLine("argumentCount++;");
}
}

_writer.WriteLine();

using (_writer.WriteIfClause("argumentCount > 1"))
{
_writer.WriteIndentedLine(
"throw new global::{0}(",
WellKnownTypes.SchemaException);
using (_writer.IncreaseIndent())
{
_writer.WriteIndentedLine(
"global::{0}.New()",
WellKnownTypes.SchemaErrorBuilder);
using (_writer.IncreaseIndent())
{
_writer.WriteIndentedLine(
".SetMessage(\"The node resolver `{0}.{1}` mustn't have more than one " +
"argument. Node resolvers can only have a single argument called `id`.\")",
resolver.Member.ContainingType.ToDisplayString(),
resolver.Member.Name);
_writer.WriteIndentedLine(".Build());");
}
}
}
}
}
}

Expand Down Expand Up @@ -329,7 +368,7 @@ private void AddStaticPropertyResolver(Resolver resolver)

private void AddResolverArguments(Resolver resolver, IMethodSymbol resolverMethod, ILocalTypeLookup typeLookup)
{
if (resolver.Parameters.Length <= 0)
if (resolver.Parameters.Length == 0)
{
return;
}
Expand All @@ -338,6 +377,18 @@ private void AddResolverArguments(Resolver resolver, IMethodSymbol resolverMetho
{
var parameter = resolver.Parameters[i];

if(resolver.IsNodeResolver
&& parameter.Kind is ResolverParameterKind.Argument or ResolverParameterKind.Unknown
&& (parameter.Name == "id" || parameter.Key == "id"))
{
_writer.WriteIndentedLine(
"var args{0} = context.GetLocalState<{1}>(" +
"global::HotChocolate.WellKnownContextData.InternalId);",
i,
parameter.Type.ToFullyQualified());
continue;
}

switch (parameter.Kind)
{
case ResolverParameterKind.Parent:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace HotChocolate.Types.Analyzers.Generators;

public sealed class DefaultLocalTypeLookup(ImmutableArray<ISyntaxInfo> syntaxInfos) : ILocalTypeLookup
public sealed class DefaultLocalTypeLookup(ImmutableArray<SyntaxInfo> syntaxInfos) : ILocalTypeLookup
{
private Dictionary<string, List<string>>? _typeNameLookup;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ public interface ISyntaxGenerator
void Generate(
SourceProductionContext context,
Compilation compilation,
ImmutableArray<ISyntaxInfo> syntaxInfos);
ImmutableArray<SyntaxInfo> syntaxInfos);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public sealed class MiddlewareGenerator : ISyntaxGenerator
public void Generate(
SourceProductionContext context,
Compilation compilation,
ImmutableArray<ISyntaxInfo> syntaxInfos)
ImmutableArray<SyntaxInfo> syntaxInfos)
{
if (syntaxInfos.IsEmpty)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ public sealed class TypeModuleSyntaxGenerator : ISyntaxGenerator
public void Generate(
SourceProductionContext context,
Compilation compilation,
ImmutableArray<ISyntaxInfo> syntaxInfos)
ImmutableArray<SyntaxInfo> syntaxInfos)
=> Execute(context, compilation, syntaxInfos);

private static void Execute(
SourceProductionContext context,
Compilation compilation,
ImmutableArray<ISyntaxInfo> syntaxInfos)
ImmutableArray<SyntaxInfo> syntaxInfos)
{
if (syntaxInfos.IsEmpty)
{
Expand All @@ -43,7 +43,7 @@ private static void Execute(

private static void WriteConfiguration(
SourceProductionContext context,
List<ISyntaxInfo> syntaxInfos,
List<SyntaxInfo> syntaxInfos,
ModuleInfo module)
{
using var generator = new ModuleFileBuilder(module.ModuleName, "Microsoft.Extensions.DependencyInjection");
Expand Down Expand Up @@ -157,7 +157,7 @@ private static void WriteConfiguration(

private static void WriteDataLoader(
SourceProductionContext context,
List<ISyntaxInfo> syntaxInfos,
List<SyntaxInfo> syntaxInfos,
DataLoaderDefaultsInfo defaults)
{
var dataLoaders = new List<DataLoaderInfo>();
Expand Down Expand Up @@ -257,7 +257,7 @@ private static void WriteDataLoader(

private static void WriteOperationTypes(
SourceProductionContext context,
List<ISyntaxInfo> syntaxInfos,
List<SyntaxInfo> syntaxInfos,
ModuleInfo module)
{
var operations = new List<OperationInfo>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ public sealed class TypesSyntaxGenerator : ISyntaxGenerator
public void Generate(
SourceProductionContext context,
Compilation compilation,
ImmutableArray<ISyntaxInfo> syntaxInfos)
ImmutableArray<SyntaxInfo> syntaxInfos)
=> Execute(context, syntaxInfos);

private static void Execute(
SourceProductionContext context,
ImmutableArray<ISyntaxInfo> syntaxInfos)
ImmutableArray<SyntaxInfo> syntaxInfos)
{
if (syntaxInfos.IsEmpty)
{
Expand All @@ -37,7 +37,7 @@ private static void Execute(

private static void WriteTypes(
SourceProductionContext context,
ImmutableArray<ISyntaxInfo> syntaxInfos,
ImmutableArray<SyntaxInfo> syntaxInfos,
StringBuilder sb)
{
var firstNamespace = true;
Expand All @@ -60,11 +60,6 @@ private static void WriteTypes(
{
if (objectTypeExtension.Diagnostics.Length > 0)
{
foreach (var diagnostic in objectTypeExtension.Diagnostics)
{
context.ReportDiagnostic(diagnostic);
}

continue;
}

Expand All @@ -89,7 +84,7 @@ private static void WriteTypes(

private static void WriteResolvers(
SourceProductionContext context,
ImmutableArray<ISyntaxInfo> syntaxInfos,
ImmutableArray<SyntaxInfo> syntaxInfos,
StringBuilder sb)
{
var typeLookup = new DefaultLocalTypeLookup(syntaxInfos);
Expand Down Expand Up @@ -119,16 +114,23 @@ private static void WriteResolvers(
}
firstClass = false;

var resolvers = objectTypeExtension.Resolvers;

if (objectTypeExtension.NodeResolver is not null)
{
resolvers = resolvers.Add(objectTypeExtension.NodeResolver);
}

generator.WriteBeginClass(objectTypeExtension.Type.Name + "Resolvers");

if (generator.AddResolverDeclarations(objectTypeExtension.Resolvers))
if (generator.AddResolverDeclarations(resolvers))
{
sb.AppendLine();
}

generator.AddParameterInitializer(objectTypeExtension.Resolvers, typeLookup);
generator.AddParameterInitializer(resolvers, typeLookup);

foreach (var resolver in objectTypeExtension.Resolvers)
foreach (var resolver in resolvers)
{
sb.AppendLine();
generator.AddResolver(resolver, typeLookup);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
private static bool Predicate(SyntaxNode node)
=> _predicate(node);

private static ISyntaxInfo? Transform(GeneratorSyntaxContext context)
private static SyntaxInfo? Transform(GeneratorSyntaxContext context)
{
for (var i = 0; i < _inspectors.Length; i++)
{
Expand All @@ -81,18 +81,29 @@ private static bool Predicate(SyntaxNode node)
private static void Execute(
SourceProductionContext context,
Compilation compilation,
ImmutableArray<ISyntaxInfo> syntaxInfos)
ImmutableArray<SyntaxInfo> syntaxInfos)
{
for (var i = 0; i < _generators.Length; i++)
foreach (var syntaxInfo in syntaxInfos.AsSpan())
{
_generators[i].Generate(context, compilation, syntaxInfos);
if (syntaxInfo.Diagnostics.Length > 0)
{
foreach (var diagnostic in syntaxInfo.Diagnostics.AsSpan())
{
context.ReportDiagnostic(diagnostic);
}
}
}

foreach (var generator in _generators.AsSpan())
{
generator.Generate(context, compilation, syntaxInfos);
}
}
}

file static class Extensions
{
public static IncrementalValuesProvider<ISyntaxInfo> WhereNotNull(
this IncrementalValuesProvider<ISyntaxInfo?> source)
public static IncrementalValuesProvider<SyntaxInfo> WhereNotNull(
this IncrementalValuesProvider<SyntaxInfo?> source)
=> source.Where(static t => t is not null)!;
}
Loading

0 comments on commit 336ffcd

Please sign in to comment.