Skip to content

Commit

Permalink
Create system to register LiteralConverters
Browse files Browse the repository at this point in the history
This will make it much easier for extensions to register their
literal converters.

Also, refactor `DefaultTypeSerializerEnricher` to implement
`IResourceFileEnricher` executed by the
`ResourceFileCompilationEnricher`.
  • Loading branch information
brantburnett committed Nov 2, 2024
1 parent f18e744 commit 3ade6a2
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ public static IServiceCollection AddDefaultCompilationEnrichers(this IServiceCol
.AddCompilationEnricher<ResourceFileCompilationEnricher>()
.AddCompilationEnricher<SyntaxTreeCompilationEnricher>()
.AddCompilationEnricher<OpenApiCompilationEnricher>()
.AddCompilationEnricher<DefaultTypeSerializersEnricher>()
.AddCompilationEnricher<FormatCompilationEnricher>();
.AddCompilationEnricher<FormatCompilationEnricher>()
.AddResourceFileEnricher<DefaultTypeSerializersEnricher>()
.AddResourceFileEnricher<DefaultLiteralConvertersEnricher>();

public static IServiceCollection AddAssemblyInfoEnricher<T>(this IServiceCollection services)
where T : class, IAssemblyInfoEnricher =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Yardarm.Enrichment.Compilation;

public class DefaultLiteralConvertersEnricher(
IEnumerable<IDefaultLiteralConverterEnricher> createDefaultRegistryEnrichers)
: IResourceFileEnricher
{
public bool ShouldEnrich(string resourceName) =>
resourceName == "Yardarm.Client.Serialization.Literals.LiteralConverterRegistry.cs";

public CompilationUnitSyntax Enrich(CompilationUnitSyntax target, ResourceFileEnrichmentContext context)
{
ClassDeclarationSyntax? classDeclaration = target
.DescendantNodes()
.OfType<ClassDeclarationSyntax>()
.FirstOrDefault(p => p.Identifier.ValueText == "LiteralConverterRegistry");

MethodDeclarationSyntax? methodDeclaration = classDeclaration?
.ChildNodes()
.OfType<MethodDeclarationSyntax>()
.FirstOrDefault(p => p.Identifier.ValueText == "CreateDefaultRegistry");

if (methodDeclaration?.ExpressionBody != null)
{
MethodDeclarationSyntax newMethodDeclaration = methodDeclaration.WithExpressionBody(
methodDeclaration.ExpressionBody.WithExpression(
methodDeclaration.ExpressionBody.Expression.Enrich(createDefaultRegistryEnrichers)));

target = target.ReplaceNode(methodDeclaration, newMethodDeclaration);
}

return target;
}
}
Original file line number Diff line number Diff line change
@@ -1,62 +1,38 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Yardarm.Enrichment.Compilation
namespace Yardarm.Enrichment.Compilation;

public class DefaultTypeSerializersEnricher(
IEnumerable<ICreateDefaultRegistryEnricher> createDefaultRegistryEnrichers) :
IResourceFileEnricher
{
public class DefaultTypeSerializersEnricher : ICompilationEnricher
{
private readonly IList<ICreateDefaultRegistryEnricher> _createDefaultRegistryEnrichers;
public bool ShouldEnrich(string resourceName) =>
resourceName == "Yardarm.Client.Serialization.TypeSerializerRegistry.cs";

public Type[] ExecuteAfter { get; } =
{
typeof(SyntaxTreeCompilationEnricher)
};
public CompilationUnitSyntax Enrich(CompilationUnitSyntax target, ResourceFileEnrichmentContext context)
{
ClassDeclarationSyntax? classDeclaration = target
.DescendantNodes()
.OfType<ClassDeclarationSyntax>()
.FirstOrDefault(p => p.Identifier.ValueText == "TypeSerializerRegistry");

public DefaultTypeSerializersEnricher(
IEnumerable<ICreateDefaultRegistryEnricher> createDefaultRegistryEnrichers)
{
_createDefaultRegistryEnrichers = createDefaultRegistryEnrichers.ToArray();
}
MethodDeclarationSyntax? methodDeclaration = classDeclaration?
.ChildNodes()
.OfType<MethodDeclarationSyntax>()
.FirstOrDefault(p => p.Identifier.ValueText == "CreateDefaultRegistry");

public async ValueTask<CSharpCompilation> EnrichAsync(CSharpCompilation target,
CancellationToken cancellationToken = default)
if (methodDeclaration?.ExpressionBody != null)
{
foreach (SyntaxTree syntaxTree in target.SyntaxTrees)
{
SyntaxNode rootNode = await syntaxTree.GetRootAsync(cancellationToken)
.ConfigureAwait(false);
MethodDeclarationSyntax newMethodDeclaration = methodDeclaration.WithExpressionBody(
methodDeclaration.ExpressionBody.WithExpression(
methodDeclaration.ExpressionBody.Expression.Enrich(createDefaultRegistryEnrichers)));

ClassDeclarationSyntax? classDeclaration = rootNode
.DescendantNodes()
.OfType<ClassDeclarationSyntax>()
.FirstOrDefault(p => p.Identifier.ValueText == "TypeSerializerRegistry");

MethodDeclarationSyntax? methodDeclaration = classDeclaration?
.ChildNodes()
.OfType<MethodDeclarationSyntax>()
.FirstOrDefault(p => p.Identifier.ValueText == "CreateDefaultRegistry");

if (methodDeclaration?.ExpressionBody != null)
{
MethodDeclarationSyntax newMethodDeclaration = methodDeclaration.WithExpressionBody(
methodDeclaration.ExpressionBody.WithExpression(
methodDeclaration.ExpressionBody.Expression.Enrich(_createDefaultRegistryEnrichers)));

rootNode = rootNode.ReplaceNode(methodDeclaration, newMethodDeclaration);

// Break once we've found what we're looking for
return target.ReplaceSyntaxTree(syntaxTree,
syntaxTree.WithRootAndOptions(rootNode, syntaxTree.Options));
}
}

return target;
target = target.ReplaceNode(methodDeclaration, newMethodDeclaration);
}

return target;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.Extensions.Logging;
using Yardarm.Generation;

namespace Yardarm.Enrichment.Compilation
{
Expand All @@ -27,13 +26,12 @@ public class FormatCompilationEnricher : ICompilationEnricher
private readonly ILogger<FormatCompilationEnricher> _logger;

public Type[] ExecuteAfter { get; } =
{
[
typeof(VersionAssemblyInfoEnricher),
typeof(SyntaxTreeCompilationEnricher),
typeof(DefaultTypeSerializersEnricher),
typeof(OpenApiCompilationEnricher),
typeof(ResourceFileCompilationEnricher)
};
];

public FormatCompilationEnricher(YardarmGenerationSettings settings,
ILogger<FormatCompilationEnricher> logger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public class OpenApiCompilationEnricher : ICompilationEnricher
private readonly ConcurrentBag<SyntaxTree> _toAdd = [];

public Type[] ExecuteAfter { get; } =
{
typeof(DefaultTypeSerializersEnricher)
};
[
typeof(ResourceFileCompilationEnricher),
];

public OpenApiCompilationEnricher(IOpenApiElementRegistry elementRegistry,
IEnumerable<IOpenApiSyntaxNodeEnricher> enrichers)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public static IServiceCollection AddCreateDefaultRegistryEnricher<T>(this IServi
where T : class, ICreateDefaultRegistryEnricher =>
services.AddTransient<ICreateDefaultRegistryEnricher, T>();

public static IServiceCollection AddDefaultLiteralConverterEnricher<T>(this IServiceCollection services)
where T : class, IDefaultLiteralConverterEnricher =>
services.AddTransient<IDefaultLiteralConverterEnricher, T>();

public static IServiceCollection AddOpenApiSyntaxNodeEnricher<T>(this IServiceCollection services)
where T : class, IOpenApiSyntaxNodeEnricher =>
services.AddTransient<IOpenApiSyntaxNodeEnricher, T>();
Expand Down
10 changes: 10 additions & 0 deletions src/main/Yardarm/Enrichment/IDefaultLiteralConverterEnricher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Yardarm.Enrichment;

/// <summary>
/// Enriches the body of the CreateDefaultRegistry method in the LiteralConverterRegistry class.
/// </summary>
public interface IDefaultLiteralConverterEnricher : IEnricher<ExpressionSyntax>
{
}

0 comments on commit 3ade6a2

Please sign in to comment.