Add support for static properties and methods (#28)

* x

* Add support for static properties and methods.
This commit is contained in:
Stef Heyenrath
2022-02-02 09:01:51 +01:00
committed by GitHub
parent 76d8a2d5a5
commit 307bc1a015
11 changed files with 87 additions and 54 deletions
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using ProxyInterfaceSourceGenerator.Enums;
using ProxyInterfaceSourceGenerator.Model;
namespace ProxyInterfaceSourceGenerator.Extensions;
@@ -18,18 +19,26 @@ internal static class PropertySymbolExtensions
return $"{type} {property.GetSanitizedName()} {{ {get}{set}}}";
}
public static string ToPropertyTextForClass(this IPropertySymbol property)
public static string ToPropertyTextForClass(this IPropertySymbol property, ClassSymbol targetClassSymbol)
{
var get = property.GetMethod != null ? $"get => _Instance.{property.GetSanitizedName()}; " : string.Empty;
var set = property.SetMethod != null ? $"set => _Instance.{property.GetSanitizedName()} = value; " : string.Empty;
string instance = !property.IsStatic ?
"_Instance" :
$"{targetClassSymbol.Symbol}";
var get = property.GetMethod != null ? $"get => {instance}.{property.GetSanitizedName()}; " : string.Empty;
var set = property.SetMethod != null ? $"set => {instance}.{property.GetSanitizedName()} = value; " : string.Empty;
return $"{property.Type} {property.GetSanitizedName()} {{ {get}{set}}}";
}
public static string ToPropertyTextForClass(this IPropertySymbol property, string overrideType)
public static string ToPropertyTextForClass(this IPropertySymbol property, ClassSymbol targetClassSymbol, string overrideType)
{
var get = property.GetMethod != null ? $"get => _mapper.Map<{overrideType}>(_Instance.{property.GetSanitizedName()}); " : string.Empty;
var set = property.SetMethod != null ? $"set => _Instance.{property.GetSanitizedName()} = _mapper.Map<{property.Type}>(value); " : string.Empty;
string instance = !property.IsStatic ?
"_Instance" :
$"{targetClassSymbol.Symbol}";
var get = property.GetMethod != null ? $"get => _mapper.Map<{overrideType}>({instance}.{property.GetSanitizedName()}); " : string.Empty;
var set = property.SetMethod != null ? $"set => {instance}.{property.GetSanitizedName()} = _mapper.Map<{property.Type}>(value); " : string.Empty;
return $"{overrideType} {property.GetSanitizedName()} {{ {get}{set}}}";
}
@@ -75,7 +75,7 @@ internal abstract class BaseGenerator
var symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName(name);
if (symbol is not null)
{
return new ClassSymbol(symbol, symbol.GetBaseTypes());
return new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
}
if (usings is not null)
@@ -85,7 +85,7 @@ internal abstract class BaseGenerator
symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName($"{@using}.{name}");
if (symbol is not null)
{
return new ClassSymbol(symbol, symbol.GetBaseTypes());
return new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
}
}
}
@@ -1,5 +1,6 @@
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using ProxyInterfaceSourceGenerator.Enums;
using ProxyInterfaceSourceGenerator.Extensions;
using ProxyInterfaceSourceGenerator.Model;
@@ -18,11 +19,11 @@ internal class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
{
foreach (var ci in Context.CandidateInterfaces)
{
yield return GenerateFile(ci.Value);
yield return GenerateFile(ci.Value, Context.CandidateInterfaces);
}
}
private FileData GenerateFile(ProxyData pd)
private FileData GenerateFile(ProxyData pd, IDictionary<InterfaceDeclarationSyntax, ProxyData> candidateInterfaces)
{
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName, pd.Usings);
var interfaceName = targetClassSymbol.Symbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.InterfaceName);
@@ -58,7 +59,7 @@ using AutoMapper;
namespace {ns}
{{
public class {className} : {interfaceName}
public partial class {className} : {interfaceName}
{{
public {targetClassSymbol.Symbol} _Instance {{ get; }}
@@ -79,6 +80,7 @@ namespace {ns}
}}
}}
{(SupportsNullable ? "#nullable disable" : string.Empty)}";
private string GeneratePrivateAutoMapper()
{
return Context.ReplacedTypes.Count == 0 ? string.Empty : " private readonly IMapper _mapper;";
@@ -114,11 +116,11 @@ namespace {ns}
var type = GetPropertyType(property, out var isReplaced);
if (isReplaced)
{
str.AppendLine($" public {property.ToPropertyTextForClass(type)}");
str.AppendLine($" public {property.ToPropertyTextForClass(targetClassSymbol, type)}");
}
else
{
str.AppendLine($" public {property.ToPropertyTextForClass()}");
str.AppendLine($" public {property.ToPropertyTextForClass(targetClassSymbol)}");
}
str.AppendLine();
}
@@ -168,15 +170,20 @@ namespace {ns}
#pragma warning disable RS1024 // Compare symbols correctly
int hash = method.ReturnType.GetHashCode();
#pragma warning restore RS1024 // Compare symbols correctly
var alternateReturnVariableName = $"result_{Math.Abs(hash)}";
string instance = !method.IsStatic ?
"_Instance" :
$"{targetClassSymbol.Symbol}";
if (returnTypeAsString == "void")
{
str.AppendLine($" _Instance.{method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", invokeParameters)});");
str.AppendLine($" {instance}.{method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", invokeParameters)});");
}
else
{
str.AppendLine($" var {alternateReturnVariableName} = _Instance.{method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", invokeParameters)});");
str.AppendLine($" var {alternateReturnVariableName} = {instance}.{method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", invokeParameters)});");
}
foreach (var ps in method.Parameters.Where(p => p.RefKind == RefKind.Out))
@@ -2,7 +2,7 @@ using Microsoft.CodeAnalysis;
namespace ProxyInterfaceSourceGenerator.Model;
internal record ClassSymbol(INamedTypeSymbol Symbol, List<INamedTypeSymbol> BaseTypes)
internal record ClassSymbol(INamedTypeSymbol Symbol, List<INamedTypeSymbol> BaseTypes, List<INamedTypeSymbol> Interfaces)
{
public override string ToString()
{