Skip to content

Commit a1008be

Browse files
committed
refactor(generator): remove collection of required usings & move redundant code to utils
1 parent 16907ae commit a1008be

5 files changed

Lines changed: 40 additions & 59 deletions

File tree

CSharpFunctionalExtensions.HttpResults.Generators/Builders/ClassBuilder.cs

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,31 @@
11
using System.Text;
2+
using CSharpFunctionalExtensions.HttpResults.Generators.Utils;
23
using Microsoft.CodeAnalysis;
34
using Microsoft.CodeAnalysis.CSharp.Syntax;
45

56
namespace CSharpFunctionalExtensions.HttpResults.Generators.Builders;
67

78
public abstract class ClassBuilder
89
{
9-
private static readonly SymbolDisplayFormat FullyQualifiedWithNullables =
10-
SymbolDisplayFormat.FullyQualifiedFormat.WithMiscellaneousOptions(
11-
SymbolDisplayFormat.FullyQualifiedFormat.MiscellaneousOptions
12-
| SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier
13-
);
14-
1510
private const string MapMethodName = "Map";
16-
private readonly List<ClassDeclarationSyntax> _mapperClasses;
17-
private readonly HashSet<string> _requiredNamespaces;
1811
private readonly Compilation? _compilation;
12+
private readonly List<ClassDeclarationSyntax> _mapperClasses;
1913

20-
protected ClassBuilder(
21-
HashSet<string> requiredNamespaces,
22-
List<ClassDeclarationSyntax> mapperClasses,
23-
Compilation? compilation = null
24-
)
14+
protected ClassBuilder(List<ClassDeclarationSyntax> mapperClasses, Compilation? compilation = null)
2515
{
26-
_requiredNamespaces = requiredNamespaces;
2716
_mapperClasses = mapperClasses;
2817
_compilation = compilation;
2918
}
3019

3120
private static string DefaultUsings =>
3221
"""
3322
using CSharpFunctionalExtensions;
34-
using IResult = Microsoft.AspNetCore.Http.IResult;
3523
using Microsoft.AspNetCore.Http.HttpResults;
3624
using Microsoft.AspNetCore.Http;
3725
using Microsoft.AspNetCore.Mvc;
3826
using Microsoft.Net.Http.Headers;
3927
using System.Text;
28+
using IResult = Microsoft.AspNetCore.Http.IResult;
4029
""";
4130

4231
public string SourceFileName => $"{ClassName}.g.cs";
@@ -55,13 +44,6 @@ public string Build()
5544
sourceBuilder.AppendLine();
5645
sourceBuilder.AppendLine(DefaultUsings);
5746

58-
_requiredNamespaces
59-
.Where(@namespace => !@namespace.StartsWith("global"))
60-
.Distinct()
61-
.Select(@namespace => $"using {@namespace};")
62-
.ToList()
63-
.ForEach(@using => sourceBuilder.AppendLine(@using));
64-
6547
sourceBuilder.AppendLine();
6648
sourceBuilder.AppendLine(ClassSummary);
6749

@@ -82,7 +64,7 @@ public string Build()
8264
throw new ArgumentException($"Mapping method in class {mapperClassName} must have exactly one parameter.");
8365

8466
var resultErrorType = GetFullyQualifiedTypeName(mapperClass, mappingMethod.ParameterList.Parameters[0].Type!);
85-
var httpResultType = GetFullyQualifiedTypeName(mapperClass, mappingMethod.ReturnType!);
67+
var httpResultType = mappingMethod.ReturnType!.ToString();
8668

8769
foreach (var methodGenerator in MethodGenerators)
8870
{
@@ -108,6 +90,6 @@ private string GetFullyQualifiedTypeName(ClassDeclarationSyntax mapperClass, Typ
10890
if (typeInfo.Type == null)
10991
return typeSyntax.ToString();
11092

111-
return typeInfo.Type.ToDisplayString(FullyQualifiedWithNullables);
93+
return TypeNameResolver.GetFullyQualifiedTypeName(typeInfo.Type);
11294
}
11395
}

CSharpFunctionalExtensions.HttpResults.Generators/Builders/ResultExtensionsClassBuilder.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
namespace CSharpFunctionalExtensions.HttpResults.Generators.Builders;
66

77
public class ResultExtensionsClassBuilder(
8-
HashSet<string> requiredNamespaces,
98
List<ClassDeclarationSyntax> mapperClasses,
109
Compilation? compilation = null
11-
) : ClassBuilder(requiredNamespaces, mapperClasses, compilation)
10+
) : ClassBuilder(mapperClasses, compilation)
1211
{
1312
protected override string ClassName => "ResultExtensions";
1413

CSharpFunctionalExtensions.HttpResults.Generators/Builders/UnitResultExtensionsClassBuilder.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
namespace CSharpFunctionalExtensions.HttpResults.Generators.Builders;
66

77
public class UnitResultExtensionsClassBuilder(
8-
HashSet<string> requiredNamespaces,
98
List<ClassDeclarationSyntax> mapperClasses,
109
Compilation? compilation = null
11-
) : ClassBuilder(requiredNamespaces, mapperClasses, compilation)
10+
) : ClassBuilder(mapperClasses, compilation)
1211
{
1312
protected override string ClassName => "UnitResultExtensions";
1413

CSharpFunctionalExtensions.HttpResults.Generators/ResultExtensionsGenerator.cs

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Text;
22
using CSharpFunctionalExtensions.HttpResults.Generators.Builders;
3+
using CSharpFunctionalExtensions.HttpResults.Generators.Utils;
34
using Microsoft.CodeAnalysis;
45
using Microsoft.CodeAnalysis.CSharp.Syntax;
56
using Microsoft.CodeAnalysis.Text;
@@ -43,33 +44,28 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
4344
var (compilation, classDeclarations) = source;
4445

4546
var mapperClasses = new List<ClassDeclarationSyntax>();
46-
var requiredNamespaces = new HashSet<string>();
4747

4848
Parallel.ForEach(
4949
classDeclarations,
5050
classDeclaration =>
5151
{
52-
var semanticModel = compilation.GetSemanticModel(classDeclaration.SyntaxTree);
53-
var namespaceName = GetNamespace(classDeclaration, semanticModel);
54-
5552
lock (mapperClasses)
5653
{
5754
mapperClasses.Add(classDeclaration);
58-
requiredNamespaces.Add(namespaceName);
5955
}
6056
}
6157
);
6258

6359
if (!ResultExtensionsGeneratorValidator.CheckRules(mapperClasses, context))
6460
return;
6561

66-
var (fileName, sourceText) = CreateErrorMapperInstancesClass(mapperClasses, requiredNamespaces);
62+
var (fileName, sourceText) = CreateErrorMapperInstancesClass(mapperClasses, compilation);
6763
context.AddSource(fileName, SourceText.From(sourceText, Encoding.UTF8));
6864

6965
var classBuilders = new List<ClassBuilder>
7066
{
71-
new ResultExtensionsClassBuilder(requiredNamespaces, mapperClasses, compilation),
72-
new UnitResultExtensionsClassBuilder(requiredNamespaces, mapperClasses, compilation),
67+
new ResultExtensionsClassBuilder(mapperClasses, compilation),
68+
new UnitResultExtensionsClassBuilder(mapperClasses, compilation),
7369
};
7470

7571
foreach (var classBuilder in classBuilders)
@@ -83,7 +79,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
8379
/// </summary>
8480
private static (string FileName, string SourceText) CreateErrorMapperInstancesClass(
8581
List<ClassDeclarationSyntax> mapperClasses,
86-
HashSet<string> requiredNamespaces
82+
Compilation compilation
8783
)
8884
{
8985
var sourceBuilder = new StringBuilder();
@@ -92,20 +88,20 @@ HashSet<string> requiredNamespaces
9288
sourceBuilder.AppendLine();
9389
sourceBuilder.AppendLine("#nullable enable");
9490
sourceBuilder.AppendLine();
95-
requiredNamespaces
96-
.Where(@namespace => !@namespace.StartsWith("global"))
97-
.Distinct()
98-
.Select(@namespace => $"using {@namespace};")
99-
.ToList()
100-
.ForEach(@using => sourceBuilder.AppendLine(@using));
10191
sourceBuilder.AppendLine();
10292

10393
sourceBuilder.AppendLine("public static class ErrorMapperInstances {");
10494

105-
foreach (var mapperName in mapperClasses)
106-
sourceBuilder.AppendLine(
107-
$" public static {mapperName.Identifier.Text} {mapperName.Identifier.Text} {{ get; }} = new();"
108-
);
95+
foreach (var mapper in mapperClasses)
96+
{
97+
var semanticModel = compilation.GetSemanticModel(mapper.SyntaxTree);
98+
99+
if (semanticModel.GetDeclaredSymbol(mapper) is not ITypeSymbol mapperSymbol)
100+
continue;
101+
102+
var mapperType = TypeNameResolver.GetFullyQualifiedTypeName(mapperSymbol);
103+
sourceBuilder.AppendLine($" public static {mapperType} {mapper.Identifier.Text} {{ get; }} = new();");
104+
}
109105

110106
sourceBuilder.AppendLine("}");
111107

@@ -127,16 +123,4 @@ private static bool ImplementsResultErrorMapper(ITypeSymbol? classSymbol)
127123
interfaceSymbol.Name.StartsWith(ResultErrorMapperInterface)
128124
);
129125
}
130-
131-
/// <summary>
132-
/// Retrieves the namespace of a class declaration.
133-
/// </summary>
134-
/// <param name="classDeclaration">The class declaration syntax node.</param>
135-
/// <param name="semanticModel">The semantic model for the syntax tree.</param>
136-
/// <returns>The namespace of the class, or an empty string if the namespace cannot be determined.</returns>
137-
private static string GetNamespace(ClassDeclarationSyntax classDeclaration, SemanticModel semanticModel)
138-
{
139-
var symbol = semanticModel.GetDeclaredSymbol(classDeclaration);
140-
return symbol?.ContainingNamespace?.ToString() ?? string.Empty;
141-
}
142126
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Microsoft.CodeAnalysis;
2+
3+
namespace CSharpFunctionalExtensions.HttpResults.Generators.Utils;
4+
5+
internal static class TypeNameResolver
6+
{
7+
private static readonly SymbolDisplayFormat FullyQualifiedWithNullables =
8+
SymbolDisplayFormat.FullyQualifiedFormat.WithMiscellaneousOptions(
9+
SymbolDisplayFormat.FullyQualifiedFormat.MiscellaneousOptions
10+
| SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier
11+
);
12+
13+
public static string GetFullyQualifiedTypeName(ITypeSymbol typeSymbol)
14+
{
15+
return typeSymbol.ToDisplayString(FullyQualifiedWithNullables);
16+
}
17+
}

0 commit comments

Comments
 (0)