Compare commits

...

4 Commits

  1. 1
      Debug.LightweightIocContainer.FactoryGenerator/SampleInstaller.cs
  2. 13
      Debug.LightweightIocContainer.FactoryGenerator/Samples/Factories/IGenericSampleFactory.cs
  3. 7
      Debug.LightweightIocContainer.FactoryGenerator/Samples/Interfaces/IOtherSample.cs
  4. 9
      Debug.LightweightIocContainer.FactoryGenerator/Samples/OtherSample.cs
  5. 56
      LightweightIocContainer.FactoryGenerator/FactoryGenerator.cs
  6. 2
      LightweightIocContainer.FactoryGenerator/LightweightIocContainer.FactoryGenerator.csproj
  7. 2
      LightweightIocContainer.Validation/LightweightIocContainer.Validation.csproj
  8. 2
      LightweightIocContainer/LightweightIocContainer.csproj

@ -16,5 +16,6 @@ public class SampleInstaller : IIocInstaller
public void Install(IRegistrationCollector registration) public void Install(IRegistrationCollector registration)
{ {
registration.Add<ISampleClass, SampleClass>().WithGeneratedFactory<ISampleClassFactory>(); registration.Add<ISampleClass, SampleClass>().WithGeneratedFactory<ISampleClassFactory>();
registration.Add<IOtherSample, OtherSample>().WithGeneratedFactory<IGenericSampleFactory<IOtherSample>>();
} }
} }

@ -0,0 +1,13 @@
// Author: Simon.Gockner
// Created: 2025-12-05
// Copyright(c) 2025 SimonG. All Rights Reserved.
using Debug.LightweightIocContainer.FactoryGenerator.Samples.Interfaces;
namespace Debug.LightweightIocContainer.FactoryGenerator.Samples.Factories;
public interface IGenericSampleFactory<T> where T : IOtherSample
{
T Create();
IOtherSample Create<U>(T parameter, U parameter2) where U : T;
}

@ -0,0 +1,7 @@
// Author: Simon.Gockner
// Created: 2025-12-05
// Copyright(c) 2025 SimonG. All Rights Reserved.
namespace Debug.LightweightIocContainer.FactoryGenerator.Samples.Interfaces;
public interface IOtherSample;

@ -0,0 +1,9 @@
// Author: Simon.Gockner
// Created: 2025-12-05
// Copyright(c) 2025 SimonG. All Rights Reserved.
using Debug.LightweightIocContainer.FactoryGenerator.Samples.Interfaces;
namespace Debug.LightweightIocContainer.FactoryGenerator.Samples;
public class OtherSample : IOtherSample;

