diff --git a/ProxyInterfaceSourceGenerator Solution.sln.DotSettings b/ProxyInterfaceSourceGenerator Solution.sln.DotSettings
new file mode 100644
index 0000000..db9ce64
--- /dev/null
+++ b/ProxyInterfaceSourceGenerator Solution.sln.DotSettings
@@ -0,0 +1,2 @@
+
+ True
\ No newline at end of file
diff --git a/README.md b/README.md
index c8f2244..02afc5b 100644
--- a/README.md
+++ b/README.md
@@ -38,6 +38,17 @@ public partial interface IPerson
}
```
+#### ProxyBaseClasses
+In case also want to proxy the properties/methods/events from the base class(es), use this:
+
+``` c#
+[ProxyInterfaceGenerator.Proxy(typeof(ProxyInterfaceConsumer.Person), true)] // 👈 Provide `true` as second parameter.
+public partial interface IPerson
+{
+}
+```
+
+
### When the code is compiled, this source generator creates the following
#### :one: An additional partial interface
@@ -80,4 +91,4 @@ public class PersonProxy : IPerson
IPerson p = new PersonProxy(new Person());
p.Name = "test";
p.HelloWorld("stef");
-```
+```
\ No newline at end of file
diff --git a/src-examples/ProxyInterfaceConsumer/IAddress.cs b/src-examples/ProxyInterfaceConsumer/IAddress.cs
index 70b8fcb..1366e7f 100644
--- a/src-examples/ProxyInterfaceConsumer/IAddress.cs
+++ b/src-examples/ProxyInterfaceConsumer/IAddress.cs
@@ -1,11 +1,9 @@
-using DifferentNamespace;
-using System;
-using System.Linq;
-
-namespace ProxyInterfaceConsumer
-{
- [ProxyInterfaceGenerator.Proxy(typeof(Address))]
- public partial interface IAddress
- {
- }
+using DifferentNamespace;
+
+namespace ProxyInterfaceConsumer
+{
+ [ProxyInterfaceGenerator.Proxy(typeof(Address))]
+ public partial interface IAddress
+ {
+ }
}
\ No newline at end of file
diff --git a/src-examples/ProxyInterfaceConsumer/IPersonT.cs b/src-examples/ProxyInterfaceConsumer/IPersonT.cs
index 1327039..3153816 100644
--- a/src-examples/ProxyInterfaceConsumer/IPersonT.cs
+++ b/src-examples/ProxyInterfaceConsumer/IPersonT.cs
@@ -1,7 +1,7 @@
-namespace ProxyInterfaceConsumer
+namespace ProxyInterfaceConsumer
{
[ProxyInterfaceGenerator.Proxy(typeof(ProxyInterfaceConsumer.PersonT<>))]
- public partial interface IPersonT where T : struct
+ public partial interface IPersonT // where T : struct
{
}
}
\ No newline at end of file
diff --git a/src-examples/ProxyInterfaceConsumer/Program.cs b/src-examples/ProxyInterfaceConsumer/Program.cs
index 2692a00..b10cbb1 100644
--- a/src-examples/ProxyInterfaceConsumer/Program.cs
+++ b/src-examples/ProxyInterfaceConsumer/Program.cs
@@ -15,16 +15,16 @@ namespace ProxyInterfaceConsumer
public static void Main()
{
- IPersonT pT = new PersonTProxy(new PersonT());
- pT.TVal = 1;
- Console.WriteLine(JsonSerializer.Serialize(pT, JsonSerializerOptions));
- Console.WriteLine(new string('-', 80));
+ //IPersonT pT = new PersonTProxy(new PersonT());
+ //pT.TVal = 1;
+ //Console.WriteLine(JsonSerializer.Serialize(pT, JsonSerializerOptions));
+ //Console.WriteLine(new string('-', 80));
- IPersonTT pTT = new PersonTTProxy(new PersonTT());
- pTT.TVal1 = 42;
- pTT.TVal2 = new Program();
- Console.WriteLine(JsonSerializer.Serialize(pTT, JsonSerializerOptions));
- Console.WriteLine(new string('-', 80));
+ //IPersonTT pTT = new PersonTTProxy(new PersonTT());
+ //pTT.TVal1 = 42;
+ //pTT.TVal2 = new Program();
+ //Console.WriteLine(JsonSerializer.Serialize(pTT, JsonSerializerOptions));
+ //Console.WriteLine(new string('-', 80));
var ap = new AddressProxy(new Address { HouseNumber = 42 });
ap.HouseNumber = -1;
diff --git a/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj b/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj
index 7718314..43d1dba 100644
--- a/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj
+++ b/src-examples/ProxyInterfaceConsumer/ProxyInterfaceConsumer.csproj
@@ -7,6 +7,13 @@
enable
+
+
+
+
+
+
+
diff --git a/src/ProxyInterfaceSourceGenerator/Compatibility/NullableAttributes.cs b/src/ProxyInterfaceSourceGenerator/Compatibility/NullableAttributes.cs
index 82dfeb2..5aceb18 100644
--- a/src/ProxyInterfaceSourceGenerator/Compatibility/NullableAttributes.cs
+++ b/src/ProxyInterfaceSourceGenerator/Compatibility/NullableAttributes.cs
@@ -1,18 +1,17 @@
-// https://stackoverflow.com/questions/61573959/how-to-resolve-error-notnullwhen-attribute-is-inaccessible-due-to-its-protectio
+// https://stackoverflow.com/questions/61573959/how-to-resolve-error-notnullwhen-attribute-is-inaccessible-due-to-its-protectio
-namespace System.Diagnostics.CodeAnalysis
+namespace System.Diagnostics.CodeAnalysis;
+
+/// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it.
+[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+internal sealed class NotNullWhenAttribute : Attribute
{
- /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it.
- [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
- internal sealed class NotNullWhenAttribute : Attribute
- {
- /// Initializes the attribute with the specified return value condition.
- ///
- /// The return value condition. If the method returns this value, the associated parameter will not be null.
- ///
- public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
+ /// Initializes the attribute with the specified return value condition.
+ ///
+ /// The return value condition. If the method returns this value, the associated parameter will not be null.
+ ///
+ public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
- /// Gets the return value condition.
- public bool ReturnValue { get; }
- }
+ /// Gets the return value condition.
+ public bool ReturnValue { get; }
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Context.cs b/src/ProxyInterfaceSourceGenerator/Context.cs
index 65c3914..e065eac 100644
--- a/src/ProxyInterfaceSourceGenerator/Context.cs
+++ b/src/ProxyInterfaceSourceGenerator/Context.cs
@@ -1,18 +1,16 @@
-using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using ProxyInterfaceSourceGenerator.SyntaxReceiver;
-namespace ProxyInterfaceSourceGenerator
+namespace ProxyInterfaceSourceGenerator;
+
+internal record Context
{
- internal record Context
- {
- public GeneratorExecutionContext GeneratorExecutionContext { get; init; }
+ public GeneratorExecutionContext GeneratorExecutionContext { get; init; }
- // public List GeneratedData { get; } = new List();
+ // public List GeneratedData { get; } = new List();
- public IDictionary CandidateInterfaces { get; init; } = default!;
+ public IDictionary CandidateInterfaces { get; init; } = default!;
- public Dictionary ReplacedTypes { get; } = new Dictionary();
- }
+ public Dictionary ReplacedTypes { get; } = new Dictionary();
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/ContextData.cs b/src/ProxyInterfaceSourceGenerator/ContextData.cs
index 301062f..85fc823 100644
--- a/src/ProxyInterfaceSourceGenerator/ContextData.cs
+++ b/src/ProxyInterfaceSourceGenerator/ContextData.cs
@@ -1,13 +1,12 @@
using ProxyInterfaceSourceGenerator.FileGenerators;
-namespace ProxyInterfaceSourceGenerator
+namespace ProxyInterfaceSourceGenerator;
+
+internal record ContextData
{
- internal record ContextData
- {
- public string? InterfaceName { get; init; }
+ public string? InterfaceName { get; init; }
- public string? ClassName { get; init; }
+ public string? ClassName { get; init; }
- public FileData FileData { get; init; } = default!;
- }
+ public FileData FileData { get; init; } = default!;
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Enums/TypeEnum.cs b/src/ProxyInterfaceSourceGenerator/Enums/TypeEnum.cs
index 3ca55a9..14ae99f 100644
--- a/src/ProxyInterfaceSourceGenerator/Enums/TypeEnum.cs
+++ b/src/ProxyInterfaceSourceGenerator/Enums/TypeEnum.cs
@@ -1,11 +1,10 @@
-namespace ProxyInterfaceSourceGenerator.Enums
+namespace ProxyInterfaceSourceGenerator.Enums;
+
+internal enum TypeEnum
{
- internal enum TypeEnum
- {
- ValueTypeOrString,
+ ValueTypeOrString,
- Interface,
+ Interface,
- Complex
- }
+ Complex
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs
index 8ed0307..96826f2 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs
+++ b/src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs
@@ -1,14 +1,12 @@
-using System.Linq;
using Microsoft.CodeAnalysis;
-namespace ProxyInterfaceSourceGenerator.Extensions
-{
- internal static class MethodSymbolExtensions
- {
- public static string GetMethodNameWithOptionalTypeParameters(this IMethodSymbol method) =>
- !method.IsGenericMethod ? method.Name : $"{method.Name}<{string.Join(", ", method.TypeParameters.Select(tp => tp.Name))}>";
+namespace ProxyInterfaceSourceGenerator.Extensions;
- public static string GetWhereStatement(this IMethodSymbol method) =>
- !method.IsGenericMethod ? string.Empty : string.Join("", method.TypeParameters.Select(tp => tp.GetWhereStatement()));
- }
+internal static class MethodSymbolExtensions
+{
+ public static string GetMethodNameWithOptionalTypeParameters(this IMethodSymbol method) =>
+ !method.IsGenericMethod ? method.Name : $"{method.Name}<{string.Join(", ", method.TypeParameters.Select(tp => tp.Name))}>";
+
+ public static string GetWhereStatement(this IMethodSymbol method) =>
+ !method.IsGenericMethod ? string.Empty : string.Join("", method.TypeParameters.Select(tp => tp.GetWhereStatement()));
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/NamedTypeSymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/NamedTypeSymbolExtensions.cs
index 54369b7..db1dfa7 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/NamedTypeSymbolExtensions.cs
+++ b/src/ProxyInterfaceSourceGenerator/Extensions/NamedTypeSymbolExtensions.cs
@@ -1,57 +1,74 @@
-using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
-namespace ProxyInterfaceSourceGenerator.Extensions
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class NamedTypeSymbolExtensions
{
- internal static class NamedTypeSymbolExtensions
+ public static List GetBaseTypes(this INamedTypeSymbol? type)
{
- public static string GetFileName(this INamedTypeSymbol namedTypeSymbol)
+ var types = new List();
+
+ bool me = true;
+ while (type != null && type.SpecialType != SpecialType.System_Object)
{
- var typeName = namedTypeSymbol.GetFullType();
- return !(typeName.Contains('<') && typeName.Contains('>')) ?
- typeName :
- $"{typeName.Replace('.', '_').Replace('<', '_').Replace('>', '_').Replace(", ", "-")}_{typeName.Count(c => c == ',') + 1}";
- }
-
- public static string GetFullType(this INamedTypeSymbol namedTypeSymbol)
- {
- // https://www.codeproject.com/Articles/861548/Roslyn-Code-Analysis-in-Easy-Samples-Part
- //var str = new StringBuilder(namedTypeSymbol.Name);
-
- //if (namedTypeSymbol.TypeArguments.Count() > 0)
- //{
- // str.AppendFormat("<{0}>", string.Join(", ", namedTypeSymbol.TypeArguments.OfType().Select(typeArg => typeArg.GetFullType())));
- //}
-
- return namedTypeSymbol.OriginalDefinition.ToString();// str.ToString();
- }
-
- public static string ResolveInterfaceNameWithOptionalTypeConstraints(this INamedTypeSymbol namedTypeSymbol, string interfaceName)
- {
- if (!namedTypeSymbol.IsGenericType)
+ if (!me)
{
- return interfaceName;
+ types.Add(type);
}
- var str = new StringBuilder($"{interfaceName}<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>");
-
- foreach (var typeParameterSymbol in namedTypeSymbol.TypeArguments.OfType())
- {
- str.Append(typeParameterSymbol.GetWhereStatement());
- }
-
- return str.ToString();
+ type = type.BaseType;
+ me = false;
}
- ///
- /// See https://stackoverflow.com/questions/24157101/roslyns-gettypebymetadataname-and-generic-types
- ///
- public static string ResolveProxyClassName(this INamedTypeSymbol namedTypeSymbol)
+ return types;
+ }
+
+ public static string GetFileName(this INamedTypeSymbol namedTypeSymbol)
+ {
+ var typeName = namedTypeSymbol.GetFullType();
+ return !(typeName.Contains('<') && typeName.Contains('>')) ?
+ typeName :
+ $"{typeName.Replace('.', '_').Replace('<', '_').Replace('>', '_').Replace(", ", "-")}_{typeName.Count(c => c == ',') + 1}";
+ }
+
+ public static string GetFullType(this INamedTypeSymbol namedTypeSymbol)
+ {
+ // https://www.codeproject.com/Articles/861548/Roslyn-Code-Analysis-in-Easy-Samples-Part
+ //var str = new StringBuilder(namedTypeSymbol.Name);
+
+ //if (namedTypeSymbol.TypeArguments.Count() > 0)
+ //{
+ // str.AppendFormat("<{0}>", string.Join(", ", namedTypeSymbol.TypeArguments.OfType().Select(typeArg => typeArg.GetFullType())));
+ //}
+
+ return namedTypeSymbol.OriginalDefinition.ToString();// str.ToString();
+ }
+
+ public static string ResolveInterfaceNameWithOptionalTypeConstraints(this INamedTypeSymbol namedTypeSymbol, string interfaceName)
+ {
+ if (!namedTypeSymbol.IsGenericType)
{
- return !namedTypeSymbol.IsGenericType ?
- $"{namedTypeSymbol.Name}Proxy" :
- $"{namedTypeSymbol.Name}Proxy<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>";
+ return interfaceName;
}
+
+ var str = new StringBuilder($"{interfaceName}<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>");
+
+ foreach (var typeParameterSymbol in namedTypeSymbol.TypeArguments.OfType())
+ {
+ str.Append(typeParameterSymbol.GetWhereStatement());
+ }
+
+ return str.ToString();
+ }
+
+ ///
+ /// See https://stackoverflow.com/questions/24157101/roslyns-gettypebymetadataname-and-generic-types
+ ///
+ public static string ResolveProxyClassName(this INamedTypeSymbol namedTypeSymbol)
+ {
+ return !namedTypeSymbol.IsGenericType ?
+ $"{namedTypeSymbol.Name}Proxy" :
+ $"{namedTypeSymbol.Name}Proxy<{string.Join(", ", namedTypeSymbol.TypeArguments.Select(ta => ta.Name))}>";
}
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs
index 620fc44..7e4094f 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs
+++ b/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs
@@ -1,35 +1,34 @@
using Microsoft.CodeAnalysis;
using ProxyInterfaceSourceGenerator.Enums;
-namespace ProxyInterfaceSourceGenerator.Extensions
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class ParameterSymbolExtensions
{
- internal static class ParameterSymbolExtensions
+ public static string GetRefPrefix(this IParameterSymbol ps)
{
- public static string GetRefPrefix(this IParameterSymbol ps)
+ switch (ps.RefKind)
{
- switch (ps.RefKind)
- {
- case RefKind.In:
- return "in ";
+ case RefKind.In:
+ return "in ";
- case RefKind.Out:
- return "out ";
+ case RefKind.Out:
+ return "out ";
- case RefKind.Ref:
- return "ref ";
+ case RefKind.Ref:
+ return "ref ";
- default:
- return string.Empty;
- }
+ default:
+ return string.Empty;
}
-
- public static string GetParamsPrefix(this IParameterSymbol ps) =>
- ps.IsParams ? "params " : string.Empty;
-
- public static string GetDefaultValue(this IParameterSymbol ps) =>
- ps.HasExplicitDefaultValue ? $" = {ps.ExplicitDefaultValue}" : string.Empty;
-
- public static TypeEnum GetTypeEnum(this IParameterSymbol p) =>
- p.Type.GetTypeEnum();
}
+
+ public static string GetParamsPrefix(this IParameterSymbol ps) =>
+ ps.IsParams ? "params " : string.Empty;
+
+ public static string GetDefaultValue(this IParameterSymbol ps) =>
+ ps.HasExplicitDefaultValue ? $" = {ps.ExplicitDefaultValue}" : string.Empty;
+
+ public static TypeEnum GetTypeEnum(this IParameterSymbol p) =>
+ p.Type.GetTypeEnum();
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs
index 7a3ee6c..1fb24c9 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs
+++ b/src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs
@@ -1,37 +1,36 @@
using Microsoft.CodeAnalysis;
using ProxyInterfaceSourceGenerator.Enums;
-namespace ProxyInterfaceSourceGenerator.Extensions
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class PropertySymbolExtensions
{
- internal static class PropertySymbolExtensions
+ public static TypeEnum GetTypeEnum(this IPropertySymbol p) =>
+ p.Type.GetTypeEnum();
+
+ public static string ToPropertyText(this IPropertySymbol property, string? overrideType = null)
{
- public static TypeEnum GetTypeEnum(this IPropertySymbol p) =>
- p.Type.GetTypeEnum();
+ var get = property.GetMethod != null ? "get; " : string.Empty;
+ var set = property.SetMethod != null ? "set; " : string.Empty;
- public static string ToPropertyText(this IPropertySymbol property, string? overrideType = null)
- {
- var get = property.GetMethod != null ? "get; " : string.Empty;
- var set = property.SetMethod != null ? "set; " : string.Empty;
+ var type = !string.IsNullOrEmpty(overrideType) ? overrideType : $"{property.Type}";
- var type = !string.IsNullOrEmpty(overrideType) ? overrideType : $"{property.Type}";
+ return $"{type} {property.GetSanitizedName()} {{ {get}{set}}}";
+ }
- return $"{type} {property.GetSanitizedName()} {{ {get}{set}}}";
- }
+ public static string ToPropertyTextForClass(this IPropertySymbol property)
+ {
+ var get = property.GetMethod != null ? $"get => _Instance.{property.GetSanitizedName()}; " : string.Empty;
+ var set = property.SetMethod != null ? $"set => _Instance.{property.GetSanitizedName()} = value; " : string.Empty;
- public static string ToPropertyTextForClass(this IPropertySymbol property)
- {
- 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}}}";
+ }
- return $"{property.Type} {property.GetSanitizedName()} {{ {get}{set}}}";
- }
+ public static string ToPropertyTextForClass(this IPropertySymbol property, 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;
- public static string ToPropertyTextForClass(this IPropertySymbol property, 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;
-
- return $"{overrideType} {property.GetSanitizedName()} {{ {get}{set}}}";
- }
+ return $"{overrideType} {property.GetSanitizedName()} {{ {get}{set}}}";
}
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs
index 04699ef..f7b68ce 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs
+++ b/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs
@@ -1,14 +1,13 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-namespace ProxyInterfaceSourceGenerator.Extensions
-{
- internal static class SymbolExtensions
- {
- public static bool IsKeywordOrReserved(this ISymbol symbol) =>
- SyntaxFacts.GetKeywordKind(symbol.Name) != SyntaxKind.None || SyntaxFacts.GetContextualKeywordKind(symbol.Name) != SyntaxKind.None;
+namespace ProxyInterfaceSourceGenerator.Extensions;
- public static string GetSanitizedName(this ISymbol symbol) =>
- symbol.IsKeywordOrReserved() ? $"@{symbol.Name}" : symbol.Name;
- }
+internal static class SymbolExtensions
+{
+ public static bool IsKeywordOrReserved(this ISymbol symbol) =>
+ SyntaxFacts.GetKeywordKind(symbol.Name) != SyntaxKind.None || SyntaxFacts.GetContextualKeywordKind(symbol.Name) != SyntaxKind.None;
+
+ public static string GetSanitizedName(this ISymbol symbol) =>
+ symbol.IsKeywordOrReserved() ? $"@{symbol.Name}" : symbol.Name;
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/SyntaxNodeUtils.cs b/src/ProxyInterfaceSourceGenerator/Extensions/SyntaxNodeUtils.cs
index bb15b92..4aed807 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/SyntaxNodeUtils.cs
+++ b/src/ProxyInterfaceSourceGenerator/Extensions/SyntaxNodeUtils.cs
@@ -1,41 +1,40 @@
using Microsoft.CodeAnalysis;
using System.Diagnostics.CodeAnalysis;
-namespace ProxyInterfaceSourceGenerator.Extensions
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class SyntaxNodeUtils
{
- internal static class SyntaxNodeUtils
+ // https://stackoverflow.com/questions/20458457/getting-class-fullname-including-namespace-from-roslyn-classdeclarationsyntax
+ public static bool TryGetParentSyntax(this SyntaxNode? syntaxNode, [NotNullWhen(true)] out T? result) where T : SyntaxNode
{
- // https://stackoverflow.com/questions/20458457/getting-class-fullname-including-namespace-from-roslyn-classdeclarationsyntax
- public static bool TryGetParentSyntax(this SyntaxNode? syntaxNode, [NotNullWhen(true)] out T? result) where T : SyntaxNode
+ result = null;
+
+ if (syntaxNode is null)
{
- result = null;
+ return false;
+ }
+
+ try
+ {
+ syntaxNode = syntaxNode.Parent;
if (syntaxNode is null)
{
return false;
}
- try
+ if (syntaxNode.GetType() == typeof(T))
{
- syntaxNode = syntaxNode.Parent;
-
- if (syntaxNode is null)
- {
- return false;
- }
-
- if (syntaxNode.GetType() == typeof(T))
- {
- result = (T)syntaxNode;
- return true;
- }
-
- return TryGetParentSyntax(syntaxNode, out result);
- }
- catch
- {
- return false;
+ result = (T)syntaxNode;
+ return true;
}
+
+ return TryGetParentSyntax(syntaxNode, out result);
+ }
+ catch
+ {
+ return false;
}
}
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/TypeParameterSymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/TypeParameterSymbolExtensions.cs
index 154f83c..4ea595b 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/TypeParameterSymbolExtensions.cs
+++ b/src/ProxyInterfaceSourceGenerator/Extensions/TypeParameterSymbolExtensions.cs
@@ -1,40 +1,37 @@
-using System.Collections.Generic;
-using System.Linq;
using Microsoft.CodeAnalysis;
-namespace ProxyInterfaceSourceGenerator.Extensions
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class TypeParameterSymbolExtensions
{
- internal static class TypeParameterSymbolExtensions
+ ///
+ /// https://www.codeproject.com/Articles/871704/Roslyn-Code-Analysis-in-Easy-Samples-Part-2
+ ///
+ public static string GetWhereStatement(this ITypeParameterSymbol typeParameterSymbol)
{
- ///
- /// https://www.codeproject.com/Articles/871704/Roslyn-Code-Analysis-in-Easy-Samples-Part-2
- ///
- public static string GetWhereStatement(this ITypeParameterSymbol typeParameterSymbol)
+ var constraints = new List();
+ if (typeParameterSymbol.HasReferenceTypeConstraint)
{
- var constraints = new List();
- if (typeParameterSymbol.HasReferenceTypeConstraint)
- {
- constraints.Add("class");
- }
-
- if (typeParameterSymbol.HasValueTypeConstraint)
- {
- constraints.Add("struct");
- }
-
- if (typeParameterSymbol.HasConstructorConstraint)
- {
- constraints.Add("new()");
- }
-
- constraints.AddRange(typeParameterSymbol.ConstraintTypes.OfType().Select(contstraintType => contstraintType.GetFullType()));
-
- if (!constraints.Any())
- {
- return string.Empty;
- }
-
- return $" where {typeParameterSymbol.Name} : {string.Join(", ", constraints)}";
+ constraints.Add("class");
}
+
+ if (typeParameterSymbol.HasValueTypeConstraint)
+ {
+ constraints.Add("struct");
+ }
+
+ if (typeParameterSymbol.HasConstructorConstraint)
+ {
+ constraints.Add("new()");
+ }
+
+ constraints.AddRange(typeParameterSymbol.ConstraintTypes.OfType().Select(contstraintType => contstraintType.GetFullType()));
+
+ if (!constraints.Any())
+ {
+ return string.Empty;
+ }
+
+ return $" where {typeParameterSymbol.Name} : {string.Join(", ", constraints)}";
}
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/TypeSymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/TypeSymbolExtensions.cs
index 672cf3c..95761bb 100644
--- a/src/ProxyInterfaceSourceGenerator/Extensions/TypeSymbolExtensions.cs
+++ b/src/ProxyInterfaceSourceGenerator/Extensions/TypeSymbolExtensions.cs
@@ -1,28 +1,27 @@
using Microsoft.CodeAnalysis;
using ProxyInterfaceSourceGenerator.Enums;
-namespace ProxyInterfaceSourceGenerator.Extensions
+namespace ProxyInterfaceSourceGenerator.Extensions;
+
+internal static class TypeSymbolExtensions
{
- internal static class TypeSymbolExtensions
+ public static TypeEnum GetTypeEnum(this ITypeSymbol ts)
{
- public static TypeEnum GetTypeEnum(this ITypeSymbol ts)
+ if (ts.IsValueType || ts.IsString())
{
- if (ts.IsValueType || ts.IsString())
- {
- return TypeEnum.ValueTypeOrString;
- }
-
- if (ts.TypeKind == TypeKind.Interface)
- {
- return TypeEnum.Interface;
- }
-
- return TypeEnum.Complex;
+ return TypeEnum.ValueTypeOrString;
}
- public static bool IsString(this ITypeSymbol ts)
+ if (ts.TypeKind == TypeKind.Interface)
{
- return ts.ToString() == "string" || ts.ToString() == "string?";
+ return TypeEnum.Interface;
}
+
+ return TypeEnum.Complex;
+ }
+
+ public static bool IsString(this ITypeSymbol ts)
+ {
+ return ts.ToString() == "string" || ts.ToString() == "string?";
}
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs
index 5203738..619be08 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs
+++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs
@@ -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? usings = null)
+ return typeSymbolAsString;
+ }
+
+ protected ClassSymbol GetNamedTypeSymbolByFullName(string name, IEnumerable? 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.");
}
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/FileData.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/FileData.cs
index 8d85676..b86ee44 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/FileData.cs
+++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/FileData.cs
@@ -1,6 +1,3 @@
-namespace ProxyInterfaceSourceGenerator.FileGenerators
-{
- internal record FileData(string FileName, string Text)
- {
- }
-}
\ No newline at end of file
+namespace ProxyInterfaceSourceGenerator.FileGenerators;
+
+internal record FileData(string FileName, string Text);
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFileGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/IFileGenerator.cs
index 6c1b8dc..2a15607 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFileGenerator.cs
+++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/IFileGenerator.cs
@@ -1,7 +1,6 @@
-namespace ProxyInterfaceSourceGenerator.FileGenerators
+namespace ProxyInterfaceSourceGenerator.FileGenerators;
+
+internal interface IFileGenerator
{
- internal interface IFileGenerator
- {
- FileData GenerateFile();
- }
+ FileData GenerateFile();
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs
index 1219da8..eb4b764 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs
+++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs
@@ -1,9 +1,6 @@
-using System.Collections.Generic;
+namespace ProxyInterfaceSourceGenerator.FileGenerators;
-namespace ProxyInterfaceSourceGenerator.FileGenerators
+internal interface IFilesGenerator
{
- internal interface IFilesGenerator
- {
- IEnumerable GenerateFiles();
- }
+ IEnumerable GenerateFiles();
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs
index 87aa153..988ceee 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs
+++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs
@@ -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 GenerateFiles()
+ {
+ foreach (var ci in Context.CandidateInterfaces)
{
+ yield return GenerateFile(ci.Key, ci.Value);
}
+ }
- public IEnumerable 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) => $@"//----------------------------------------------------------------------------------------
//
// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
//
@@ -50,74 +50,73 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators
//
//----------------------------------------------------------------------------------------
-{(_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();
+ foreach (var ps in method.Parameters)
{
- var methodParameters = new List();
- 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();
}
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyAttributeGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyAttributeGenerator.cs
index ca91969..4accc18 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyAttributeGenerator.cs
+++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyAttributeGenerator.cs
@@ -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", $@"//----------------------------------------------------------------------------------------
//
// 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;
}}
}}
}}");
- }
}
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs
index c694c0e..9dde281 100644
--- a/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs
+++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/ProxyClassesGenerator.cs
@@ -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 GenerateFiles()
+ {
+ foreach (var ci in Context.CandidateInterfaces)
{
+ yield return GenerateFile(ci.Value);
}
+ }
- public IEnumerable 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) => $@"//----------------------------------------------------------------------------------------
//
// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
//
@@ -55,7 +52,7 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators
//
//----------------------------------------------------------------------------------------
-{(_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();
+ var invokeParameters = new List();
+
+ 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();
- var invokeParameters = new List();
-
- 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();
}
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Model/ClassSymbol.cs b/src/ProxyInterfaceSourceGenerator/Model/ClassSymbol.cs
new file mode 100644
index 0000000..06cfee2
--- /dev/null
+++ b/src/ProxyInterfaceSourceGenerator/Model/ClassSymbol.cs
@@ -0,0 +1,11 @@
+using Microsoft.CodeAnalysis;
+
+namespace ProxyInterfaceSourceGenerator.Model;
+
+internal record ClassSymbol(INamedTypeSymbol Symbol, List BaseTypes)
+{
+ public override string ToString()
+ {
+ return Symbol.ToString();
+ }
+}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs b/src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs
index 39b2800..2b3070a 100644
--- a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs
+++ b/src/ProxyInterfaceSourceGenerator/ProxyInterfaceCodeGenerator.cs
@@ -1,4 +1,3 @@
-using System;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
@@ -6,83 +5,95 @@ using Microsoft.CodeAnalysis.Text;
using ProxyInterfaceSourceGenerator.FileGenerators;
using ProxyInterfaceSourceGenerator.SyntaxReceiver;
-namespace ProxyInterfaceSourceGenerator
+namespace ProxyInterfaceSourceGenerator;
+
+[Generator]
+internal class ProxyInterfaceCodeGenerator : ISourceGenerator
{
- [Generator]
- internal class ProxyInterfaceCodeGenerator : ISourceGenerator
+ private readonly ProxyAttributeGenerator _proxyAttributeGenerator = new ProxyAttributeGenerator();
+
+ public void Initialize(GeneratorInitializationContext context)
{
- private readonly ProxyAttributeGenerator _proxyAttributeGenerator = new ProxyAttributeGenerator();
+ //if (!System.Diagnostics.Debugger.IsAttached)
+ //{
+ // System.Diagnostics.Debugger.Launch();
+ //}
- public void Initialize(GeneratorInitializationContext context)
+ context.RegisterForSyntaxNotifications(() => new ProxySyntaxReceiver());
+ }
+
+ public void Execute(GeneratorExecutionContext context)
+ {
+ if (context.ParseOptions is not CSharpParseOptions csharpParseOptions)
{
- //if (!System.Diagnostics.Debugger.IsAttached)
- //{
- // System.Diagnostics.Debugger.Launch();
- //}
-
- context.RegisterForSyntaxNotifications(() => new ProxySyntaxReceiver());
+ throw new NotSupportedException("Only C# is supported.");
}
- public void Execute(GeneratorExecutionContext context)
+ if (context.SyntaxReceiver is not ProxySyntaxReceiver receiver)
{
- if (context.ParseOptions is not CSharpParseOptions csharpParseOptions)
- {
- throw new NotSupportedException("Only C# is supported.");
- }
+ return;
+ }
- 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;
+ // https://github.com/reactiveui/refit/blob/main/InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
+ var supportsNullable = csharpParseOptions.LanguageVersion >= LanguageVersion.CSharp8;
+ try
+ {
GenerateProxyAttribute(context, receiver);
GeneratePartialInterfaces(context, receiver, supportsNullable);
GenerateProxyClasses(context, receiver, supportsNullable);
}
-
- private void GenerateProxyAttribute(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver)
+ catch (Exception exception)
{
- var context = new Context
- {
- GeneratorExecutionContext = ctx,
- CandidateInterfaces = receiver.CandidateInterfaces
- };
-
- var attributeData = _proxyAttributeGenerator.GenerateFile();
- context.GeneratorExecutionContext.AddSource(attributeData.FileName, SourceText.From(attributeData.Text, Encoding.UTF8));
+ GenerateError(context, exception);
}
+ }
- private static void GeneratePartialInterfaces(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable)
+ private void GenerateError(GeneratorExecutionContext context, Exception exception)
+ {
+ var message = $"/*\r\n{nameof(ProxyInterfaceCodeGenerator)}\r\n\r\n{exception}\r\n*/";
+ context.AddSource("Error.g", SourceText.From(message, Encoding.UTF8));
+ }
+
+ private void GenerateProxyAttribute(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver)
+ {
+ var context = new Context
{
- var context = new Context
- {
- GeneratorExecutionContext = ctx,
- CandidateInterfaces = receiver.CandidateInterfaces
- };
+ GeneratorExecutionContext = ctx,
+ CandidateInterfaces = receiver.CandidateInterfaces
+ };
- var partialInterfacesGenerator = new PartialInterfacesGenerator(context, supportsNullable);
- foreach (var data in partialInterfacesGenerator.GenerateFiles())
- {
- context.GeneratorExecutionContext.AddSource(data.FileName, SourceText.From(data.Text, Encoding.UTF8));
- }
+ var attributeData = _proxyAttributeGenerator.GenerateFile();
+ context.GeneratorExecutionContext.AddSource(attributeData.FileName, SourceText.From(attributeData.Text, Encoding.UTF8));
+ }
+
+ private static void GeneratePartialInterfaces(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable)
+ {
+ var context = new Context
+ {
+ GeneratorExecutionContext = ctx,
+ CandidateInterfaces = receiver.CandidateInterfaces
+ };
+
+ var partialInterfacesGenerator = new PartialInterfacesGenerator(context, supportsNullable);
+ foreach (var data in partialInterfacesGenerator.GenerateFiles())
+ {
+ context.GeneratorExecutionContext.AddSource(data.FileName, SourceText.From(data.Text, Encoding.UTF8));
}
+ }
- private static void GenerateProxyClasses(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable)
+ private static void GenerateProxyClasses(GeneratorExecutionContext ctx, ProxySyntaxReceiver receiver, bool supportsNullable)
+ {
+ var context = new Context
{
- var context = new Context
- {
- GeneratorExecutionContext = ctx,
- CandidateInterfaces = receiver.CandidateInterfaces
- };
+ GeneratorExecutionContext = ctx,
+ CandidateInterfaces = receiver.CandidateInterfaces
+ };
- var proxyClassesGenerator = new ProxyClassesGenerator(context, supportsNullable);
- foreach (var data in proxyClassesGenerator.GenerateFiles())
- {
- context.GeneratorExecutionContext.AddSource(data.FileName, SourceText.From(data.Text, Encoding.UTF8));
- }
+ var proxyClassesGenerator = new ProxyClassesGenerator(context, supportsNullable);
+ foreach (var data in proxyClassesGenerator.GenerateFiles())
+ {
+ context.GeneratorExecutionContext.AddSource(data.FileName, SourceText.From(data.Text, Encoding.UTF8));
}
}
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj b/src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj
index e827ecf..5a5b9e4 100644
--- a/src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj
+++ b/src/ProxyInterfaceSourceGenerator/ProxyInterfaceSourceGenerator.csproj
@@ -4,7 +4,7 @@
0.0.11
netstandard2.0
{12344228-91F4-4502-9595-39584E5ABB34}
- 9
+ 10
enable
Stef Heyenrath
@@ -24,6 +24,7 @@
true
$(BaseIntermediateOutputPath)Generated
true
+ enable
@@ -31,7 +32,7 @@
-
+
diff --git a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxyData.cs b/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxyData.cs
index 0965348..bd7a443 100644
--- a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxyData.cs
+++ b/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxyData.cs
@@ -1,8 +1,11 @@
-using System.Collections.Generic;
+namespace ProxyInterfaceSourceGenerator.SyntaxReceiver;
-namespace ProxyInterfaceSourceGenerator.SyntaxReceiver
-{
- internal record ProxyData(string Namespace, string InterfaceName, string RawTypeName, string TypeName, List Usings, bool ProxyAll)
- {
- }
-}
\ No newline at end of file
+internal record ProxyData
+(
+ string Namespace,
+ string InterfaceName,
+ string RawTypeName,
+ string TypeName,
+ List Usings,
+ bool ProxyBaseClasses
+);
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs b/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs
index 81f9d13..3adf2d2 100644
--- a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs
+++ b/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs
@@ -1,85 +1,91 @@
-using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using ProxyInterfaceSourceGenerator.Extensions;
-namespace ProxyInterfaceSourceGenerator.SyntaxReceiver
+namespace ProxyInterfaceSourceGenerator.SyntaxReceiver;
+
+internal class ProxySyntaxReceiver : ISyntaxReceiver
{
- internal class ProxySyntaxReceiver : ISyntaxReceiver
+ private static readonly string[] Modifiers = { "public", "partial" };
+
+ public IDictionary CandidateInterfaces { get; } = new Dictionary();
+
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
- private static readonly string[] Modifiers = new[] { "public", "partial" };
-
- public IDictionary CandidateInterfaces { get; } = new Dictionary();
-
- public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ if (syntaxNode is InterfaceDeclarationSyntax interfaceDeclarationSyntax && TryGet(interfaceDeclarationSyntax, out var data))
{
- if (syntaxNode is InterfaceDeclarationSyntax interfaceDeclarationSyntax && TryGet(interfaceDeclarationSyntax, out var data))
- {
- CandidateInterfaces.Add(interfaceDeclarationSyntax, data);
- }
- }
-
- private static bool TryGet(InterfaceDeclarationSyntax interfaceDeclarationSyntax, [NotNullWhen(true)] out ProxyData? data)
- {
- data = null;
-
- if (interfaceDeclarationSyntax.Modifiers.Select(m => m.ToString()).Except(Modifiers).Count() != 0)
- {
- // InterfaceDeclarationSyntax should be "public" and "partial"
- return false;
- }
-
- var attributeLists = interfaceDeclarationSyntax.AttributeLists.FirstOrDefault(x => x.Attributes.Any(a => a.Name.ToString().Equals("ProxyInterfaceGenerator.Proxy")));
- if (attributeLists is null)
- {
- return false;
- }
-
- var argumentList = attributeLists.Attributes.FirstOrDefault()?.ArgumentList;
- if (argumentList is null)
- {
- return false;
- }
-
- var usings = new List();
-
- string ns = string.Empty;
- if (SyntaxNodeUtils.TryGetParentSyntax(interfaceDeclarationSyntax, out NamespaceDeclarationSyntax? namespaceDeclarationSyntax))
- {
- ns = namespaceDeclarationSyntax.Name.ToString();
- usings.Add(ns);
- }
-
- if (SyntaxNodeUtils.TryGetParentSyntax(interfaceDeclarationSyntax, out CompilationUnitSyntax? cc))
- {
- foreach (var @using in cc.Usings)
- {
- usings.Add(@using.Name.ToString());
- }
- }
-
- string rawTypeName = ((TypeOfExpressionSyntax)argumentList.Arguments[0].Expression).Type.ToString();
-
- data = new
- (
- ns,
- interfaceDeclarationSyntax.Identifier.ToString(),
- rawTypeName,
- ConvertTypeName(rawTypeName),
- usings,
- false //bool.Parse(argumentList.Arguments[1].Expression.GetText().ToString())
- );
-
- return true;
- }
-
- private static string ConvertTypeName(string typeName)
- {
- return !(typeName.Contains('<') && typeName.Contains('>')) ?
- typeName :
- $"{typeName.Replace("<", string.Empty).Replace(">", string.Empty).Replace(",", string.Empty).Trim()}`{typeName.Count(c => c == ',') + 1}";
+ CandidateInterfaces.Add(interfaceDeclarationSyntax, data);
}
}
+
+ private static bool TryGet(InterfaceDeclarationSyntax interfaceDeclarationSyntax, [NotNullWhen(true)] out ProxyData? data)
+ {
+ data = null;
+
+ if (interfaceDeclarationSyntax.Modifiers.Select(m => m.ToString()).Except(Modifiers).Count() != 0)
+ {
+ // InterfaceDeclarationSyntax should be "public" and "partial"
+ return false;
+ }
+
+ var attributeLists = interfaceDeclarationSyntax.AttributeLists.FirstOrDefault(x => x.Attributes.Any(a => a.Name.ToString().Equals("ProxyInterfaceGenerator.Proxy")));
+ if (attributeLists is null)
+ {
+ return false;
+ }
+
+ var argumentList = attributeLists.Attributes.FirstOrDefault()?.ArgumentList;
+ if (argumentList is null)
+ {
+ return false;
+ }
+
+ var usings = new List();
+
+ string ns = string.Empty;
+ if (SyntaxNodeUtils.TryGetParentSyntax(interfaceDeclarationSyntax, out NamespaceDeclarationSyntax? namespaceDeclarationSyntax))
+ {
+ ns = namespaceDeclarationSyntax.Name.ToString();
+ usings.Add(ns);
+ }
+
+ if (SyntaxNodeUtils.TryGetParentSyntax(interfaceDeclarationSyntax, out CompilationUnitSyntax? cc))
+ {
+ foreach (var @using in cc.Usings)
+ {
+ usings.Add(@using.Name.ToString());
+ }
+ }
+
+ string rawTypeName = ((TypeOfExpressionSyntax)argumentList.Arguments[0].Expression).Type.ToString();
+ bool proxyAllClasses;
+ try
+ {
+ proxyAllClasses = bool.Parse(((LiteralExpressionSyntax)argumentList.Arguments[1].Expression).ToString());
+ }
+ catch
+ {
+ proxyAllClasses = false;
+ }
+
+ data = new
+ (
+ ns,
+ interfaceDeclarationSyntax.Identifier.ToString(),
+ rawTypeName,
+ ConvertTypeName(rawTypeName),
+ usings,
+ proxyAllClasses
+ );
+
+ return true;
+ }
+
+ private static string ConvertTypeName(string typeName)
+ {
+ return !(typeName.Contains('<') && typeName.Contains('>')) ?
+ typeName :
+ $"{typeName.Replace("<", string.Empty).Replace(">", string.Empty).Replace(",", string.Empty).Trim()}`{typeName.Count(c => c == ',') + 1}";
+ }
}
\ No newline at end of file
diff --git a/src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs b/src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs
index e49efec..486b2f6 100644
--- a/src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs
+++ b/src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs
@@ -1,87 +1,105 @@
using Microsoft.CodeAnalysis;
-using System;
-using System.Collections.Generic;
-using System.Linq;
+using ProxyInterfaceSourceGenerator.Model;
-namespace ProxyInterfaceSourceGenerator.Utils
+namespace ProxyInterfaceSourceGenerator.Utils;
+
+internal static class MemberHelper
{
- internal static class MemberHelper
+ private static readonly string[] ExcludedMethods = { "ToString", "GetHashCode" };
+
+ public static IEnumerable GetPublicProperties(
+ ClassSymbol classSymbol,
+ bool proxyBaseClasses,
+ params Func[] filters)
{
- private static string[] _excludedMethods = new string[] { "ToString", "GetHashCode" };
-
- public static IEnumerable GetPublicProperties(INamedTypeSymbol classSymbol, params Func[] filters)
+ var allFilters = new List>(filters)
{
- var allFilters = new List>(filters);
- allFilters.Add(p => p.Kind == SymbolKind.Property);
+ p => p.Kind == SymbolKind.Property
+ };
- return GetPublicMembers(classSymbol, allFilters.ToArray());
+ return GetPublicMembers(classSymbol, proxyBaseClasses, allFilters.ToArray());
+ }
+
+ public static IEnumerable GetPublicMethods(
+ ClassSymbol classSymbol,
+ bool proxyBaseClasses,
+ Func? filter = null)
+ {
+ if (filter is null)
+ {
+ filter = _ => true;
}
- public static IEnumerable GetPublicMethods(INamedTypeSymbol classSymbol, Func? filter = null)
- {
- if (filter is null)
- {
- filter = _ => true;
- }
+ return GetPublicMembers(classSymbol,
+ proxyBaseClasses,
+ m => m.Kind == SymbolKind.Method,
+ m => m.MethodKind == MethodKind.Ordinary,
+ m => !ExcludedMethods.Contains(m.Name),
+ filter);
+ }
- return GetPublicMembers(classSymbol,
- m => m.Kind == SymbolKind.Method,
- m => m.MethodKind == MethodKind.Ordinary,
- m => !_excludedMethods.Contains(m.Name),
- filter);
+ public static IEnumerable> GetPublicEvents(
+ ClassSymbol classSymbol,
+ bool proxyBaseClasses,
+ Func? filter = null)
+ {
+ if (filter is null)
+ {
+ filter = _ => true;
}
- public static IEnumerable> GetPublicEvents(INamedTypeSymbol classSymbol, Func? filter = null)
- {
- if (filter is null)
- {
- filter = _ => true;
- }
-
#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type.
#pragma warning disable RS1024 // Compare symbols correctly
- return GetPublicMembers(classSymbol,
+ return GetPublicMembers(classSymbol,
+ proxyBaseClasses,
m => m.MethodKind == MethodKind.EventAdd || m.MethodKind == MethodKind.EventRemove/* || m.MethodKind == MethodKind.EventRaise*/,
filter)
- .GroupBy(e => e.AssociatedSymbol);
+ .GroupBy(e => e.AssociatedSymbol);
#pragma warning restore RS1024 // Compare symbols correctly
#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type.
+ }
+
+ // TODO : do we need also to check for "SanitizedName()" here?
+ private static IEnumerable GetPublicMembers(
+ ClassSymbol classSymbol,
+ bool proxyBaseClasses,
+ params Func[] filters) where T : ISymbol
+ {
+ var membersQuery = classSymbol.Symbol.GetMembers().OfType()
+ .Where(m => m.DeclaredAccessibility == Accessibility.Public);
+
+ foreach (var filter in filters)
+ {
+ membersQuery = membersQuery.Where(filter);
}
- // TODO : do we need also to check for "SanitizedName()" here?
- private static IEnumerable GetPublicMembers(INamedTypeSymbol classSymbol, params Func[] filters) where T : ISymbol
+ var ownMembers = membersQuery.ToList();
+ var ownPropertyNames = ownMembers.Select(x => x.Name);
+
+ if (!proxyBaseClasses)
{
- var membersQuery = classSymbol.GetMembers().OfType()
- .Where(m => m.DeclaredAccessibility == Accessibility.Public);
+ return ownMembers;
+ }
+
+ var allMembers = ownMembers;
+ var baseType = classSymbol.Symbol.BaseType;
+
+ while (baseType != null && baseType.SpecialType != SpecialType.System_Object)
+ {
+ var baseMembers = baseType.GetMembers().OfType()
+ .Where(m => m.DeclaredAccessibility == Accessibility.Public)
+ .Where(x => !ownPropertyNames.Contains(x.Name));
foreach (var filter in filters)
{
- membersQuery = membersQuery.Where(filter);
+ baseMembers = baseMembers.Where(filter);
}
- var members = membersQuery.ToList();
+ allMembers.AddRange(baseMembers);
- var propertyNames = membersQuery.Select(x => x.Name);
-
- var baseType = classSymbol.BaseType;
-
- while (baseType != null)
- {
- var baseMembers = baseType.GetMembers().OfType()
- .Where(m => m.DeclaredAccessibility == Accessibility.Public)
- .Where(x => !propertyNames.Contains(x.Name));
-
- foreach (var filter in filters)
- {
- baseMembers = baseMembers.Where(filter);
- }
-
- members.AddRange(baseMembers);
-
- baseType = baseType.BaseType;
- }
-
- return membersQuery;
+ baseType = baseType.BaseType;
}
+
+ return allMembers;
}
}
\ No newline at end of file
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.HumanProxy.g.cs b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.HumanProxy.g.cs
new file mode 100644
index 0000000..3beaf96
--- /dev/null
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.HumanProxy.g.cs
@@ -0,0 +1,38 @@
+//----------------------------------------------------------------------------------------
+//
+// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//----------------------------------------------------------------------------------------
+
+#nullable enable
+using System;
+using AutoMapper;
+
+namespace ProxyInterfaceSourceGeneratorTests.Source
+{
+ public class HumanProxy : IHuman
+ {
+ public ProxyInterfaceSourceGeneratorTests.Source.Human _Instance { get; }
+
+ public bool IsAlive { get => _Instance.IsAlive; set => _Instance.IsAlive = value; }
+
+
+
+
+
+
+
+ public HumanProxy(ProxyInterfaceSourceGeneratorTests.Source.Human instance)
+ {
+ _Instance = instance;
+
+
+ }
+
+
+ }
+}
+#nullable disable
\ No newline at end of file
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.IHuman.g.cs b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.IHuman.g.cs
new file mode 100644
index 0000000..5c712c3
--- /dev/null
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.IHuman.g.cs
@@ -0,0 +1,26 @@
+//----------------------------------------------------------------------------------------
+//
+// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//----------------------------------------------------------------------------------------
+
+#nullable enable
+using System;
+
+namespace ProxyInterfaceSourceGeneratorTests.Source
+{
+ public partial interface IHuman
+ {
+ bool IsAlive { get; set; }
+
+
+
+
+
+
+ }
+}
+#nullable disable
\ No newline at end of file
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.DTO.IPerson.g.cs b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.IPerson.g.cs
similarity index 95%
rename from tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.DTO.IPerson.g.cs
rename to tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.IPerson.g.cs
index 69bdafe..bf16cf5 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.DTO.IPerson.g.cs
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.IPerson.g.cs
@@ -10,7 +10,7 @@
#nullable enable
using System;
-namespace ProxyInterfaceSourceGeneratorTests.DTO
+namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface IPerson
{
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.IPersonExtends.g.cs b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.IPersonExtends.g.cs
new file mode 100644
index 0000000..523ae49
--- /dev/null
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.IPersonExtends.g.cs
@@ -0,0 +1,56 @@
+//----------------------------------------------------------------------------------------
+//
+// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//----------------------------------------------------------------------------------------
+
+#nullable enable
+using System;
+
+namespace ProxyInterfaceSourceGeneratorTests.Source
+{
+ public partial interface IPersonExtends
+ {
+ string Name { get; set; }
+
+ string? StringNullable { get; set; }
+
+ long? NullableLong { get; }
+
+ object @object { get; set; }
+
+ bool IsAlive { get; set; }
+
+ bool X { get; set; }
+
+
+
+ void Void();
+
+ string HelloWorld(string name);
+
+ void WithParams(params string[] values);
+
+ string Add(string s, string @string);
+
+ int DefaultValue(int x = 100);
+
+ void In_Out_Ref1(in int a, out int b, ref int c);
+
+ bool Generic2(int x, T1 t1, T2 t2) where T1 : struct where T2 : class, new();
+
+ System.Threading.Tasks.Task Method1Async();
+
+ System.Threading.Tasks.Task Method2Async();
+
+ System.Threading.Tasks.Task Method3Async();
+
+
+
+
+ }
+}
+#nullable disable
\ No newline at end of file
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs
new file mode 100644
index 0000000..8bcce3f
--- /dev/null
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs
@@ -0,0 +1,117 @@
+//----------------------------------------------------------------------------------------
+//
+// This code was generated by https://github.com/StefH/ProxyInterfaceSourceGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//----------------------------------------------------------------------------------------
+
+#nullable enable
+using System;
+using AutoMapper;
+
+namespace ProxyInterfaceSourceGeneratorTests.Source
+{
+ public class PersonExtendsProxy : IPersonExtends
+ {
+ public ProxyInterfaceSourceGeneratorTests.Source.PersonExtends _Instance { get; }
+
+ public string Name { get => _Instance.Name; set => _Instance.Name = value; }
+
+ public string? StringNullable { get => _Instance.StringNullable; set => _Instance.StringNullable = value; }
+
+ public long? NullableLong { get => _Instance.NullableLong; }
+
+ public object @object { get => _Instance.@object; set => _Instance.@object = value; }
+
+ public bool IsAlive { get => _Instance.IsAlive; set => _Instance.IsAlive = value; }
+
+ public bool X { get => _Instance.X; set => _Instance.X = value; }
+
+
+
+ public void Void()
+ {
+ _Instance.Void();
+ }
+
+ public string HelloWorld(string name)
+ {
+ string name_ = name;
+ var result_58477331 = _Instance.HelloWorld(name_);
+ return result_58477331;
+ }
+
+ public void WithParams(params string[] values)
+ {
+ string[] values_ = values;
+ _Instance.WithParams(values_);
+ }
+
+ public string Add(string s, string @string)
+ {
+ string s_ = s;
+ string @string_ = @string;
+ var result_58477331 = _Instance.Add(s_, @string_);
+ return result_58477331;
+ }
+
+ public int DefaultValue(int x = 100)
+ {
+ int x_ = x;
+ var result_42930144 = _Instance.DefaultValue(x_);
+ return result_42930144;
+ }
+
+ public void In_Out_Ref1(in int a, out int b, ref int c)
+ {
+ int a_ = a;
+ int b_;
+ int c_ = c;
+ _Instance.In_Out_Ref1(in a_, out b_, ref c_);
+ b = b_;
+ }
+
+ public bool Generic2(int x, T1 t1, T2 t2) where T1 : struct where T2 : class, new()
+ {
+ int x_ = x;
+ T1 t1_ = t1;
+ T2 t2_ = t2;
+ var result_38995950 = _Instance.Generic2(x_, t1_, t2_);
+ return result_38995950;
+ }
+
+ public System.Threading.Tasks.Task Method1Async()
+ {
+ var result_51708797 = _Instance.Method1Async();
+ return result_51708797;
+ }
+
+ public System.Threading.Tasks.Task Method2Async()
+ {
+ var result_1620952573 = _Instance.Method2Async();
+ return result_1620952573;
+ }
+
+ public System.Threading.Tasks.Task Method3Async()
+ {
+ var result_1636499760 = _Instance.Method3Async();
+ return result_1636499760;
+ }
+
+
+
+
+
+ public PersonExtendsProxy(ProxyInterfaceSourceGeneratorTests.Source.PersonExtends instance)
+ {
+ _Instance = instance;
+
+
+ }
+
+
+ }
+}
+#nullable disable
\ No newline at end of file
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.DTO.PersonProxy.g.cs b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonProxy.g.cs
similarity index 55%
rename from tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.DTO.PersonProxy.g.cs
rename to tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonProxy.g.cs
index 1fa560a..8025ed0 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.DTO.PersonProxy.g.cs
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Destination/ProxyInterfaceSourceGeneratorTests.Source.PersonProxy.g.cs
@@ -11,11 +11,11 @@
using System;
using AutoMapper;
-namespace ProxyInterfaceSourceGeneratorTests.DTO
+namespace ProxyInterfaceSourceGeneratorTests.Source
{
public class PersonProxy : IPerson
{
- public ProxyInterfaceSourceGeneratorTests.DTO.Person _Instance { get; }
+ public ProxyInterfaceSourceGeneratorTests.Source.Person _Instance { get; }
public string Name { get => _Instance.Name; set => _Instance.Name = value; }
@@ -29,78 +29,78 @@ namespace ProxyInterfaceSourceGeneratorTests.DTO
public void Void()
{
- _Instance.Void();
+ _Instance.Void();
}
public string HelloWorld(string name)
{
- string name_ = name;
- var result_15289640 = _Instance.HelloWorld(name_);
- return result_15289640;
+ string name_ = name;
+ var result_56365455 = _Instance.HelloWorld(name_);
+ return result_56365455;
}
public void WithParams(params string[] values)
{
- string[] values_ = values;
- _Instance.WithParams(values_);
+ string[] values_ = values;
+ _Instance.WithParams(values_);
}
public string Add(string s, string @string)
{
- string s_ = s;
- string @string_ = @string;
- var result_15289640 = _Instance.Add(s_, @string_);
- return result_15289640;
+ string s_ = s;
+ string @string_ = @string;
+ var result_56365455 = _Instance.Add(s_, @string_);
+ return result_56365455;
}
public int DefaultValue(int x = 100)
{
- int x_ = x;
- var result_54302544 = _Instance.DefaultValue(x_);
- return result_54302544;
+ int x_ = x;
+ var result_39875940 = _Instance.DefaultValue(x_);
+ return result_39875940;
}
public void In_Out_Ref1(in int a, out int b, ref int c)
{
- int a_ = a;
- int b_;
- int c_ = c;
- _Instance.In_Out_Ref1(in a_, out b_, ref c_);
- b = b_;
+ int a_ = a;
+ int b_;
+ int c_ = c;
+ _Instance.In_Out_Ref1(in a_, out b_, ref c_);
+ b = b_;
}
public bool Generic2(int x, T1 t1, T2 t2) where T1 : struct where T2 : class, new()
{
- int x_ = x;
- T1 t1_ = t1;
- T2 t2_ = t2;
- var result_40004473 = _Instance.Generic2(x_, t1_, t2_);
- return result_40004473;
+ int x_ = x;
+ T1 t1_ = t1;
+ T2 t2_ = t2;
+ var result_41799290 = _Instance.Generic2(x_, t1_, t2_);
+ return result_41799290;
}
public System.Threading.Tasks.Task Method1Async()
{
- var result_50153955 = _Instance.Method1Async();
- return result_50153955;
+ var result_32599313 = _Instance.Method1Async();
+ return result_32599313;
}
public System.Threading.Tasks.Task Method2Async()
{
- var result_1151242754 = _Instance.Method2Async();
- return result_1151242754;
+ var result_1620495907 = _Instance.Method2Async();
+ return result_1620495907;
}
public System.Threading.Tasks.Task Method3Async()
{
- var result_1190255658 = _Instance.Method3Async();
- return result_1190255658;
+ var result_1604006392 = _Instance.Method3Async();
+ return result_1604006392;
}
- public PersonProxy(ProxyInterfaceSourceGeneratorTests.DTO.Person instance)
+ public PersonProxy(ProxyInterfaceSourceGeneratorTests.Source.Person instance)
{
_Instance = instance;
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs
index 40b74bd..c291b0b 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs
+++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTest.cs
@@ -1,14 +1,18 @@
+using System.Collections.Generic;
using System.IO;
+using AnyOfTypes;
using CSharp.SourceGenerators.Extensions;
using CSharp.SourceGenerators.Extensions.Models;
using FluentAssertions;
using ProxyInterfaceSourceGenerator;
using Xunit;
-namespace FluentBuilderGeneratorTests
+namespace ProxyInterfaceSourceGeneratorTests
{
public class ProxyInterfaceSourceGeneratorTest
{
+ private bool Write = true;
+
private readonly ProxyInterfaceCodeGenerator _sut;
public ProxyInterfaceSourceGeneratorTest()
@@ -21,10 +25,10 @@ namespace FluentBuilderGeneratorTests
{
// Arrange
var attributeFilename = "ProxyInterfaceGenerator.ProxyAttribute.g.cs";
- var interfaceFilename = "ProxyInterfaceSourceGeneratorTests.DTO.IPerson.g.cs";
- var proxyClassFilename = "ProxyInterfaceSourceGeneratorTests.DTO.PersonProxy.g.cs";
+ var interfaceFilename = "ProxyInterfaceSourceGeneratorTests.Source.IPersonExtends.g.cs";
+ var proxyClassFilename = "ProxyInterfaceSourceGeneratorTests.Source.PersonExtendsProxy.g.cs";
- var path = "./Source/IPerson.cs";
+ var path = "./Source/IPersonExtends.cs";
var sourceFile = new SourceFile
{
Path = path,
@@ -32,7 +36,7 @@ namespace FluentBuilderGeneratorTests
AttributeToAddToInterface = new ExtraAttribute
{
Name = "ProxyInterfaceGenerator.Proxy",
- ArgumentList = "typeof(ProxyInterfaceSourceGeneratorTests.DTO.Person)"
+ ArgumentList = new [] { "typeof(ProxyInterfaceSourceGeneratorTests.Source.PersonExtends)", "true" }
}
};
@@ -43,16 +47,16 @@ namespace FluentBuilderGeneratorTests
result.Valid.Should().BeTrue();
result.Files.Should().HaveCount(3);
- // Assert interface
- var @attribute = result.Files[0].SyntaxTree;
- @attribute.FilePath.Should().EndWith(attributeFilename);
+ // Assert attribute
+ var attribute = result.Files[0].SyntaxTree;
+ attribute.FilePath.Should().EndWith(attributeFilename);
// Assert interface
var @interface = result.Files[1].SyntaxTree;
@interface.FilePath.Should().EndWith(interfaceFilename);
var interfaceCode = @interface.ToString();
- File.WriteAllText($"../../../Destination/{interfaceFilename}", interfaceCode);
+ if (Write) File.WriteAllText($"../../../Destination/{interfaceFilename}", interfaceCode);
interfaceCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{interfaceFilename}"));
// Assert Proxy
@@ -60,8 +64,90 @@ namespace FluentBuilderGeneratorTests
proxyClass.FilePath.Should().EndWith(proxyClassFilename);
var proxyCode = proxyClass.ToString();
- File.WriteAllText($"../../../Destination/{proxyClassFilename}", proxyCode);
+ if (Write) File.WriteAllText($"../../../Destination/{proxyClassFilename}", proxyCode);
proxyCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassFilename}"));
}
+
+ [Fact]
+ public void GenerateFiles_ForTwoClasses_Should_GenerateCorrectFiles()
+ {
+ // Arrange
+ var attributeFilename = "ProxyInterfaceGenerator.ProxyAttribute.g.cs";
+ var interfaceHumanFilename = "ProxyInterfaceSourceGeneratorTests.Source.IHuman.g.cs";
+ var proxyClassHumanFilename = "ProxyInterfaceSourceGeneratorTests.Source.HumanProxy.g.cs";
+ var interfacePersonFilename = "ProxyInterfaceSourceGeneratorTests.Source.IPerson.g.cs";
+ var proxyClassPersonFilename = "ProxyInterfaceSourceGeneratorTests.Source.PersonProxy.g.cs";
+
+ var pathPerson = "./Source/IPerson.cs";
+ var sourceFilePerson = new SourceFile
+ {
+ Path = pathPerson,
+ Text = File.ReadAllText(pathPerson),
+ AttributeToAddToInterface = new ExtraAttribute
+ {
+ Name = "ProxyInterfaceGenerator.Proxy",
+ ArgumentList = "typeof(ProxyInterfaceSourceGeneratorTests.Source.Person)"
+ }
+ };
+
+ var pathHuman = "./Source/IHuman.cs";
+ var sourceFileHuman = new SourceFile
+ {
+ Path = pathHuman,
+ Text = File.ReadAllText(pathHuman),
+ AttributeToAddToInterface = new ExtraAttribute
+ {
+ Name = "ProxyInterfaceGenerator.Proxy",
+ ArgumentList = "typeof(ProxyInterfaceSourceGeneratorTests.Source.Human)"
+ }
+ };
+
+ // Act
+ var result = _sut.Execute(new[] { sourceFileHuman, sourceFilePerson });
+
+ // Assert
+ result.Valid.Should().BeTrue();
+ result.Files.Should().HaveCount(5);
+
+ // Assert attribute
+ var attribute = result.Files[0].SyntaxTree;
+ attribute.FilePath.Should().EndWith(attributeFilename);
+
+
+ // Assert interface Human
+ var interfaceHuman = result.Files[1].SyntaxTree;
+ interfaceHuman.FilePath.Should().EndWith(interfaceHumanFilename);
+
+ var interfaceCodeHuman = interfaceHuman.ToString();
+ if (Write) File.WriteAllText($"../../../Destination/{interfaceHumanFilename}", interfaceCodeHuman);
+ interfaceCodeHuman.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{interfaceHumanFilename}"));
+
+
+ // Assert interface Person
+ var interfacePerson = result.Files[2].SyntaxTree;
+ interfacePerson.FilePath.Should().EndWith(interfacePersonFilename);
+
+ var interfaceCodePerson = interfacePerson.ToString();
+ if (Write) File.WriteAllText($"../../../Destination/{interfacePersonFilename}", interfaceCodePerson);
+ interfaceCodePerson.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{interfacePersonFilename}"));
+
+
+ // Assert Proxy Human
+ var proxyClassHuman = result.Files[3].SyntaxTree;
+ proxyClassHuman.FilePath.Should().EndWith(proxyClassHumanFilename);
+
+ var proxyCodeHuman = proxyClassHuman.ToString();
+ if (Write) File.WriteAllText($"../../../Destination/{proxyClassHumanFilename}", proxyCodeHuman);
+ proxyCodeHuman.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassHumanFilename}"));
+
+
+ // Assert Proxy Person
+ var proxyClassPerson = result.Files[4].SyntaxTree;
+ proxyClassPerson.FilePath.Should().EndWith(proxyClassPersonFilename);
+
+ var proxyCode = proxyClassPerson.ToString();
+ if (Write) File.WriteAllText($"../../../Destination/{proxyClassPersonFilename}", proxyCode);
+ proxyCode.Should().NotBeNullOrEmpty().And.Be(File.ReadAllText($"../../../Destination/{proxyClassPersonFilename}"));
+ }
}
}
\ No newline at end of file
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj
index 975143a..aa629d4 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj
+++ b/tests/ProxyInterfaceSourceGeneratorTests/ProxyInterfaceSourceGeneratorTests.csproj
@@ -8,11 +8,6 @@
false
-
-
-
-
-
@@ -32,22 +27,29 @@
-
+
-
- PreserveNewest
-
-
- PreserveNewest
-
-
-
-
-
-
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
\ No newline at end of file
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/Human.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/Human.cs
new file mode 100644
index 0000000..05eeaae
--- /dev/null
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/Human.cs
@@ -0,0 +1,12 @@
+namespace ProxyInterfaceSourceGeneratorTests.Source
+{
+ public class Human : Animal
+ {
+ public bool IsAlive { get; set; }
+ }
+
+ public class Animal
+ {
+ public bool X { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/IHuman.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/IHuman.cs
new file mode 100644
index 0000000..22ba8b1
--- /dev/null
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/IHuman.cs
@@ -0,0 +1,6 @@
+namespace ProxyInterfaceSourceGeneratorTests.Source
+{
+ public partial interface IHuman
+ {
+ }
+}
\ No newline at end of file
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/IPerson.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/IPerson.cs
index 45e7781..7ca6065 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/Source/IPerson.cs
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/IPerson.cs
@@ -1,4 +1,4 @@
-namespace ProxyInterfaceSourceGeneratorTests.DTO
+namespace ProxyInterfaceSourceGeneratorTests.Source
{
public partial interface IPerson
{
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/IPersonExtends.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/IPersonExtends.cs
new file mode 100644
index 0000000..8d37a42
--- /dev/null
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/IPersonExtends.cs
@@ -0,0 +1,6 @@
+namespace ProxyInterfaceSourceGeneratorTests.Source
+{
+ public partial interface IPersonExtends
+ {
+ }
+}
\ No newline at end of file
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs
index bf38d53..66d430d 100644
--- a/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/Person.cs
@@ -1,6 +1,6 @@
using System.Threading.Tasks;
-namespace ProxyInterfaceSourceGeneratorTests.DTO
+namespace ProxyInterfaceSourceGeneratorTests.Source
{
public class Person
{
diff --git a/tests/ProxyInterfaceSourceGeneratorTests/Source/PersonExtends.cs b/tests/ProxyInterfaceSourceGeneratorTests/Source/PersonExtends.cs
new file mode 100644
index 0000000..712898a
--- /dev/null
+++ b/tests/ProxyInterfaceSourceGeneratorTests/Source/PersonExtends.cs
@@ -0,0 +1,65 @@
+using System.Threading.Tasks;
+
+namespace ProxyInterfaceSourceGeneratorTests.Source
+{
+ public class PersonExtends : Human
+ {
+ public string Name { get; set; }
+
+ public string? StringNullable { get; set; }
+
+ public long? NullableLong { get; }
+
+ public object @object { get; set; }
+
+ public void Void()
+ {
+ }
+
+ public string HelloWorld(string name)
+ {
+ return $"Hello {name} !";
+ }
+
+ public void WithParams(params string[] values)
+ {
+ }
+
+ public string Add(string s, string @string)
+ {
+ return s + @string;
+ }
+
+ public int DefaultValue(int x = 100)
+ {
+ return x + 1;
+ }
+
+ public void In_Out_Ref1(in int a, out int b, ref int c)
+ {
+ b = 1;
+ }
+
+ public bool Generic2(int x, T1 t1, T2 t2)
+ where T1 : struct
+ where T2 : class, new()
+ {
+ return true;
+ }
+
+ public Task Method1Async()
+ {
+ return Task.CompletedTask;
+ }
+
+ public Task Method2Async()
+ {
+ return Task.FromResult(1);
+ }
+
+ public Task Method3Async()
+ {
+ return Task.FromResult((string?)"");
+ }
+ }
+}
\ No newline at end of file