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()
{
@@ -14,6 +14,8 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface IPersonExtends
{
string StaticString { get; set; }
string Name { get; set; }
string? StringNullable { get; set; }
@@ -24,9 +26,9 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
bool IsAlive { get; set; }
bool X { get; set; }
string StaticMethod(int x, string y);
void Void();
@@ -13,10 +13,12 @@ using AutoMapper;
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public class PersonExtendsProxy : IPersonExtends
public partial class PersonExtendsProxy : IPersonExtends
{
public ProxyInterfaceSourceGeneratorTests.Source.PersonExtends _Instance { get; }
public string StaticString { get => ProxyInterfaceSourceGeneratorTests.Source.PersonExtends.StaticString; set => ProxyInterfaceSourceGeneratorTests.Source.PersonExtends.StaticString = value; }
public string Name { get => _Instance.Name; set => _Instance.Name = value; }
public string? StringNullable { get => _Instance.StringNullable; set => _Instance.StringNullable = value; }
@@ -27,9 +29,15 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
public bool IsAlive { get => _Instance.IsAlive; set => _Instance.IsAlive = value; }
public bool X { get => _Instance.X; set => _Instance.X = value; }
public string StaticMethod(int x, string y)
{
int x_ = x;
string y_ = y;
var result_6851397 = ProxyInterfaceSourceGeneratorTests.Source.PersonExtends.StaticMethod(x_, y_);
return result_6851397;
}
public void Void()
{
@@ -39,8 +47,8 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
public string HelloWorld(string name)
{
string name_ = name;
var result_58477331 = _Instance.HelloWorld(name_);
return result_58477331;
var result_6851397 = _Instance.HelloWorld(name_);
return result_6851397;
}
public void WithParams(params string[] values)
@@ -53,15 +61,15 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
{
string s_ = s;
string @string_ = @string;
var result_58477331 = _Instance.Add(s_, @string_);
return result_58477331;
var result_6851397 = _Instance.Add(s_, @string_);
return result_6851397;
}
public int DefaultValue(int x = 100)
{
int x_ = x;
var result_42930144 = _Instance.DefaultValue(x_);
return result_42930144;
var result_3873514 = _Instance.DefaultValue(x_);
return result_3873514;
}
public void In_Out_Ref1(in int a, out int b, ref int c)
@@ -78,26 +86,26 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
int x_ = x;
T1 t1_ = t1;
T2 t2_ = t2;
var result_38995950 = _Instance.Generic2<T1, T2>(x_, t1_, t2_);
return result_38995950;
var result_14331071 = _Instance.Generic2<T1, T2>(x_, t1_, t2_);
return result_14331071;
}
public System.Threading.Tasks.Task Method1Async()
{
var result_51708797 = _Instance.Method1Async();
return result_51708797;
var result_39535275 = _Instance.Method1Async();
return result_39535275;
}
public System.Threading.Tasks.Task<int> Method2Async()
{
var result_1620952573 = _Instance.Method2Async();
return result_1620952573;
var result_772784336 = _Instance.Method2Async();
return result_772784336;
}
public System.Threading.Tasks.Task<string?> Method3Async()
{
var result_1636499760 = _Instance.Method3Async();
return result_1636499760;
var result_769806453 = _Instance.Method3Async();
return result_769806453;
}
@@ -35,8 +35,8 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
public string HelloWorld(string name)
{
string name_ = name;
var result_56365455 = _Instance.HelloWorld(name_);
return result_56365455;
var result_37309470 = _Instance.HelloWorld(name_);
return result_37309470;
}
public void WithParams(params string[] values)
@@ -49,15 +49,15 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
{
string s_ = s;
string @string_ = @string;
var result_56365455 = _Instance.Add(s_, @string_);
return result_56365455;
var result_37309470 = _Instance.Add(s_, @string_);
return result_37309470;
}
public int DefaultValue(int x = 100)
{
int x_ = x;
var result_39875940 = _Instance.DefaultValue(x_);
return result_39875940;
var result_24216618 = _Instance.DefaultValue(x_);
return result_24216618;
}
public void In_Out_Ref1(in int a, out int b, ref int c)
@@ -74,26 +74,26 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
int x_ = x;
T1 t1_ = t1;
T2 t2_ = t2;
var result_41799290 = _Instance.Generic2<T1, T2>(x_, t1_, t2_);
return result_41799290;
var result_60333940 = _Instance.Generic2<T1, T2>(x_, t1_, t2_);
return result_60333940;
}
public System.Threading.Tasks.Task Method1Async()
{
var result_32599313 = _Instance.Method1Async();
return result_32599313;
var result_2292327 = _Instance.Method1Async();
return result_2292327;
}
public System.Threading.Tasks.Task<int> Method2Async()
{
var result_1620495907 = _Instance.Method2Async();
return result_1620495907;
var result_1229624901 = _Instance.Method2Async();
return result_1229624901;
}
public System.Threading.Tasks.Task<string?> Method3Async()
{
var result_1604006392 = _Instance.Method3Async();
return result_1604006392;
var result_1242717753 = _Instance.Method3Async();
return result_1242717753;
}
@@ -108,6 +108,7 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
}
public bool IsAlive { get; set; }
}
}
#nullable disable
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using AnyOfTypes;
@@ -6,6 +7,7 @@ using CSharp.SourceGenerators.Extensions.Models;
using FluentAssertions;
using ProxyInterfaceSourceGenerator;
using Xunit;
using Xunit.Sdk;
namespace ProxyInterfaceSourceGeneratorTests
{
@@ -109,6 +111,8 @@ namespace ProxyInterfaceSourceGeneratorTests
result.Valid.Should().BeTrue();
result.Files.Should().HaveCount(5);
throw new Exception();
// Assert attribute
var attribute = result.Files[0].SyntaxTree;
attribute.FilePath.Should().EndWith(attributeFilename);
@@ -1,12 +1,7 @@
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public class Human : Animal
public class Human
{
public bool IsAlive { get; set; }
}
public class Animal
{
public bool X { get; set; }
}
}
@@ -1,6 +1,6 @@
namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface IPerson
public partial interface IPerson : IHuman
{
}
}
@@ -4,6 +4,13 @@ namespace ProxyInterfaceSourceGeneratorTests.Source
{
public class PersonExtends : Human
{
public static string StaticMethod(int x, string y)
{
return "test";
}
public static string StaticString { get; set; } = "500";
public string Name { get; set; }
public string? StringNullable { get; set; }