@ -73,7 +73,7 @@ public class FactoryGenerator : IIncrementalGenerator
if (!genericNameSyntax.ToString().StartsWith("WithGeneratedFactory")) if (!genericNameSyntax.ToString().StartsWith("WithGeneratedFactory"))
return false; return false;
if (genericNameSyntax.TypeArgumentList.Arguments[0] is not IdentifierNameSyntax) if (genericNameSyntax.TypeArgumentList.Arguments[0] is not (IdentifierNameSyntax or GenericNameSyntax))
return false; return false;
return true; return true;
@ -84,10 +84,10 @@ public class FactoryGenerator : IIncrementalGenerator
if (syntaxContext.Node is not GenericNameSyntax genericNameSyntax) if (syntaxContext.Node is not GenericNameSyntax genericNameSyntax)
return null; return null;
if (genericNameSyntax.TypeArgumentList.Arguments[0] is not IdentifierNameSyntax identifierNameSyntax) if (genericNameSyntax.TypeArgumentList.Arguments[0] is not SimpleNameSyntax nameSyntax)
return null; return null;
if (syntaxContext.SemanticModel.GetSymbolInfo(identifierNameSyntax).Symbol is not ITypeSymbol typeSymbol) if (syntaxContext.SemanticModel.GetSymbolInfo(nameSyntax).Symbol is not ITypeSymbol typeSymbol)
return null; return null;
return typeSymbol; return typeSymbol;
@ -140,9 +140,9 @@ public class FactoryGenerator : IIncrementalGenerator
if (symbol is not ITypeSymbol type) 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({GetTypeText(type, false)}))");
stringBuilder.AppendLine($"{INDENT}{INDENT}{{"); stringBuilder.AppendLine($"{INDENT}{INDENT}{{");
stringBuilder.AppendLine($"{INDENT}{INDENT}{INDENT}return (TFactory) (object) new Generated{type.Name}(container);"); stringBuilder.AppendLine($"{INDENT}{INDENT}{INDENT}return (TFactory) (object) new Generated{GetTypeText(type, false)}(container);");
stringBuilder.AppendLine($"{INDENT}{INDENT}}}"); stringBuilder.AppendLine($"{INDENT}{INDENT}}}");
stringBuilder.AppendLine(); stringBuilder.AppendLine();
} }
@ -157,7 +157,6 @@ public class FactoryGenerator : IIncrementalGenerator
private string GenerateFactorySourceCode(ITypeSymbol typeSymbol) private string GenerateFactorySourceCode(ITypeSymbol typeSymbol)
{ {
string typeName = typeSymbol.Name;
string? typeNamespace = typeSymbol.ContainingNamespace.IsGlobalNamespace ? null : typeSymbol.ContainingNamespace.ToString(); string? typeNamespace = typeSymbol.ContainingNamespace.IsGlobalNamespace ? null : typeSymbol.ContainingNamespace.ToString();
StringBuilder stringBuilder = new(); StringBuilder stringBuilder = new();
@ -195,7 +194,12 @@ public class FactoryGenerator : IIncrementalGenerator
stringBuilder.AppendLine(); stringBuilder.AppendLine();
} }
stringBuilder.AppendLine($"public class Generated{typeName}(IocContainer container) : {typeName}"); stringBuilder.Append($"public class Generated{GetGenericTypeText(typeSymbol)}(IocContainer container) : {GetGenericTypeText(typeSymbol)}");
if (typeSymbol is INamedTypeSymbol { IsGenericType: true } genericTypeSymbol)
stringBuilder.Append(GetParameterConstraintsText(genericTypeSymbol));
stringBuilder.AppendLine();
stringBuilder.AppendLine("{"); stringBuilder.AppendLine("{");
foreach (ISymbol? member in members) foreach (ISymbol? member in members)
@ -205,20 +209,20 @@ public class FactoryGenerator : IIncrementalGenerator
if (!method.ReturnsVoid) //create method if (!method.ReturnsVoid) //create method
{ {
stringBuilder.Append($"{INDENT}public {GetTypeText(method.ReturnType)} {method.Name}"); stringBuilder.Append($"{INDENT}public {GetTypeText(method.OriginalDefinition.ReturnType)} {method.Name}");
if (method.IsGenericMethod) if (method.IsGenericMethod)
stringBuilder.Append(GetGenericParameters(method)); stringBuilder.Append(GetGenericParameters(method.OriginalDefinition));
stringBuilder.Append($"({string.Join(", ", method.Parameters.Select(GetParameterText))})"); stringBuilder.Append($"({string.Join(", ", method.OriginalDefinition.Parameters.Select(GetParameterText))})");
if (method.IsGenericMethod) if (method.IsGenericMethod)
stringBuilder.Append(GetParameterConstraintsText(method)); stringBuilder.Append(GetParameterConstraintsText(method.OriginalDefinition));
stringBuilder.AppendLine(); stringBuilder.AppendLine();
stringBuilder.AppendLine($"{INDENT}{{"); stringBuilder.AppendLine($"{INDENT}{{");
foreach (IParameterSymbol parameter in method.Parameters) foreach (IParameterSymbol parameter in method.OriginalDefinition.Parameters)
{ {
stringBuilder.AppendLine($"{INDENT}{INDENT}object? {parameter.Name}Value = {parameter.Name};"); stringBuilder.AppendLine($"{INDENT}{INDENT}object? {parameter.Name}Value = {parameter.Name};");
stringBuilder.AppendLine($"{INDENT}{INDENT}if ({parameter.Name}Value is null)"); stringBuilder.AppendLine($"{INDENT}{INDENT}if ({parameter.Name}Value is null)");
@ -227,17 +231,17 @@ public class FactoryGenerator : IIncrementalGenerator
} }
//don't use getTypeText here, because we need the raw type name for Task<> //don't use getTypeText here, because we need the raw type name for Task<>
if (method.ReturnType is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol) if (method.OriginalDefinition.ReturnType is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol)
{ {
if (method.ReturnType.Name == "Task") if (method.OriginalDefinition.ReturnType.Name == "Task")
stringBuilder.Append($"{INDENT}{INDENT}return container.FactoryResolveAsync{GetGenericArguments(namedTypeSymbol)}("); stringBuilder.Append($"{INDENT}{INDENT}return container.FactoryResolveAsync{GetGenericArguments(namedTypeSymbol)}(");
else else
stringBuilder.Append($"{INDENT}{INDENT}return container.FactoryResolve<{method.ReturnType.Name}{GetGenericArguments(namedTypeSymbol)}>("); stringBuilder.Append($"{INDENT}{INDENT}return container.FactoryResolve<{method.OriginalDefinition.ReturnType.Name}{GetGenericArguments(namedTypeSymbol)}>(");
} }
else else
stringBuilder.Append($"{INDENT}{INDENT}return container.FactoryResolve<{method.ReturnType.Name}>("); stringBuilder.Append($"{INDENT}{INDENT}return container.FactoryResolve<{method.OriginalDefinition.ReturnType.Name}>(");
stringBuilder.Append(string.Join(", ", method.Parameters.Select(p => $"{p.Name}Value"))); stringBuilder.Append(string.Join(", ", method.OriginalDefinition.Parameters.Select(p => $"{p.Name}Value")));
stringBuilder.AppendLine(");"); stringBuilder.AppendLine(");");
stringBuilder.AppendLine($"{INDENT}}}"); stringBuilder.AppendLine($"{INDENT}}}");
@ -297,19 +301,33 @@ public class FactoryGenerator : IIncrementalGenerator
return stringBuilder.ToString(); return stringBuilder.ToString();
} }
private string GetGenericTypeText(ITypeSymbol typeSymbol)
{
StringBuilder stringBuilder = new();
stringBuilder.Append(typeSymbol.Name);
if (typeSymbol is INamedTypeSymbol { IsGenericType: true } namedTypeSymbol)
stringBuilder.Append(GetGenericParameters(namedTypeSymbol));
return stringBuilder.ToString();
}
private string GetParameterText(IParameterSymbol parameter) => $"{GetTypeText(parameter.Type)} {parameter.Name}"; private string GetParameterText(IParameterSymbol parameter) => $"{GetTypeText(parameter.Type)} {parameter.Name}";
private string GetGenericArguments(INamedTypeSymbol namedTypeSymbol) => GetGenericArguments(namedTypeSymbol.TypeArguments); private string GetGenericArguments(INamedTypeSymbol namedTypeSymbol) => GetGenericArguments(namedTypeSymbol.TypeArguments);
private string GetGenericArguments(IMethodSymbol methodSymbol) => GetGenericArguments(methodSymbol.TypeArguments); private string GetGenericArguments(IMethodSymbol methodSymbol) => GetGenericArguments(methodSymbol.TypeArguments);
private string GetGenericArguments(ImmutableArray<ITypeSymbol> typeArguments) => $"<{string.Join(", ", typeArguments.Select(GetTypeText))}>"; private string GetGenericArguments(ImmutableArray<ITypeSymbol> typeArguments) => $"<{string.Join(", ", typeArguments.Select(GetTypeText))}>";
private string GetGenericParameters(INamedTypeSymbol namedTypeSymbol) => GetGenericParameters(namedTypeSymbol.TypeParameters);
private string GetGenericParameters(IMethodSymbol methodSymbol) => GetGenericParameters(methodSymbol.TypeParameters); private string GetGenericParameters(IMethodSymbol methodSymbol) => GetGenericParameters(methodSymbol.TypeParameters);
private string GetGenericParameters(ImmutableArray<ITypeParameterSymbol> typeParameters) => $"<{string.Join(", ", typeParameters.Select(GetTypeText))}>"; private string GetGenericParameters(ImmutableArray<ITypeParameterSymbol> typeParameters) => $"<{string.Join(", ", typeParameters.Select(GetTypeText))}>";
private string GetParameterConstraintsText(IMethodSymbol method) private string GetParameterConstraintsText(INamedTypeSymbol namedTypeSymbol) => GetParameterConstraintsText(namedTypeSymbol.TypeParameters);
private string GetParameterConstraintsText(IMethodSymbol method) => GetParameterConstraintsText(method.TypeParameters);
private string GetParameterConstraintsText(ImmutableArray<ITypeParameterSymbol> typeParameters)
{ {
StringBuilder stringBuilder = new(); StringBuilder stringBuilder = new();
foreach (ITypeParameterSymbol typeParameter in method.TypeParameters) foreach (ITypeParameterSymbol typeParameter in typeParameters)
{ {
List<string> parameterConstraints = GetParameterConstraints(typeParameter); List<string> parameterConstraints = GetParameterConstraints(typeParameter);
if (parameterConstraints.Count == 0) if (parameterConstraints.Count == 0)

@ -12,7 +12,7 @@
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent> <IsRoslynComponent>true</IsRoslynComponent>
<VersionPrefix>5.0.0</VersionPrefix> <VersionPrefix>5.0.0</VersionPrefix>
<VersionSuffix>beta2</VersionSuffix> <VersionSuffix>beta3</VersionSuffix>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

@ -11,7 +11,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<DocumentationFile>LightweightIocContainer.Validation.xml</DocumentationFile> <DocumentationFile>LightweightIocContainer.Validation.xml</DocumentationFile>
<VersionPrefix>5.0.0</VersionPrefix> <VersionPrefix>5.0.0</VersionPrefix>
<VersionSuffix>beta2</VersionSuffix> <VersionSuffix>beta3</VersionSuffix>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

@ -11,7 +11,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<DocumentationFile>LightweightIocContainer.xml</DocumentationFile> <DocumentationFile>LightweightIocContainer.xml</DocumentationFile>
<VersionPrefix>5.0.0</VersionPrefix> <VersionPrefix>5.0.0</VersionPrefix>
<VersionSuffix>beta2</VersionSuffix> <VersionSuffix>beta3</VersionSuffix>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

Loading…
Cancel
Save