Add support for base (proxy) class (#29)

This commit is contained in:
Stef Heyenrath
2022-02-04 11:33:26 +01:00
committed by GitHub
parent 94d322cfb3
commit d7483d6b7e
38 changed files with 400 additions and 309 deletions
@@ -71,4 +71,11 @@ internal static class NamedTypeSymbolExtensions
$"{namedTypeSymbol.Name}Proxy" :
$"{namedTypeSymbol.Name}Proxy<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>";
}
public static string ResolveFullProxyClassName(this INamedTypeSymbol namedTypeSymbol)
{
return !namedTypeSymbol.IsGenericType ?
$"{namedTypeSymbol}Proxy" :
$"{namedTypeSymbol}Proxy<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>";
}
}
@@ -1,6 +1,6 @@
using Microsoft.CodeAnalysis;
using ProxyInterfaceSourceGenerator.Enums;
using ProxyInterfaceSourceGenerator.Model;
using ProxyInterfaceSourceGenerator.Models;
namespace ProxyInterfaceSourceGenerator.Extensions;
@@ -0,0 +1,29 @@
namespace ProxyInterfaceSourceGenerator.Extensions;
internal static class StringExtensions
{
// See https://andrewlock.net/why-is-string-gethashcode-different-each-time-i-run-my-program-in-net-core/
public static string GetDeterministicHashCodeAsString(this string str)
{
unchecked
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1;
for (int i = 0; i < str.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ str[i];
if (i == str.Length - 1)
{
break;
}
hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
}
int result = hash1 + hash2 * 1566083941;
return result.ToString().Replace('-', '_');
}
}
}
@@ -20,8 +20,9 @@ internal static class TypeSymbolExtensions
return TypeEnum.Complex;
}
public static bool IsString(this ITypeSymbol ts)
{
return ts.ToString() == "string" || ts.ToString() == "string?";
}
public static bool IsString(this ITypeSymbol ts) =>
ts.ToString() == "string" || ts.ToString() == "string?";
internal static bool IsClass(this ITypeSymbol ts) =>
ts.IsReferenceType && ts.TypeKind == TypeKind.Class;
}
@@ -1,6 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis;
using ProxyInterfaceSourceGenerator.Extensions;
using ProxyInterfaceSourceGenerator.Model;
using ProxyInterfaceSourceGenerator.Models;
namespace ProxyInterfaceSourceGenerator.FileGenerators;
@@ -36,11 +37,11 @@ internal abstract class BaseGenerator
{
if (!Context.ReplacedTypes.ContainsKey(typeSymbolAsString))
{
Context.ReplacedTypes.Add(typeSymbolAsString, existing.InterfaceName);
Context.ReplacedTypes.Add(typeSymbolAsString, existing.FullInterfaceName);
}
isReplaced = true;
return existing.InterfaceName;
return existing.FullInterfaceName;
}
if (typeSymbol is INamedTypeSymbol namedTypedSymbol)
@@ -56,10 +57,10 @@ internal abstract class BaseGenerator
if (!Context.ReplacedTypes.ContainsKey(typeArgumentAsString))
{
Context.ReplacedTypes.Add(typeArgumentAsString, exist.InterfaceName);
Context.ReplacedTypes.Add(typeArgumentAsString, exist.FullInterfaceName);
}
propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, exist.InterfaceName);
propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, exist.FullInterfaceName);
}
}
@@ -69,27 +70,28 @@ internal abstract class BaseGenerator
return typeSymbolAsString;
}
protected ClassSymbol GetNamedTypeSymbolByFullName(string name, IEnumerable<string>? usings = null)
protected bool TryGetNamedTypeSymbolByFullName(TypeKind kind, string name, IEnumerable<string> usings, [NotNullWhen(true)] out ClassSymbol? classSymbol)
{
classSymbol = default;
// 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)
if (symbol is not null && symbol.TypeKind == kind)
{
return new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
classSymbol = new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
return true;
}
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.TypeKind == kind)
{
symbol = Context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName($"{@using}.{name}");
if (symbol is not null)
{
return new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
}
classSymbol = new ClassSymbol(symbol, symbol.GetBaseTypes(), symbol.AllInterfaces.ToList());
return true;
}
}
throw new Exception($"The type '{name}' is not found.");
return false;
}
}
@@ -1,3 +0,0 @@
namespace ProxyInterfaceSourceGenerator.FileGenerators;
internal record FileData(string FileName, string Text);
@@ -1,3 +1,5 @@
using ProxyInterfaceSourceGenerator.Models;
namespace ProxyInterfaceSourceGenerator.FileGenerators;
internal interface IFileGenerator
@@ -1,3 +1,5 @@
using ProxyInterfaceSourceGenerator.Models;
namespace ProxyInterfaceSourceGenerator.FileGenerators;
internal interface IFilesGenerator
@@ -1,9 +1,10 @@
using System.Diagnostics.CodeAnalysis;
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.Models;
using ProxyInterfaceSourceGenerator.Utils;
namespace ProxyInterfaceSourceGenerator.FileGenerators;
@@ -19,22 +20,35 @@ internal class PartialInterfacesGenerator : BaseGenerator, IFilesGenerator
{
foreach (var ci in Context.CandidateInterfaces)
{
yield return GenerateFile(ci.Key, ci.Value);
if (TryGenerateFile(ci.Key, ci.Value, out var file))
{
yield return file;
}
}
}
private FileData GenerateFile(InterfaceDeclarationSyntax ci, ProxyData pd)
private bool TryGenerateFile(InterfaceDeclarationSyntax ci, ProxyData pd, [NotNullWhen(true)] out FileData? fileData)
{
var sourceInterfaceSymbol = GetNamedTypeSymbolByFullName(ci.Identifier.ToString(), pd.Usings);
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName, pd.Usings);
var interfaceName = targetClassSymbol.Symbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.InterfaceName);
fileData = default;
var file = new FileData(
if (!TryGetNamedTypeSymbolByFullName(TypeKind.Interface, ci.Identifier.ToString(), pd.Usings, out var sourceInterfaceSymbol))
{
return false;
}
if (!TryGetNamedTypeSymbolByFullName(TypeKind.Class, pd.TypeName, pd.Usings, out var targetClassSymbol))
{
return false;
}
var interfaceName = targetClassSymbol.Symbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.ShortInterfaceName);
fileData = new FileData(
$"{sourceInterfaceSymbol.Symbol.GetFileName()}.g.cs",
CreatePartialInterfaceCode(pd.Namespace, targetClassSymbol, interfaceName, pd.ProxyBaseClasses)
);
return file;
return true;
}
private string CreatePartialInterfaceCode(
@@ -1,3 +1,5 @@
using ProxyInterfaceSourceGenerator.Models;
namespace ProxyInterfaceSourceGenerator.FileGenerators;
internal class ProxyAttributeGenerator : IFileGenerator
@@ -1,15 +1,14 @@
using System.Diagnostics.CodeAnalysis;
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.Models;
using ProxyInterfaceSourceGenerator.Utils;
namespace ProxyInterfaceSourceGenerator.FileGenerators;
internal class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
internal partial class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
{
public ProxyClassesGenerator(Context context, bool supportsNullable) : base(context, supportsNullable)
{
@@ -19,32 +18,72 @@ internal class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
{
foreach (var ci in Context.CandidateInterfaces)
{
yield return GenerateFile(ci.Value, Context.CandidateInterfaces);
if (TryGenerateFile(ci.Value, out var file))
{
yield return file;
}
}
}
private FileData GenerateFile(ProxyData pd, IDictionary<InterfaceDeclarationSyntax, ProxyData> candidateInterfaces)
[SuppressMessage("MicrosoftCodeAnalysisCorrectness", "RS1024:Compare symbols correctly", Justification = "<Pending>")]
private bool TryGenerateFile(ProxyData pd, [NotNullWhen(true)] out FileData? fileData)
{
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName, pd.Usings);
var interfaceName = targetClassSymbol.Symbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.InterfaceName);
fileData = default;
if (!TryGetNamedTypeSymbolByFullName(TypeKind.Class, pd.TypeName, pd.Usings, out var targetClassSymbol))
{
return false;
}
var interfaceName = targetClassSymbol.Symbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.ShortInterfaceName);
var className = targetClassSymbol.Symbol.ResolveProxyClassName();
var constructorName = $"{targetClassSymbol.Symbol.Name}Proxy";
var file = new FileData(
var extendsProxyClasses = targetClassSymbol.BaseTypes
.Join(
Context.CandidateInterfaces.Values.Select(v => v.RawTypeName),
bt => bt.ToString(),
ci => ci, (bt, _) => bt
).ToList();
fileData = new FileData(
$"{targetClassSymbol.Symbol.GetFileName()}Proxy.g.cs",
CreateProxyClassCode(pd.Namespace, targetClassSymbol, pd.ProxyBaseClasses, interfaceName, className, constructorName)
CreateProxyClassCode(pd, targetClassSymbol, extendsProxyClasses, interfaceName, className, constructorName)
);
return file;
return true;
}
private string CreateProxyClassCode(
string ns,
ProxyData pd,
ClassSymbol targetClassSymbol,
bool proxyBaseClasses,
List<INamedTypeSymbol> extendsProxyClasses,
string interfaceName,
string className,
string constructorName) => $@"//----------------------------------------------------------------------------------------
string constructorName)
{
var extendsFullNames = extendsProxyClasses.Select(e => e.ResolveFullProxyClassName()).ToList();
var extends = extendsProxyClasses.Any() ? $"{string.Join(", ", extendsFullNames)}, " : string.Empty;
var @base = extendsProxyClasses.Any() ? " : base(instance)" : string.Empty;
var @new = extendsProxyClasses.Any() ? "new " : string.Empty;
var instanceBaseDefinition = extendsProxyClasses.Any() ? $"public {extendsProxyClasses.First()} _InstanceBase {{ get; }}\r\n" : string.Empty;
var instanceBaseSet = extendsProxyClasses.Any() ? "_InstanceBase = instance;" : string.Empty;
var properties = GeneratePublicProperties(targetClassSymbol, pd.ProxyBaseClasses);
var methods = GeneratePublicMethods(targetClassSymbol, pd.ProxyBaseClasses);
var events = GenerateEvents(targetClassSymbol, pd.ProxyBaseClasses);
var configurationForAutoMapper = string.Empty;
var privateAutoMapper = string.Empty;
var usingAutoMapper = string.Empty;
if (Context.ReplacedTypes.Any())
{
configurationForAutoMapper = GenerateMapperConfigurationForAutoMapper();
privateAutoMapper = GeneratePrivateAutoMapper();
usingAutoMapper = "using AutoMapper;";
}
return $@"//----------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
//
@@ -55,52 +94,52 @@ internal class ProxyClassesGenerator : BaseGenerator, IFilesGenerator
{(SupportsNullable ? "#nullable enable" : string.Empty)}
using System;
using AutoMapper;
{usingAutoMapper}
namespace {ns}
namespace {pd.Namespace}
{{
public partial class {className} : {interfaceName}
public partial class {className} : {extends}{interfaceName}
{{
public {targetClassSymbol.Symbol} _Instance {{ get; }}
public {@new}{targetClassSymbol.Symbol} _Instance {{ get; }}
{instanceBaseDefinition}
{GeneratePublicProperties(targetClassSymbol, proxyBaseClasses)}
{properties}
{GeneratePublicMethods(targetClassSymbol, proxyBaseClasses)}
{methods}
{GenerateEvents(targetClassSymbol, proxyBaseClasses)}
{events}
public {constructorName}({targetClassSymbol} instance)
public {constructorName}({targetClassSymbol} instance){@base}
{{
_Instance = instance;
{instanceBaseSet}
{GenerateMapperConfigurationForAutoMapper()}
{configurationForAutoMapper}
}}
{GeneratePrivateAutoMapper()}
{privateAutoMapper}
}}
}}
{(SupportsNullable ? "#nullable disable" : string.Empty)}";
}
private string GeneratePrivateAutoMapper()
private static string GeneratePrivateAutoMapper()
{
return Context.ReplacedTypes.Count == 0 ? string.Empty : " private readonly IMapper _mapper;";
return " private readonly IMapper _mapper;";
}
private string GenerateMapperConfigurationForAutoMapper()
{
if (Context.ReplacedTypes.Count == 0)
{
return string.Empty;
}
var str = new StringBuilder();
str.AppendLine(" _mapper = new MapperConfiguration(cfg =>");
str.AppendLine(" {");
foreach (var replacedType in Context.ReplacedTypes)
{
str.AppendLine($" cfg.CreateMap<{replacedType.Key}, {replacedType.Value}>();");
str.AppendLine($" cfg.CreateMap<{replacedType.Value}, {replacedType.Key}>();");
var proxy = $"{replacedType.Key}Proxy";
str.AppendLine($" cfg.CreateMap<{replacedType.Key}, {replacedType.Value}>().ConstructUsing(instance => new {proxy}(instance));");
str.AppendLine($" cfg.CreateMap<{replacedType.Value}, {replacedType.Key}>().ConstructUsing(proxy => (({proxy}) proxy)._Instance);");
}
str.AppendLine(" }).CreateMapper();");
@@ -167,11 +206,8 @@ namespace {ns}
str.AppendLine($" {ps.Type} {ps.GetSanitizedName()}_{normalOrMap};");
}
#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)}";
var methodName = method.GetMethodNameWithOptionalTypeParameters();
var alternateReturnVariableName = $"result_{methodName.GetDeterministicHashCodeAsString()}";
string instance = !method.IsStatic ?
"_Instance" :
@@ -179,11 +215,11 @@ namespace {ns}
if (returnTypeAsString == "void")
{
str.AppendLine($" {instance}.{method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", invokeParameters)});");
str.AppendLine($" {instance}.{methodName}({string.Join(", ", invokeParameters)});");
}
else
{
str.AppendLine($" var {alternateReturnVariableName} = {instance}.{method.GetMethodNameWithOptionalTypeParameters()}({string.Join(", ", invokeParameters)});");
str.AppendLine($" var {alternateReturnVariableName} = {instance}.{methodName}({string.Join(", ", invokeParameters)});");
}
foreach (var ps in method.Parameters.Where(p => p.RefKind == RefKind.Out))
@@ -1,6 +1,6 @@
using Microsoft.CodeAnalysis;
namespace ProxyInterfaceSourceGenerator.Model;
namespace ProxyInterfaceSourceGenerator.Models;
internal record ClassSymbol(INamedTypeSymbol Symbol, List<INamedTypeSymbol> BaseTypes, List<INamedTypeSymbol> Interfaces)
{
@@ -1,16 +1,15 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using ProxyInterfaceSourceGenerator.SyntaxReceiver;
namespace ProxyInterfaceSourceGenerator;
internal record Context
{
public GeneratorExecutionContext GeneratorExecutionContext { get; init; }
// public List<ContextData> GeneratedData { get; } = new List<ContextData>();
public IDictionary<InterfaceDeclarationSyntax, ProxyData> CandidateInterfaces { get; init; } = default!;
public Dictionary<string, string> ReplacedTypes { get; } = new Dictionary<string, string>();
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace ProxyInterfaceSourceGenerator.Models;
internal record Context
{
public GeneratorExecutionContext GeneratorExecutionContext { get; init; }
// public List<ContextData> GeneratedData { get; } = new List<ContextData>();
public IDictionary<InterfaceDeclarationSyntax, ProxyData> CandidateInterfaces { get; init; } = default!;
public Dictionary<string, string> ReplacedTypes { get; } = new Dictionary<string, string>();
}
@@ -1,12 +1,10 @@
using ProxyInterfaceSourceGenerator.FileGenerators;
namespace ProxyInterfaceSourceGenerator;
internal record ContextData
{
public string? InterfaceName { get; init; }
public string? ClassName { get; init; }
public FileData FileData { get; init; } = default!;
namespace ProxyInterfaceSourceGenerator.Models;
internal record ContextData
{
public string? InterfaceName { get; init; }
public string? ClassName { get; init; }
public FileData FileData { get; init; } = default!;
}
@@ -0,0 +1,3 @@
namespace ProxyInterfaceSourceGenerator.Models;
internal record FileData(string FileName, string Text);
@@ -1,11 +1,12 @@
namespace ProxyInterfaceSourceGenerator.SyntaxReceiver;
internal record ProxyData
(
string Namespace,
string InterfaceName,
string RawTypeName,
string TypeName,
List<string> Usings,
bool ProxyBaseClasses
namespace ProxyInterfaceSourceGenerator.Models;
internal record ProxyData
(
string Namespace,
string ShortInterfaceName,
string FullInterfaceName,
string RawTypeName,
string TypeName,
List<string> Usings,
bool ProxyBaseClasses
);
@@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using ProxyInterfaceSourceGenerator.FileGenerators;
using ProxyInterfaceSourceGenerator.Models;
using ProxyInterfaceSourceGenerator.SyntaxReceiver;
namespace ProxyInterfaceSourceGenerator;
@@ -10,7 +11,7 @@ namespace ProxyInterfaceSourceGenerator;
[Generator]
internal class ProxyInterfaceCodeGenerator : ISourceGenerator
{
private readonly ProxyAttributeGenerator _proxyAttributeGenerator = new ProxyAttributeGenerator();
private readonly ProxyAttributeGenerator _proxyAttributeGenerator = new ();
public void Initialize(GeneratorInitializationContext context)
{
@@ -24,21 +25,21 @@ internal class ProxyInterfaceCodeGenerator : ISourceGenerator
public void Execute(GeneratorExecutionContext context)
{
if (context.ParseOptions is not CSharpParseOptions csharpParseOptions)
{
throw new NotSupportedException("Only C# is supported.");
}
if (context.SyntaxReceiver is not ProxySyntaxReceiver receiver)
{
return;
}
// https://github.com/reactiveui/refit/blob/main/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
var supportsNullable = csharpParseOptions.LanguageVersion >= LanguageVersion.CSharp8;
try
{
if (context.ParseOptions is not CSharpParseOptions csharpParseOptions)
{
throw new NotSupportedException("Only C# is supported.");
}
if (context.SyntaxReceiver is not ProxySyntaxReceiver receiver)
{
throw new NotSupportedException($"Only {nameof(ProxySyntaxReceiver)} is supported.");
}
// https://github.com/reactiveui/refit/blob/main/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
var supportsNullable = csharpParseOptions.LanguageVersion >= LanguageVersion.CSharp8;
GenerateProxyAttribute(context, receiver);
GeneratePartialInterfaces(context, receiver, supportsNullable);
GenerateProxyClasses(context, receiver, supportsNullable);
@@ -51,7 +52,7 @@ internal class ProxyInterfaceCodeGenerator : ISourceGenerator
private void GenerateError(GeneratorExecutionContext context, Exception exception)
{
var message = $"/*\r\n{nameof(ProxyInterfaceCodeGenerator)}\r\n\r\n{exception}\r\n\r\n{exception.StackTrace}*/";
var message = $"/*\r\n{nameof(ProxyInterfaceCodeGenerator)}\r\n\r\n[Exception]\r\n{exception}\r\n\r\n[StackTrace]\r\n{exception.StackTrace}*/";
context.AddSource("Error.g", SourceText.From(message, Encoding.UTF8));
}
@@ -76,9 +77,9 @@ internal class ProxyInterfaceCodeGenerator : ISourceGenerator
};
var partialInterfacesGenerator = new PartialInterfacesGenerator(context, supportsNullable);
foreach (var data in partialInterfacesGenerator.GenerateFiles())
foreach (var (fileName, text) in partialInterfacesGenerator.GenerateFiles())
{
context.GeneratorExecutionContext.AddSource(data.FileName, SourceText.From(data.Text, Encoding.UTF8));
context.GeneratorExecutionContext.AddSource(fileName, SourceText.From(text, Encoding.UTF8));
}
}
@@ -91,9 +92,9 @@ internal class ProxyInterfaceCodeGenerator : ISourceGenerator
};
var proxyClassesGenerator = new ProxyClassesGenerator(context, supportsNullable);
foreach (var data in proxyClassesGenerator.GenerateFiles())
foreach (var (fileName, text) in proxyClassesGenerator.GenerateFiles())
{
context.GeneratorExecutionContext.AddSource(data.FileName, SourceText.From(data.Text, Encoding.UTF8));
context.GeneratorExecutionContext.AddSource(fileName, SourceText.From(text, Encoding.UTF8));
}
}
}
@@ -36,7 +36,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="10.1.1" />
<!--<PackageReference Include="AutoMapper" Version="10.1.1" />-->
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -46,11 +46,19 @@
</ItemGroup>
<ItemGroup>
<None Remove="bin\Debug\netstandard2.0\\ProxyInterfaceGenerator.dll" />
<None Remove="bin\Release\netstandard2.0\\ProxyInterfaceGenerator.dll" />
<ProjectCapability Include="DynamicDependentFile" />
<ProjectCapability Include="DynamicFileNesting" />
</ItemGroup>
<ItemGroup>
<Compile Update="ProxyClassesGenerator.*.cs">
<DependentUpon>ProxyClassesGenerator.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Remove="bin\Debug\netstandard2.0\\ProxyInterfaceGenerator.dll" />
<None Remove="bin\Release\netstandard2.0\\ProxyInterfaceGenerator.dll" />
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>
@@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using ProxyInterfaceSourceGenerator.Extensions;
using ProxyInterfaceSourceGenerator.Models;
namespace ProxyInterfaceSourceGenerator.SyntaxReceiver;
@@ -44,13 +45,13 @@ internal class ProxySyntaxReceiver : ISyntaxReceiver
var usings = new List<string>();
string ns = string.Empty;
if (SyntaxNodeUtils.TryGetParentSyntax(interfaceDeclarationSyntax, out NamespaceDeclarationSyntax? namespaceDeclarationSyntax))
if (interfaceDeclarationSyntax.TryGetParentSyntax(out NamespaceDeclarationSyntax? namespaceDeclarationSyntax))
{
ns = namespaceDeclarationSyntax.Name.ToString();
usings.Add(ns);
}
if (SyntaxNodeUtils.TryGetParentSyntax(interfaceDeclarationSyntax, out CompilationUnitSyntax? cc))
if (interfaceDeclarationSyntax.TryGetParentSyntax(out CompilationUnitSyntax? cc))
{
foreach (var @using in cc.Usings)
{
@@ -58,7 +59,9 @@ internal class ProxySyntaxReceiver : ISyntaxReceiver
}
}
string rawTypeName = ((TypeOfExpressionSyntax)argumentList.Arguments[0].Expression).Type.ToString();
var type = ((TypeOfExpressionSyntax)argumentList.Arguments[0].Expression).Type;
string rawTypeName = type.ToString();
bool proxyAllClasses;
try
{
@@ -73,6 +76,7 @@ internal class ProxySyntaxReceiver : ISyntaxReceiver
(
ns,
interfaceDeclarationSyntax.Identifier.ToString(),
$"{ns}.{interfaceDeclarationSyntax.Identifier}",
rawTypeName,
ConvertTypeName(rawTypeName),
usings,
@@ -1,5 +1,5 @@
using Microsoft.CodeAnalysis;
using ProxyInterfaceSourceGenerator.Model;
using ProxyInterfaceSourceGenerator.Models;
namespace ProxyInterfaceSourceGenerator.Utils;