ProxyBaseClasses (#27)
This commit is contained in:
@@ -1,97 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using ProxyInterfaceSourceGenerator.Extensions;
|
||||
using ProxyInterfaceSourceGenerator.Model;
|
||||
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators;
|
||||
|
||||
internal abstract class BaseGenerator
|
||||
{
|
||||
internal abstract class BaseGenerator
|
||||
protected readonly Context Context;
|
||||
protected readonly bool SupportsNullable;
|
||||
|
||||
protected BaseGenerator(Context context, bool supportsNullable)
|
||||
{
|
||||
protected readonly Context _context;
|
||||
protected readonly bool _supportsNullable;
|
||||
Context = context;
|
||||
SupportsNullable = supportsNullable;
|
||||
}
|
||||
|
||||
public BaseGenerator(Context context, bool supportsNullable)
|
||||
protected string GetPropertyType(IPropertySymbol property, out bool isReplaced)
|
||||
{
|
||||
return GetReplacedType(property.Type, out isReplaced);
|
||||
}
|
||||
|
||||
protected string GetParameterType(IParameterSymbol property, out bool isReplaced)
|
||||
{
|
||||
return GetReplacedType(property.Type, out isReplaced);
|
||||
}
|
||||
|
||||
protected string GetReplacedType(ITypeSymbol typeSymbol, out bool isReplaced)
|
||||
{
|
||||
isReplaced = false;
|
||||
|
||||
var typeSymbolAsString = typeSymbol.ToString();
|
||||
|
||||
var existing = Context.CandidateInterfaces.Values.FirstOrDefault(x => x.RawTypeName == typeSymbolAsString);
|
||||
if (existing is not null)
|
||||
{
|
||||
_context = context;
|
||||
_supportsNullable = supportsNullable;
|
||||
}
|
||||
|
||||
protected string GetPropertyType(IPropertySymbol property, out bool isReplaced)
|
||||
{
|
||||
return GetReplacedType(property.Type, out isReplaced);
|
||||
}
|
||||
|
||||
protected string GetParameterType(IParameterSymbol property, out bool isReplaced)
|
||||
{
|
||||
return GetReplacedType(property.Type, out isReplaced);
|
||||
}
|
||||
|
||||
protected string GetReplacedType(ITypeSymbol typeSymbol, out bool isReplaced)
|
||||
{
|
||||
isReplaced = false;
|
||||
|
||||
var typeSymbolAsString = typeSymbol.ToString();
|
||||
|
||||
var existing = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.RawTypeName == typeSymbolAsString);
|
||||
if (existing is not null)
|
||||
if (!Context.ReplacedTypes.ContainsKey(typeSymbolAsString))
|
||||
{
|
||||
if (!_context.ReplacedTypes.ContainsKey(typeSymbolAsString))
|
||||
{
|
||||
_context.ReplacedTypes.Add(typeSymbolAsString, existing.InterfaceName);
|
||||
}
|
||||
|
||||
isReplaced = true;
|
||||
return existing.InterfaceName;
|
||||
Context.ReplacedTypes.Add(typeSymbolAsString, existing.InterfaceName);
|
||||
}
|
||||
|
||||
if (typeSymbol is INamedTypeSymbol namedTypedSymbol)
|
||||
isReplaced = true;
|
||||
return existing.InterfaceName;
|
||||
}
|
||||
|
||||
if (typeSymbol is INamedTypeSymbol namedTypedSymbol)
|
||||
{
|
||||
var propertyTypeAsStringToBeModified = typeSymbolAsString;
|
||||
foreach (var typeArgument in namedTypedSymbol.TypeArguments)
|
||||
{
|
||||
var propertyTypeAsStringToBeModified = typeSymbolAsString;
|
||||
foreach (var typeArgument in namedTypedSymbol.TypeArguments)
|
||||
var typeArgumentAsString = typeArgument.ToString();
|
||||
var exist = Context.CandidateInterfaces.Values.FirstOrDefault(x => x.RawTypeName == typeArgumentAsString);
|
||||
if (exist is not null)
|
||||
{
|
||||
var typeArgumentAsString = typeArgument.ToString();
|
||||
var exist = _context.CandidateInterfaces.Values.FirstOrDefault(x => x.RawTypeName == typeArgumentAsString);
|
||||
if (exist is not null)
|
||||
isReplaced = true;
|
||||
|
||||
if (!Context.ReplacedTypes.ContainsKey(typeArgumentAsString))
|
||||
{
|
||||
isReplaced = true;
|
||||
|
||||
if (!_context.ReplacedTypes.ContainsKey(typeArgumentAsString))
|
||||
{
|
||||
_context.ReplacedTypes.Add(typeArgumentAsString, exist.InterfaceName);
|
||||
}
|
||||
|
||||
propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, exist.InterfaceName);
|
||||
Context.ReplacedTypes.Add(typeArgumentAsString, exist.InterfaceName);
|
||||
}
|
||||
}
|
||||
|
||||
return propertyTypeAsStringToBeModified;
|
||||
propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, exist.InterfaceName);
|
||||
}
|
||||
}
|
||||
|
||||
return typeSymbolAsString;
|
||||
return propertyTypeAsStringToBeModified;
|
||||
}
|
||||
|
||||
protected INamedTypeSymbol GetNamedTypeSymbolByFullName(string name, IEnumerable<string>? usings = null)
|
||||
return typeSymbolAsString;
|
||||
}
|
||||
|
||||
protected ClassSymbol GetNamedTypeSymbolByFullName(string name, IEnumerable<string>? usings = null)
|
||||
{
|
||||
// The GetTypeByMetadataName method returns null if no type matches the full name or if 2 or more types (in different assemblies) match the full name.
|
||||
var symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName(name);
|
||||
if (symbol is not null)
|
||||
{
|
||||
// The GetTypeByMetadataName method returns null if no type matches the full name or if 2 or more types (in different assemblies) match the full name.
|
||||
var symbol = _context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName(name);
|
||||
if (symbol is not null)
|
||||
{
|
||||
return symbol;
|
||||
}
|
||||
return new ClassSymbol(symbol, symbol.GetBaseTypes());
|
||||
}
|
||||
|
||||
if (usings is not null)
|
||||
if (usings is not null)
|
||||
{
|
||||
foreach (var @using in usings)
|
||||
{
|
||||
foreach (var @using in usings)
|
||||
symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName($"{@using}.{name}");
|
||||
if (symbol is not null)
|
||||
{
|
||||
symbol = _context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName($"{@using}.{name}");
|
||||
if (symbol is not null)
|
||||
{
|
||||
return symbol;
|
||||
}
|
||||
return new ClassSymbol(symbol, symbol.GetBaseTypes());
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception($"The type '{name}' is not found.");
|
||||
}
|
||||
|
||||
throw new Exception($"The type '{name}' is not found.");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,3 @@
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
{
|
||||
internal record FileData(string FileName, string Text)
|
||||
{
|
||||
}
|
||||
}
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators;
|
||||
|
||||
internal record FileData(string FileName, string Text);
|
||||
@@ -1,7 +1,6 @@
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators;
|
||||
|
||||
internal interface IFileGenerator
|
||||
{
|
||||
internal interface IFileGenerator
|
||||
{
|
||||
FileData GenerateFile();
|
||||
}
|
||||
FileData GenerateFile();
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators;
|
||||
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
internal interface IFilesGenerator
|
||||
{
|
||||
internal interface IFilesGenerator
|
||||
{
|
||||
IEnumerable<FileData> GenerateFiles();
|
||||
}
|
||||
IEnumerable<FileData> GenerateFiles();
|
||||
}
|
||||
@@ -1,47 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using ProxyInterfaceSourceGenerator.Enums;
|
||||
using ProxyInterfaceSourceGenerator.Extensions;
|
||||
using ProxyInterfaceSourceGenerator.Model;
|
||||
using ProxyInterfaceSourceGenerator.SyntaxReceiver;
|
||||
using ProxyInterfaceSourceGenerator.Utils;
|
||||
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators;
|
||||
|
||||
internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator
|
||||
{
|
||||
internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator
|
||||
public PartialInterfacesGenerator(Context context, bool supportsNullable) :
|
||||
base(context, supportsNullable)
|
||||
{
|
||||
public PartialInterfacesGenerator(Context context, bool supportsNullable) :
|
||||
base(context, supportsNullable)
|
||||
}
|
||||
|
||||
public IEnumerable<FileData> GenerateFiles()
|
||||
{
|
||||
foreach (var ci in Context.CandidateInterfaces)
|
||||
{
|
||||
yield return GenerateFile(ci.Key, ci.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<FileData> GenerateFiles()
|
||||
{
|
||||
foreach (var ci in _context.CandidateInterfaces)
|
||||
{
|
||||
yield return GenerateFile(ci.Key, ci.Value);
|
||||
}
|
||||
}
|
||||
private FileData GenerateFile(InterfaceDeclarationSyntax ci, ProxyData pd)
|
||||
{
|
||||
var sourceInterfaceSymbol = GetNamedTypeSymbolByFullName(ci.Identifier.ToString(), pd.Usings);
|
||||
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName, pd.Usings);
|
||||
var interfaceName = targetClassSymbol.Symbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.InterfaceName);
|
||||
|
||||
private FileData GenerateFile(InterfaceDeclarationSyntax ci, ProxyData pd)
|
||||
{
|
||||
var sourceInterfaceSymbol = GetNamedTypeSymbolByFullName(ci.Identifier.ToString(), pd.Usings);
|
||||
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName, pd.Usings);
|
||||
var interfaceName = targetClassSymbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.InterfaceName);
|
||||
var file = new FileData(
|
||||
$"{sourceInterfaceSymbol.Symbol.GetFileName()}.g.cs",
|
||||
CreatePartialInterfaceCode(pd.Namespace, targetClassSymbol, interfaceName, pd.ProxyBaseClasses)
|
||||
);
|
||||
|
||||
var file = new FileData(
|
||||
$"{sourceInterfaceSymbol.GetFileName()}.g.cs",
|
||||
CreatePartialInterfaceCode(pd.Namespace, targetClassSymbol, interfaceName, pd.ProxyAll)
|
||||
);
|
||||
return file;
|
||||
}
|
||||
|
||||
// _context.GeneratedData.Add(new() { InterfaceName = interfaceName, ClassName = null, FileData = file });
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private string CreatePartialInterfaceCode(string ns, INamedTypeSymbol targetClassSymbol, string interfaceName, bool proxyAll) => $@"//----------------------------------------------------------------------------------------
|
||||
private string CreatePartialInterfaceCode(
|
||||
string ns,
|
||||
ClassSymbol classSymbol,
|
||||
string interfaceName,
|
||||
bool proxyBaseClasses) => $@"//----------------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
|
||||
//
|
||||
@@ -50,74 +50,73 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
// </auto-generated>
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
{(_supportsNullable ? "#nullable enable" : string.Empty)}
|
||||
{(SupportsNullable ? "#nullable enable" : string.Empty)}
|
||||
using System;
|
||||
|
||||
namespace {ns}
|
||||
{{
|
||||
public partial interface {interfaceName}
|
||||
{{
|
||||
{GenerateProperties(targetClassSymbol, proxyAll)}
|
||||
{GenerateProperties(classSymbol, proxyBaseClasses)}
|
||||
|
||||
{GenerateMethods(targetClassSymbol)}
|
||||
{GenerateMethods(classSymbol, proxyBaseClasses)}
|
||||
|
||||
{GenerateEvents(targetClassSymbol)}
|
||||
{GenerateEvents(classSymbol, proxyBaseClasses)}
|
||||
}}
|
||||
}}
|
||||
{(_supportsNullable ? "#nullable disable" : string.Empty)}";
|
||||
{(SupportsNullable ? "#nullable disable" : string.Empty)}";
|
||||
|
||||
private string GenerateProperties(INamedTypeSymbol targetClassSymbol, bool proxyAll)
|
||||
private string GenerateProperties(ClassSymbol targetClassSymbol, bool proxyBaseClasses)
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
|
||||
foreach (var property in MemberHelper.GetPublicProperties(targetClassSymbol, proxyBaseClasses))
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
|
||||
foreach (var property in MemberHelper.GetPublicProperties(targetClassSymbol))
|
||||
var type = GetPropertyType(property, out var isReplaced);
|
||||
if (isReplaced)
|
||||
{
|
||||
var type = GetPropertyType(property, out var isReplaced);
|
||||
if (isReplaced)
|
||||
{
|
||||
str.AppendLine($" {property.ToPropertyText(type)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
str.AppendLine($" {property.ToPropertyText()}");
|
||||
}
|
||||
str.AppendLine();
|
||||
str.AppendLine($" {property.ToPropertyText(type)}");
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
else
|
||||
{
|
||||
str.AppendLine($" {property.ToPropertyText()}");
|
||||
}
|
||||
str.AppendLine();
|
||||
}
|
||||
|
||||
private string GenerateMethods(INamedTypeSymbol targetClassSymbol)
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
private string GenerateMethods(ClassSymbol targetClassSymbol, bool proxyBaseClasses)
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
foreach (var method in MemberHelper.GetPublicMethods(targetClassSymbol, proxyBaseClasses))
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
foreach (var method in MemberHelper.GetPublicMethods(targetClassSymbol))
|
||||
var methodParameters = new List<string>();
|
||||
foreach (var ps in method.Parameters)
|
||||
{
|
||||
var methodParameters = new List<string>();
|
||||
foreach (var ps in method.Parameters)
|
||||
{
|
||||
var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
|
||||
methodParameters.Add($"{ps.GetParamsPrefix()}{ps.GetRefPrefix()}{type} {ps.GetSanitizedName()}{ps.GetDefaultValue()}");
|
||||
}
|
||||
|
||||
str.AppendLine($" {GetReplacedType(method.ReturnType, out _)} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){method.GetWhereStatement()};");
|
||||
str.AppendLine();
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
private string GenerateEvents(INamedTypeSymbol targetClassSymbol)
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
foreach (var @event in MemberHelper.GetPublicEvents(targetClassSymbol))
|
||||
{
|
||||
var ps = @event.First().Parameters.First();
|
||||
var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
|
||||
str.AppendLine($" event {type} {@event.Key.GetSanitizedName()};");
|
||||
str.AppendLine();
|
||||
methodParameters.Add($"{ps.GetParamsPrefix()}{ps.GetRefPrefix()}{type} {ps.GetSanitizedName()}{ps.GetDefaultValue()}");
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
str.AppendLine($" {GetReplacedType(method.ReturnType, out _)} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){method.GetWhereStatement()};");
|
||||
str.AppendLine();
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
private string GenerateEvents(ClassSymbol targetClassSymbol, bool proxyBaseClasses)
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
foreach (var @event in MemberHelper.GetPublicEvents(targetClassSymbol, proxyBaseClasses))
|
||||
{
|
||||
var ps = @event.First().Parameters.First();
|
||||
var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
|
||||
str.AppendLine($" event {type} {@event.Key.GetSanitizedName()};");
|
||||
str.AppendLine();
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
{
|
||||
internal class ProxyAttributeGenerator : IFileGenerator
|
||||
{
|
||||
private const string ClassName = "ProxyAttribute";
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators;
|
||||
|
||||
public FileData GenerateFile()
|
||||
{
|
||||
return new FileData($"ProxyInterfaceGenerator.{ClassName}.g.cs", $@"//----------------------------------------------------------------------------------------
|
||||
internal class ProxyAttributeGenerator : IFileGenerator
|
||||
{
|
||||
private const string ClassName = "ProxyAttribute";
|
||||
|
||||
public FileData GenerateFile()
|
||||
{
|
||||
return new FileData($"ProxyInterfaceGenerator.{ClassName}.g.cs", $@"//----------------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
|
||||
//
|
||||
@@ -23,15 +23,14 @@ namespace ProxyInterfaceGenerator
|
||||
public class {ClassName} : Attribute
|
||||
{{
|
||||
public Type Type {{ get; }}
|
||||
public bool ProxyAll {{ get; }}
|
||||
public bool ProxyBaseClasses {{ get; }}
|
||||
|
||||
public {ClassName}(Type type, bool proxyAll = false)
|
||||
public {ClassName}(Type type, bool proxyBaseClasses = false)
|
||||
{{
|
||||
Type = type;
|
||||
ProxyAll = proxyAll;
|
||||
ProxyBaseClasses = proxyBaseClasses;
|
||||
}}
|
||||
}}
|
||||
}}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using ProxyInterfaceSourceGenerator.Enums;
|
||||
using ProxyInterfaceSourceGenerator.Extensions;
|
||||
using ProxyInterfaceSourceGenerator.Model;
|
||||
using ProxyInterfaceSourceGenerator.SyntaxReceiver;
|
||||
using ProxyInterfaceSourceGenerator.Utils;
|
||||
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
namespace ProxyInterfaceSourceGenerator.FileGenerators;
|
||||
|
||||
internal class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
|
||||
{
|
||||
internal class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
|
||||
public ProxyClassesGenerator(Context context, bool supportsNullable) : base(context, supportsNullable)
|
||||
{
|
||||
public ProxyClassesGenerator(Context context, bool supportsNullable) : base(context, supportsNullable)
|
||||
}
|
||||
|
||||
public IEnumerable<FileData> GenerateFiles()
|
||||
{
|
||||
foreach (var ci in Context.CandidateInterfaces)
|
||||
{
|
||||
yield return GenerateFile(ci.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<FileData> GenerateFiles()
|
||||
{
|
||||
foreach (var ci in _context.CandidateInterfaces)
|
||||
{
|
||||
yield return GenerateFile(ci.Value);
|
||||
}
|
||||
}
|
||||
private FileData GenerateFile(ProxyData pd)
|
||||
{
|
||||
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName, pd.Usings);
|
||||
var interfaceName = targetClassSymbol.Symbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.InterfaceName);
|
||||
var className = targetClassSymbol.Symbol.ResolveProxyClassName();
|
||||
var constructorName = $"{targetClassSymbol.Symbol.Name}Proxy";
|
||||
|
||||
private FileData GenerateFile(ProxyData pd)
|
||||
{
|
||||
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName, pd.Usings);
|
||||
var interfaceName = targetClassSymbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.InterfaceName);
|
||||
var className = targetClassSymbol.ResolveProxyClassName();
|
||||
var constructorName = $"{targetClassSymbol.Name}Proxy";
|
||||
var file = new FileData(
|
||||
$"{targetClassSymbol.Symbol.GetFileName()}Proxy.g.cs",
|
||||
CreateProxyClassCode(pd.Namespace, targetClassSymbol, pd.ProxyBaseClasses, interfaceName, className, constructorName)
|
||||
);
|
||||
|
||||
var file = new FileData(
|
||||
$"{targetClassSymbol.GetFileName()}Proxy.g.cs",
|
||||
CreateProxyClassCode(pd.Namespace, targetClassSymbol, interfaceName, className, constructorName)
|
||||
);
|
||||
return file;
|
||||
}
|
||||
|
||||
// _context.GeneratedData.Add(new() { InterfaceName = interfaceName, ClassName = pd.ClassName, FileData = file });
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private string CreateProxyClassCode(
|
||||
string ns,
|
||||
INamedTypeSymbol targetClassSymbol,
|
||||
string interfaceName,
|
||||
string className,
|
||||
string constructorName) => $@"//----------------------------------------------------------------------------------------
|
||||
private string CreateProxyClassCode(
|
||||
string ns,
|
||||
ClassSymbol targetClassSymbol,
|
||||
bool proxyBaseClasses,
|
||||
string interfaceName,
|
||||
string className,
|
||||
string constructorName) => $@"//----------------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
|
||||
//
|
||||
@@ -55,7 +52,7 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
// </auto-generated>
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
{(_supportsNullable ? "#nullable enable" : string.Empty)}
|
||||
{(SupportsNullable ? "#nullable enable" : string.Empty)}
|
||||
using System;
|
||||
using AutoMapper;
|
||||
|
||||
@@ -63,13 +60,13 @@ namespace {ns}
|
||||
{{
|
||||
public class {className} : {interfaceName}
|
||||
{{
|
||||
public {targetClassSymbol} _Instance {{ get; }}
|
||||
public {targetClassSymbol.Symbol} _Instance {{ get; }}
|
||||
|
||||
{GeneratePublicProperties(targetClassSymbol, false)}
|
||||
{GeneratePublicProperties(targetClassSymbol, proxyBaseClasses)}
|
||||
|
||||
{GeneratePublicMethods(targetClassSymbol)}
|
||||
{GeneratePublicMethods(targetClassSymbol, proxyBaseClasses)}
|
||||
|
||||
{GenerateEvents(targetClassSymbol)}
|
||||
{GenerateEvents(targetClassSymbol, proxyBaseClasses)}
|
||||
|
||||
public {constructorName}({targetClassSymbol} instance)
|
||||
{{
|
||||
@@ -81,165 +78,164 @@ namespace {ns}
|
||||
{GeneratePrivateAutoMapper()}
|
||||
}}
|
||||
}}
|
||||
{(_supportsNullable ? "#nullable disable" : string.Empty)}";
|
||||
private string GeneratePrivateAutoMapper()
|
||||
{(SupportsNullable ? "#nullable disable" : string.Empty)}";
|
||||
private string GeneratePrivateAutoMapper()
|
||||
{
|
||||
return Context.ReplacedTypes.Count == 0 ? string.Empty : " private readonly IMapper _mapper;";
|
||||
}
|
||||
|
||||
private string GenerateMapperConfigurationForAutoMapper()
|
||||
{
|
||||
if (Context.ReplacedTypes.Count == 0)
|
||||
{
|
||||
return _context.ReplacedTypes.Count == 0 ? string.Empty : " private readonly IMapper _mapper;";
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private string GenerateMapperConfigurationForAutoMapper()
|
||||
var str = new StringBuilder();
|
||||
|
||||
str.AppendLine(" _mapper = new MapperConfiguration(cfg =>");
|
||||
str.AppendLine(" {");
|
||||
foreach (var replacedType in Context.ReplacedTypes)
|
||||
{
|
||||
if (_context.ReplacedTypes.Count == 0)
|
||||
str.AppendLine($" cfg.CreateMap<{replacedType.Key}, {replacedType.Value}>();");
|
||||
str.AppendLine($" cfg.CreateMap<{replacedType.Value}, {replacedType.Key}>();");
|
||||
}
|
||||
str.AppendLine(" }).CreateMapper();");
|
||||
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
private string GeneratePublicProperties(ClassSymbol targetClassSymbol, bool proxyBaseClasses)
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
|
||||
foreach (var property in MemberHelper.GetPublicProperties(targetClassSymbol, proxyBaseClasses))
|
||||
{
|
||||
var type = GetPropertyType(property, out var isReplaced);
|
||||
if (isReplaced)
|
||||
{
|
||||
return string.Empty;
|
||||
str.AppendLine($" public {property.ToPropertyTextForClass(type)}");
|
||||
}
|
||||
|
||||
var str = new StringBuilder();
|
||||
|
||||
str.AppendLine(" _mapper = new MapperConfiguration(cfg =>");
|
||||
str.AppendLine(" {");
|
||||
foreach (var replacedType in _context.ReplacedTypes)
|
||||
else
|
||||
{
|
||||
str.AppendLine($" cfg.CreateMap<{replacedType.Key}, {replacedType.Value}>();");
|
||||
str.AppendLine($" cfg.CreateMap<{replacedType.Value}, {replacedType.Key}>();");
|
||||
str.AppendLine($" public {property.ToPropertyTextForClass()}");
|
||||
}
|
||||
str.AppendLine(" }).CreateMapper();");
|
||||
|
||||
return str.ToString();
|
||||
str.AppendLine();
|
||||
}
|
||||
|
||||
private string GeneratePublicProperties(INamedTypeSymbol targetClassSymbol, bool proxyAll)
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
foreach (var property in MemberHelper.GetPublicProperties(targetClassSymbol))
|
||||
private string GeneratePublicMethods(ClassSymbol targetClassSymbol, bool proxyBaseClasses)
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
foreach (var method in MemberHelper.GetPublicMethods(targetClassSymbol, proxyBaseClasses))
|
||||
{
|
||||
var methodParameters = new List<string>();
|
||||
var invokeParameters = new List<string>();
|
||||
|
||||
foreach (var ps in method.Parameters)
|
||||
{
|
||||
var type = GetPropertyType(property, out var isReplaced);
|
||||
if (isReplaced)
|
||||
var type = GetParameterType(ps, out _);
|
||||
|
||||
methodParameters.Add($"{ps.GetParamsPrefix()}{ps.GetRefPrefix()}{type} {ps.GetSanitizedName()}{ps.GetDefaultValue()}");
|
||||
invokeParameters.Add($"{ps.GetRefPrefix()}{ps.GetSanitizedName()}_");
|
||||
}
|
||||
|
||||
string returnTypeAsString = GetReplacedType(method.ReturnType, out var returnIsReplaced);
|
||||
|
||||
str.AppendLine($" public {returnTypeAsString} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){method.GetWhereStatement()}");
|
||||
str.AppendLine(" {");
|
||||
foreach (var ps in method.Parameters)
|
||||
{
|
||||
string normalOrMap = $" = {ps.GetSanitizedName()}";
|
||||
if (ps.RefKind == RefKind.Out)
|
||||
{
|
||||
str.AppendLine($" public {property.ToPropertyTextForClass(type)}");
|
||||
normalOrMap = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
str.AppendLine($" public {property.ToPropertyTextForClass()}");
|
||||
var type = GetParameterType(ps, out var isReplaced);
|
||||
if (isReplaced)
|
||||
{
|
||||
normalOrMap = $" = _mapper.Map<{ps.Type}>({ps.GetSanitizedName()})";
|
||||
}
|
||||
}
|
||||
str.AppendLine();
|
||||
|
||||
str.AppendLine($" {ps.Type} {ps.GetSanitizedName()}_{normalOrMap};");
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
private string GeneratePublicMethods(INamedTypeSymbol targetClassSymbol)
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
foreach (var method in MemberHelper.GetPublicMethods(targetClassSymbol))
|
||||
{
|
||||
var methodParameters = new List<string>();
|
||||
var invokeParameters = new List<string>();
|
||||
|
||||
foreach (var ps in method.Parameters)
|
||||
{
|
||||
var type = GetParameterType(ps, out _);
|
||||
|
||||
methodParameters.Add($"{ps.GetParamsPrefix()}{ps.GetRefPrefix()}{type} {ps.GetSanitizedName()}{ps.GetDefaultValue()}");
|
||||
invokeParameters.Add($"{ps.GetRefPrefix()}{ps.GetSanitizedName()}_");
|
||||
}
|
||||
|
||||
string returnTypeAsString = GetReplacedType(method.ReturnType, out var returnIsReplaced);
|
||||
|
||||
str.AppendLine($" public {returnTypeAsString} {method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", methodParameters)}){method.GetWhereStatement()}");
|
||||
str.AppendLine(" {");
|
||||
foreach (var ps in method.Parameters)
|
||||
{
|
||||
string normalOrMap = $" = {ps.GetSanitizedName()}";
|
||||
if (ps.RefKind == RefKind.Out)
|
||||
{
|
||||
normalOrMap = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
var type = GetParameterType(ps, out var isReplaced);
|
||||
if (isReplaced)
|
||||
{
|
||||
normalOrMap = $" = _mapper.Map<{ps.Type}>({ps.GetSanitizedName()})";
|
||||
}
|
||||
}
|
||||
|
||||
str.AppendLine($" {ps.Type} {ps.GetSanitizedName()}_{normalOrMap};");
|
||||
}
|
||||
|
||||
#pragma warning disable RS1024 // Compare symbols correctly
|
||||
int hash = method.ReturnType.GetHashCode();
|
||||
int hash = method.ReturnType.GetHashCode();
|
||||
#pragma warning restore RS1024 // Compare symbols correctly
|
||||
var alternateReturnVariableName = $"result_{Math.Abs(hash)}";
|
||||
var alternateReturnVariableName = $"result_{Math.Abs(hash)}";
|
||||
|
||||
if (returnTypeAsString == "void")
|
||||
if (returnTypeAsString == "void")
|
||||
{
|
||||
str.AppendLine($" _Instance.{method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", invokeParameters)});");
|
||||
}
|
||||
else
|
||||
{
|
||||
str.AppendLine($" var {alternateReturnVariableName} = _Instance.{method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", invokeParameters)});");
|
||||
}
|
||||
|
||||
foreach (var ps in method.Parameters.Where(p => p.RefKind == RefKind.Out))
|
||||
{
|
||||
string normalOrMap = $" = {ps.GetSanitizedName()}_";
|
||||
if (ps.GetTypeEnum() == TypeEnum.Complex)
|
||||
{
|
||||
str.AppendLine($" _Instance.{method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", invokeParameters)});");
|
||||
var type = GetParameterType(ps, out var isReplaced);
|
||||
if (isReplaced)
|
||||
{
|
||||
normalOrMap = $" = _mapper.Map<{type}>({ps.GetSanitizedName()}_)";
|
||||
}
|
||||
}
|
||||
|
||||
str.AppendLine($" {ps.GetSanitizedName()}{normalOrMap};");
|
||||
}
|
||||
|
||||
if (returnTypeAsString != "void")
|
||||
{
|
||||
if (returnIsReplaced)
|
||||
{
|
||||
str.AppendLine($" return _mapper.Map<{returnTypeAsString}>({alternateReturnVariableName});");
|
||||
}
|
||||
else
|
||||
{
|
||||
str.AppendLine($" var {alternateReturnVariableName} = _Instance.{method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", invokeParameters)});");
|
||||
str.AppendLine($" return {alternateReturnVariableName};");
|
||||
}
|
||||
|
||||
foreach (var ps in method.Parameters.Where(p => p.RefKind == RefKind.Out))
|
||||
{
|
||||
string normalOrMap = $" = {ps.GetSanitizedName()}_";
|
||||
if (ps.GetTypeEnum() == TypeEnum.Complex)
|
||||
{
|
||||
var type = GetParameterType(ps, out var isReplaced);
|
||||
if (isReplaced)
|
||||
{
|
||||
normalOrMap = $" = _mapper.Map<{type}>({ps.GetSanitizedName()}_)";
|
||||
}
|
||||
}
|
||||
|
||||
str.AppendLine($" {ps.GetSanitizedName()}{normalOrMap};");
|
||||
}
|
||||
|
||||
if (returnTypeAsString != "void")
|
||||
{
|
||||
if (returnIsReplaced)
|
||||
{
|
||||
str.AppendLine($" return _mapper.Map<{returnTypeAsString}>({alternateReturnVariableName});");
|
||||
}
|
||||
else
|
||||
{
|
||||
str.AppendLine($" return {alternateReturnVariableName};");
|
||||
}
|
||||
}
|
||||
|
||||
str.AppendLine(" }");
|
||||
str.AppendLine();
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
str.AppendLine(" }");
|
||||
str.AppendLine();
|
||||
}
|
||||
|
||||
private string GenerateEvents(INamedTypeSymbol targetClassSymbol)
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
private string GenerateEvents(ClassSymbol targetClassSymbol, bool proxyBaseClasses)
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
foreach (var @event in MemberHelper.GetPublicEvents(targetClassSymbol, proxyBaseClasses))
|
||||
{
|
||||
var str = new StringBuilder();
|
||||
foreach (var @event in MemberHelper.GetPublicEvents(targetClassSymbol))
|
||||
var name = @event.Key.GetSanitizedName();
|
||||
var ps = @event.First().Parameters.First();
|
||||
var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
|
||||
str.Append($" public event {type} {name} {{");
|
||||
|
||||
if (@event.Any(e => e.MethodKind == MethodKind.EventAdd))
|
||||
{
|
||||
var name = @event.Key.GetSanitizedName();
|
||||
var ps = @event.First().Parameters.First();
|
||||
var type = ps.GetTypeEnum() == TypeEnum.Complex ? GetParameterType(ps, out _) : ps.Type.ToString();
|
||||
str.Append($" public event {type} {name} {{");
|
||||
|
||||
if (@event.Any(e => e.MethodKind == MethodKind.EventAdd))
|
||||
{
|
||||
str.Append($" add {{ _Instance.{name} += value; }}");
|
||||
}
|
||||
if (@event.Any(e => e.MethodKind == MethodKind.EventRemove))
|
||||
{
|
||||
str.Append($" remove {{ _Instance.{name} -= value; }}");
|
||||
}
|
||||
|
||||
str.AppendLine(" }");
|
||||
str.AppendLine();
|
||||
str.Append($" add {{ _Instance.{name} += value; }}");
|
||||
}
|
||||
if (@event.Any(e => e.MethodKind == MethodKind.EventRemove))
|
||||
{
|
||||
str.Append($" remove {{ _Instance.{name} -= value; }}");
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
str.AppendLine(" }");
|
||||
str.AppendLine();
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user