|
|
|
@ -29,7 +29,7 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
IncrementalValuesProvider<ITypeSymbol?> syntaxProvider = context.SyntaxProvider.CreateSyntaxProvider(IsCallToGenerateFactory, GetTypeArgument); |
|
|
|
IncrementalValuesProvider<ITypeSymbol?> syntaxProvider = context.SyntaxProvider.CreateSyntaxProvider(IsCallToGenerateFactory, GetTypeArgument); |
|
|
|
|
|
|
|
|
|
|
|
context.RegisterSourceOutput(syntaxProvider.Collect(), GenerateTypeDependentClasses); |
|
|
|
context.RegisterSourceOutput(syntaxProvider.Collect(), GenerateTypeDependentClasses); |
|
|
|
context.RegisterSourceOutput(syntaxProvider, GenerateFactory); |
|
|
|
context.RegisterSourceOutput(syntaxProvider.Collect(), GenerateFactory); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private string GenerateFactoryExtensionsClass(string? classNamespace, string className) |
|
|
|
private string GenerateFactoryExtensionsClass(string? classNamespace, string className) |
|
|
|
@ -99,13 +99,16 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
context.AddSource($"{BUILDER_CLASS_NAME}.g.cs", GenerateBuilderClassSourceCode(classNamespace, types)); |
|
|
|
context.AddSource($"{BUILDER_CLASS_NAME}.g.cs", GenerateBuilderClassSourceCode(classNamespace, types)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void GenerateFactory(SourceProductionContext context, ITypeSymbol? typeSymbol) |
|
|
|
private void GenerateFactory(SourceProductionContext context, ImmutableArray<ITypeSymbol?> types) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (typeSymbol is null) |
|
|
|
foreach (ISymbol? symbol in types.Distinct(SymbolEqualityComparer.IncludeNullability)) |
|
|
|
return; |
|
|
|
{ |
|
|
|
|
|
|
|
if (symbol is not ITypeSymbol typeSymbol) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
context.AddSource($"Generated{typeSymbol.Name}.g.cs", GenerateFactorySourceCode(typeSymbol)); |
|
|
|
context.AddSource($"Generated{typeSymbol.Name}.g.cs", GenerateFactorySourceCode(typeSymbol)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private string GenerateBuilderClassSourceCode(string? classNamespace, ImmutableArray<ITypeSymbol?> types) |
|
|
|
private string GenerateBuilderClassSourceCode(string? classNamespace, ImmutableArray<ITypeSymbol?> types) |
|
|
|
{ |
|
|
|
{ |
|
|
|
@ -132,9 +135,9 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
stringBuilder.AppendLine($"{INDENT}public TFactory Create<TFactory>(IocContainer container)"); |
|
|
|
stringBuilder.AppendLine($"{INDENT}public TFactory Create<TFactory>(IocContainer container)"); |
|
|
|
stringBuilder.AppendLine($"{INDENT}{{"); |
|
|
|
stringBuilder.AppendLine($"{INDENT}{{"); |
|
|
|
|
|
|
|
|
|
|
|
foreach (ITypeSymbol? type in types) |
|
|
|
foreach (ISymbol? symbol in types.Distinct(SymbolEqualityComparer.IncludeNullability)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (type is null) |
|
|
|
if (symbol is not ITypeSymbol type) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
stringBuilder.AppendLine($"{INDENT}{INDENT}if (typeof(TFactory) == typeof({type.Name}))"); |
|
|
|
stringBuilder.AppendLine($"{INDENT}{INDENT}if (typeof(TFactory) == typeof({type.Name}))"); |
|
|
|
@ -166,6 +169,34 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
stringBuilder.AppendLine(); |
|
|
|
stringBuilder.AppendLine(); |
|
|
|
|
|
|
|
|
|
|
|
stringBuilder.AppendLine("using LightweightIocContainer;"); |
|
|
|
stringBuilder.AppendLine("using LightweightIocContainer;"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ImmutableArray<ISymbol> members = typeSymbol.GetMembers(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<string?> namespaces = []; |
|
|
|
|
|
|
|
foreach (ISymbol? member in members) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (member is not IMethodSymbol method) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!method.ReturnsVoid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (method.ReturnType is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
namespaces.AddRange(namedTypeSymbol.TypeArguments.Select(GetNamespaceOfType)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (method.ReturnType.Name != "Task") |
|
|
|
|
|
|
|
namespaces.Add(GetNamespaceOfType(method.ReturnType)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
namespaces.Add(GetNamespaceOfType(method.ReturnType)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespaces.AddRange(method.Parameters.Select(p => GetNamespaceOfType(p.Type))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (string @namespace in namespaces.Distinct().OfType<string>().OrderBy(n => n)) |
|
|
|
|
|
|
|
stringBuilder.AppendLine($"using {@namespace};"); |
|
|
|
|
|
|
|
|
|
|
|
stringBuilder.AppendLine(); |
|
|
|
stringBuilder.AppendLine(); |
|
|
|
|
|
|
|
|
|
|
|
if (typeNamespace is not null) |
|
|
|
if (typeNamespace is not null) |
|
|
|
@ -177,7 +208,6 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
stringBuilder.AppendLine($"public class Generated{typeName}(IocContainer container) : {typeName}"); |
|
|
|
stringBuilder.AppendLine($"public class Generated{typeName}(IocContainer container) : {typeName}"); |
|
|
|
stringBuilder.AppendLine("{"); |
|
|
|
stringBuilder.AppendLine("{"); |
|
|
|
|
|
|
|
|
|
|
|
ImmutableArray<ISymbol> members = typeSymbol.GetMembers(); |
|
|
|
|
|
|
|
foreach (ISymbol? member in members) |
|
|
|
foreach (ISymbol? member in members) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (member is not IMethodSymbol method) |
|
|
|
if (member is not IMethodSymbol method) |
|
|
|
@ -187,11 +217,8 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
{ |
|
|
|
{ |
|
|
|
stringBuilder.Append($"{INDENT}public {method.ReturnType.Name}"); |
|
|
|
stringBuilder.Append($"{INDENT}public {method.ReturnType.Name}"); |
|
|
|
|
|
|
|
|
|
|
|
if (method.ReturnType.Name == "Task") |
|
|
|
if (method.ReturnType is INamedTypeSymbol { IsGenericType: true } namedReturnType) |
|
|
|
{ |
|
|
|
stringBuilder.Append(GetGenericArguments(namedReturnType)); |
|
|
|
if (method.ReturnType is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol) |
|
|
|
|
|
|
|
stringBuilder.Append($"<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(a => a.Name))}>"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stringBuilder.Append($" {method.Name}"); |
|
|
|
stringBuilder.Append($" {method.Name}"); |
|
|
|
|
|
|
|
|
|
|
|
@ -223,17 +250,15 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
stringBuilder.AppendLine(); |
|
|
|
stringBuilder.AppendLine(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (method.ReturnType.Name == "Task") |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
stringBuilder.Append($"{INDENT}{INDENT}return container.ResolveAsync"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (method.ReturnType is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol) |
|
|
|
if (method.ReturnType is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol) |
|
|
|
stringBuilder.Append($"<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(a => a.Name))}>"); |
|
|
|
{ |
|
|
|
|
|
|
|
if (method.ReturnType.Name == "Task") |
|
|
|
stringBuilder.Append("("); |
|
|
|
stringBuilder.Append($"{INDENT}{INDENT}return container.FactoryResolveAsync{GetGenericArguments(namedTypeSymbol)}("); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
stringBuilder.Append($"{INDENT}{INDENT}return container.FactoryResolve<{method.ReturnType.Name}{GetGenericArguments(namedTypeSymbol)}>("); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
stringBuilder.Append($"{INDENT}{INDENT}return container.Resolve<{method.ReturnType.Name}>("); |
|
|
|
stringBuilder.Append($"{INDENT}{INDENT}return container.FactoryResolve<{method.ReturnType.Name}>("); |
|
|
|
|
|
|
|
|
|
|
|
stringBuilder.Append(string.Join(", ", method.Parameters.Select(p => $"{p.Name}Value"))); |
|
|
|
stringBuilder.Append(string.Join(", ", method.Parameters.Select(p => $"{p.Name}Value"))); |
|
|
|
stringBuilder.AppendLine(");"); |
|
|
|
stringBuilder.AppendLine(");"); |
|
|
|
@ -265,9 +290,10 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
return stringBuilder.ToString(); |
|
|
|
return stringBuilder.ToString(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private string? GetNamespaceOfType(ITypeSymbol s) => s.ContainingNamespace.IsGlobalNamespace ? null : s.ContainingNamespace.ToString(); |
|
|
|
private IEnumerable<string> GetNamespacesOfTypes(ImmutableArray<ITypeSymbol?> types) => |
|
|
|
private IEnumerable<string> GetNamespacesOfTypes(ImmutableArray<ITypeSymbol?> types) => |
|
|
|
types.OfType<ITypeSymbol>() |
|
|
|
types.OfType<ITypeSymbol>() |
|
|
|
.Select(s => s.ContainingNamespace.IsGlobalNamespace ? null : s.ContainingNamespace.ToString()) |
|
|
|
.Select(GetNamespaceOfType) |
|
|
|
.OfType<string>() |
|
|
|
.OfType<string>() |
|
|
|
.Distinct(); |
|
|
|
.Distinct(); |
|
|
|
|
|
|
|
|
|
|
|
@ -276,6 +302,9 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
StringBuilder stringBuilder = new(); |
|
|
|
StringBuilder stringBuilder = new(); |
|
|
|
stringBuilder.Append(parameter.Type.Name); |
|
|
|
stringBuilder.Append(parameter.Type.Name); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (parameter.Type is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol) |
|
|
|
|
|
|
|
stringBuilder.Append(GetGenericArguments(namedTypeSymbol)); |
|
|
|
|
|
|
|
|
|
|
|
if (parameter.NullableAnnotation == NullableAnnotation.Annotated) |
|
|
|
if (parameter.NullableAnnotation == NullableAnnotation.Annotated) |
|
|
|
stringBuilder.Append("?"); |
|
|
|
stringBuilder.Append("?"); |
|
|
|
|
|
|
|
|
|
|
|
@ -283,13 +312,24 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
return stringBuilder.ToString(); |
|
|
|
return stringBuilder.ToString(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private List<string> GetParameterConstraints(ITypeParameterSymbol typeParameterSymbol) |
|
|
|
private string GetGenericArguments(INamedTypeSymbol namedTypeSymbol) => $"<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(GetGenericArgument))}>"; |
|
|
|
|
|
|
|
private string GetGenericArgument(ITypeSymbol argument) |
|
|
|
{ |
|
|
|
{ |
|
|
|
List<string> constraints = []; |
|
|
|
StringBuilder stringBuilder = new(); |
|
|
|
|
|
|
|
stringBuilder.Append(argument.Name); |
|
|
|
|
|
|
|
|
|
|
|
foreach (ITypeSymbol constraintType in typeParameterSymbol.ConstraintTypes) |
|
|
|
if (argument is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol) |
|
|
|
constraints.Add(constraintType.Name); |
|
|
|
stringBuilder.Append(GetGenericArguments(namedTypeSymbol)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (argument.NullableAnnotation == NullableAnnotation.Annotated) |
|
|
|
|
|
|
|
stringBuilder.Append("?"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return stringBuilder.ToString(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<string> GetParameterConstraints(ITypeParameterSymbol typeParameterSymbol) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
List<string> constraints = []; |
|
|
|
if (typeParameterSymbol.HasReferenceTypeConstraint) |
|
|
|
if (typeParameterSymbol.HasReferenceTypeConstraint) |
|
|
|
constraints.Add("class"); |
|
|
|
constraints.Add("class"); |
|
|
|
|
|
|
|
|
|
|
|
@ -305,6 +345,14 @@ public class FactoryGenerator : IIncrementalGenerator |
|
|
|
if (typeParameterSymbol.HasNotNullConstraint) |
|
|
|
if (typeParameterSymbol.HasNotNullConstraint) |
|
|
|
constraints.Add("notnull"); |
|
|
|
constraints.Add("notnull"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (ITypeSymbol constraintType in typeParameterSymbol.ConstraintTypes) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (constraintType is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol) |
|
|
|
|
|
|
|
constraints.Add($"{constraintType.Name}{GetGenericArguments(namedTypeSymbol)}"); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
constraints.Add(constraintType.Name); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return constraints; |
|
|
|
return constraints; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |