diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0d64ba1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +[*] +indent_style = space +indent_size = 4 +end_of_line = crlf +charset = utf-8 +trim_trailing_whitespace = true \ No newline at end of file diff --git a/ProxyInterfaceSourceGenerator Solution.sln b/ProxyInterfaceSourceGenerator Solution.sln index f915b17..b7fd5e6 100644 --- a/ProxyInterfaceSourceGenerator Solution.sln +++ b/ProxyInterfaceSourceGenerator Solution.sln @@ -1,55 +1,56 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31515.178 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED3DA9DD-1E07-444B-A2D7-2DBA280F96D4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2CE637DC-E8F5-4603-8B57-E51A32F631F1}" - ProjectSection(SolutionItems) = preProject - GitHubReleaseNotes.txt = GitHubReleaseNotes.txt - README.md = README.md - ReleaseNotes.md = ReleaseNotes.md - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{19009F5B-3267-45E2-A8B6-89F2AB47D72C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src-examples", "src-examples", "{38BA087F-EDA1-4F8A-A140-85B84791B815}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceSourceGenerator", "src\ProxyInterfaceSourceGenerator\ProxyInterfaceSourceGenerator.csproj", "{12344228-91F4-4502-9595-39584E5ABB34}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumer", "src-examples\ProxyInterfaceConsumer\ProxyInterfaceConsumer.csproj", "{7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProxyInterfaceConsumerViaNuGet", "src-examples\ProxyInterfaceConsumerViaNuGet\ProxyInterfaceConsumerViaNuGet.csproj", "{6BEBFEB9-635F-44A2-949C-15DDDF0B7740}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {12344228-91F4-4502-9595-39584E5ABB34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {12344228-91F4-4502-9595-39584E5ABB34}.Debug|Any CPU.Build.0 = Debug|Any CPU - {12344228-91F4-4502-9595-39584E5ABB34}.Release|Any CPU.ActiveCfg = Release|Any CPU - {12344228-91F4-4502-9595-39584E5ABB34}.Release|Any CPU.Build.0 = Release|Any CPU - {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Release|Any CPU.Build.0 = Release|Any CPU - {6BEBFEB9-635F-44A2-949C-15DDDF0B7740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BEBFEB9-635F-44A2-949C-15DDDF0B7740}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6BEBFEB9-635F-44A2-949C-15DDDF0B7740}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6BEBFEB9-635F-44A2-949C-15DDDF0B7740}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {12344228-91F4-4502-9595-39584E5ABB34} = {ED3DA9DD-1E07-444B-A2D7-2DBA280F96D4} - {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9} = {38BA087F-EDA1-4F8A-A140-85B84791B815} - {6BEBFEB9-635F-44A2-949C-15DDDF0B7740} = {38BA087F-EDA1-4F8A-A140-85B84791B815} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {585F071D-051D-441C-9C6B-226D9E15A1F5} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31521.260 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED3DA9DD-1E07-444B-A2D7-2DBA280F96D4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2CE637DC-E8F5-4603-8B57-E51A32F631F1}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + GitHubReleaseNotes.txt = GitHubReleaseNotes.txt + README.md = README.md + ReleaseNotes.md = ReleaseNotes.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{19009F5B-3267-45E2-A8B6-89F2AB47D72C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src-examples", "src-examples", "{38BA087F-EDA1-4F8A-A140-85B84791B815}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceSourceGenerator", "src\ProxyInterfaceSourceGenerator\ProxyInterfaceSourceGenerator.csproj", "{12344228-91F4-4502-9595-39584E5ABB34}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumer", "src-examples\ProxyInterfaceConsumer\ProxyInterfaceConsumer.csproj", "{7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyInterfaceConsumerViaNuGet", "src-examples\ProxyInterfaceConsumerViaNuGet\ProxyInterfaceConsumerViaNuGet.csproj", "{6BEBFEB9-635F-44A2-949C-15DDDF0B7740}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {12344228-91F4-4502-9595-39584E5ABB34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {12344228-91F4-4502-9595-39584E5ABB34}.Debug|Any CPU.Build.0 = Debug|Any CPU + {12344228-91F4-4502-9595-39584E5ABB34}.Release|Any CPU.ActiveCfg = Release|Any CPU + {12344228-91F4-4502-9595-39584E5ABB34}.Release|Any CPU.Build.0 = Release|Any CPU + {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9}.Release|Any CPU.Build.0 = Release|Any CPU + {6BEBFEB9-635F-44A2-949C-15DDDF0B7740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6BEBFEB9-635F-44A2-949C-15DDDF0B7740}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6BEBFEB9-635F-44A2-949C-15DDDF0B7740}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6BEBFEB9-635F-44A2-949C-15DDDF0B7740}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {12344228-91F4-4502-9595-39584E5ABB34} = {ED3DA9DD-1E07-444B-A2D7-2DBA280F96D4} + {7E0A10EE-CCC3-4281-9541-B0AF037D3DF9} = {38BA087F-EDA1-4F8A-A140-85B84791B815} + {6BEBFEB9-635F-44A2-949C-15DDDF0B7740} = {38BA087F-EDA1-4F8A-A140-85B84791B815} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {585F071D-051D-441C-9C6B-226D9E15A1F5} + EndGlobalSection +EndGlobal diff --git a/src/ProxyInterfaceSourceGenerator/Compatibility/IsExternalInit.cs b/src/ProxyInterfaceSourceGenerator/Compatibility/IsExternalInit.cs index 83c76ea..53b909b 100644 --- a/src/ProxyInterfaceSourceGenerator/Compatibility/IsExternalInit.cs +++ b/src/ProxyInterfaceSourceGenerator/Compatibility/IsExternalInit.cs @@ -1,7 +1,7 @@ -// https://bartwullems.blogspot.com/2021/01/c-9use-record-types-in-net-standard-20.html -#if NETSTANDARD2_0 -namespace System.Runtime.CompilerServices -{ - public class IsExternalInit { } -} +// https://bartwullems.blogspot.com/2021/01/c-9use-record-types-in-net-standard-20.html +#if NETSTANDARD2_0 +namespace System.Runtime.CompilerServices +{ + public class IsExternalInit { } +} #endif \ No newline at end of file diff --git a/src/ProxyInterfaceSourceGenerator/Context.cs b/src/ProxyInterfaceSourceGenerator/Context.cs index d8b7e6b..8c7b67b 100644 --- a/src/ProxyInterfaceSourceGenerator/Context.cs +++ b/src/ProxyInterfaceSourceGenerator/Context.cs @@ -1,18 +1,18 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using ProxyInterfaceSourceGenerator.SyntaxReceiver; - -namespace ProxyInterfaceSourceGenerator -{ - internal record Context - { - public GeneratorExecutionContext GeneratorExecutionContext { get; init; } - - // public List GeneratedData { get; } = new List(); - - public IDictionary CandidateInterfaces { get; init; } - - public Dictionary ReplacedTypes { get; } = new Dictionary(); -} +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using ProxyInterfaceSourceGenerator.SyntaxReceiver; + +namespace ProxyInterfaceSourceGenerator +{ + internal record Context + { + public GeneratorExecutionContext GeneratorExecutionContext { get; init; } + + // public List GeneratedData { get; } = new List(); + + public IDictionary CandidateInterfaces { get; init; } + + 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 8fb4220..df25eb5 100644 --- a/src/ProxyInterfaceSourceGenerator/ContextData.cs +++ b/src/ProxyInterfaceSourceGenerator/ContextData.cs @@ -1,13 +1,13 @@ -using ProxyInterfaceSourceGenerator.FileGenerators; - -namespace ProxyInterfaceSourceGenerator -{ - internal record ContextData - { - public string? InterfaceName { get; init; } - - public string? ClassName { get; init; } - - public FileData FileData { get; init; } - } +using ProxyInterfaceSourceGenerator.FileGenerators; + +namespace ProxyInterfaceSourceGenerator +{ + internal record ContextData + { + public string? InterfaceName { get; init; } + + public string? ClassName { get; init; } + + public FileData FileData { get; init; } + } } \ No newline at end of file diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs index cfd03a6..8ed0307 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/MethodSymbolExtensions.cs @@ -1,14 +1,14 @@ -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))}>"; - - public static string GetWhereStatement(this IMethodSymbol method) => - !method.IsGenericMethod ? string.Empty : string.Join("", method.TypeParameters.Select(tp => tp.GetWhereStatement())); - } +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))}>"; + + 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 239e11f..71647a6 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/NamedTypeSymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/NamedTypeSymbolExtensions.cs @@ -1,52 +1,51 @@ -using System; -using System.Linq; -using System.Text; -using Microsoft.CodeAnalysis; - -namespace ProxyInterfaceSourceGenerator.Extensions -{ - internal static class NamedTypeSymbolExtensions - { - /// - /// See https://www.codeproject.com/Articles/861548/Roslyn-Code-Analysis-in-Easy-Samples-Part - /// - public static string GetFullTypeString(this INamedTypeSymbol namedTypeSymbol) - { - var str = new StringBuilder(namedTypeSymbol.Name); - - if (namedTypeSymbol.TypeArguments.Count() > 0) - { - str.AppendFormat("<{0}>", string.Join(", ", namedTypeSymbol.TypeArguments.OfType().Select(typeArg => typeArg.GetFullTypeString()))); - } - - return str.ToString(); - } - - public static string ResolveInterfaceNameWithOptionalTypeConstraints(this INamedTypeSymbol namedTypeSymbol, string interfaceName) - { - if (!namedTypeSymbol.IsGenericType) - { - 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))}>"; - } - } +using Microsoft.CodeAnalysis; +using System.Linq; +using System.Text; + +namespace ProxyInterfaceSourceGenerator.Extensions +{ + internal static class NamedTypeSymbolExtensions + { + /// + /// See https://www.codeproject.com/Articles/861548/Roslyn-Code-Analysis-in-Easy-Samples-Part + /// + public static string GetFullTypeString(this INamedTypeSymbol namedTypeSymbol) + { + var str = new StringBuilder(namedTypeSymbol.Name); + + if (namedTypeSymbol.TypeArguments.Count() > 0) + { + str.AppendFormat("<{0}>", string.Join(", ", namedTypeSymbol.TypeArguments.OfType().Select(typeArg => typeArg.GetFullTypeString()))); + } + + return str.ToString(); + } + + public static string ResolveInterfaceNameWithOptionalTypeConstraints(this INamedTypeSymbol namedTypeSymbol, string interfaceName) + { + if (!namedTypeSymbol.IsGenericType) + { + 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 d352c8e..620fc44 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/ParameterSymbolExtensions.cs @@ -1,35 +1,35 @@ -using Microsoft.CodeAnalysis; -using ProxyInterfaceSourceGenerator.Enums; - -namespace ProxyInterfaceSourceGenerator.Extensions -{ - internal static class ParameterSymbolExtensions - { - public static string GetRefPrefix(this IParameterSymbol ps) - { - switch (ps.RefKind) - { - case RefKind.In: - return "in "; - - case RefKind.Out: - return "out "; - - case RefKind.Ref: - return "ref "; - - 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(); - } +using Microsoft.CodeAnalysis; +using ProxyInterfaceSourceGenerator.Enums; + +namespace ProxyInterfaceSourceGenerator.Extensions +{ + internal static class ParameterSymbolExtensions + { + public static string GetRefPrefix(this IParameterSymbol ps) + { + switch (ps.RefKind) + { + case RefKind.In: + return "in "; + + case RefKind.Out: + return "out "; + + case RefKind.Ref: + return "ref "; + + 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(); + } } \ No newline at end of file diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs index e86665e..7a3ee6c 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/PropertySymbolExtensions.cs @@ -1,37 +1,37 @@ -using Microsoft.CodeAnalysis; -using ProxyInterfaceSourceGenerator.Enums; - -namespace ProxyInterfaceSourceGenerator.Extensions -{ - internal static class PropertySymbolExtensions - { - public static TypeEnum GetTypeEnum(this IPropertySymbol p) => - p.Type.GetTypeEnum(); - - 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}"; - - 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; - - 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; - - return $"{overrideType} {property.GetSanitizedName()} {{ {get}{set}}}"; - } - } +using Microsoft.CodeAnalysis; +using ProxyInterfaceSourceGenerator.Enums; + +namespace ProxyInterfaceSourceGenerator.Extensions +{ + internal static class PropertySymbolExtensions + { + public static TypeEnum GetTypeEnum(this IPropertySymbol p) => + p.Type.GetTypeEnum(); + + 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}"; + + 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; + + 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; + + 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 9d37eca..04699ef 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/SymbolExtensions.cs @@ -1,14 +1,14 @@ -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; - - public static string GetSanitizedName(this ISymbol symbol) => - symbol.IsKeywordOrReserved() ? $"@{symbol.Name}" : symbol.Name; - } +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; + + 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 a8bed5e..bb15b92 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/SyntaxNodeUtils.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/SyntaxNodeUtils.cs @@ -1,41 +1,41 @@ -using Microsoft.CodeAnalysis; -using System.Diagnostics.CodeAnalysis; - -namespace ProxyInterfaceSourceGenerator.Extensions -{ - 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 - { - result = null; - - if (syntaxNode is null) - { - return false; - } - - try - { - 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; - } - } - } +using Microsoft.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; + +namespace ProxyInterfaceSourceGenerator.Extensions +{ + 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 + { + result = null; + + if (syntaxNode is null) + { + return false; + } + + try + { + 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; + } + } + } } \ No newline at end of file diff --git a/src/ProxyInterfaceSourceGenerator/Extensions/TypeParameterSymbolExtensions.cs b/src/ProxyInterfaceSourceGenerator/Extensions/TypeParameterSymbolExtensions.cs index eb764d1..40fde56 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/TypeParameterSymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/TypeParameterSymbolExtensions.cs @@ -1,40 +1,40 @@ -using System.Collections.Generic; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace ProxyInterfaceSourceGenerator.Extensions -{ - 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) - { - 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.GetFullTypeString())); - - if (!constraints.Any()) - { - return string.Empty; - } - - return $" where {typeParameterSymbol.Name} : {string.Join(", ", constraints)}"; - } - } +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace ProxyInterfaceSourceGenerator.Extensions +{ + 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) + { + 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.GetFullTypeString())); + + 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 247c7ae..672cf3c 100644 --- a/src/ProxyInterfaceSourceGenerator/Extensions/TypeSymbolExtensions.cs +++ b/src/ProxyInterfaceSourceGenerator/Extensions/TypeSymbolExtensions.cs @@ -1,28 +1,28 @@ -using Microsoft.CodeAnalysis; -using ProxyInterfaceSourceGenerator.Enums; - -namespace ProxyInterfaceSourceGenerator.Extensions -{ - internal static class TypeSymbolExtensions - { - public static TypeEnum GetTypeEnum(this ITypeSymbol ts) - { - if (ts.IsValueType || ts.IsString()) - { - return TypeEnum.ValueTypeOrString; - } - - if (ts.TypeKind == TypeKind.Interface) - { - return TypeEnum.Interface; - } - - return TypeEnum.Complex; - } - - public static bool IsString(this ITypeSymbol ts) - { - return ts.ToString() == "string" || ts.ToString() == "string?"; - } - } +using Microsoft.CodeAnalysis; +using ProxyInterfaceSourceGenerator.Enums; + +namespace ProxyInterfaceSourceGenerator.Extensions +{ + internal static class TypeSymbolExtensions + { + public static TypeEnum GetTypeEnum(this ITypeSymbol ts) + { + if (ts.IsValueType || ts.IsString()) + { + return TypeEnum.ValueTypeOrString; + } + + if (ts.TypeKind == TypeKind.Interface) + { + 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 a570541..b58dae3 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/BaseGenerator.cs @@ -1,77 +1,77 @@ -using System; +using System; using System.Collections.Generic; -using System.Linq; -using Microsoft.CodeAnalysis; - -namespace ProxyInterfaceSourceGenerator.FileGenerators -{ - internal abstract class BaseGenerator - { - protected readonly Context _context; - - public BaseGenerator(Context context) - { - _context = context; - } - - 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)) - { - _context.ReplacedTypes.Add(typeSymbolAsString, existing.InterfaceName); - } - - isReplaced = true; - return existing.InterfaceName; - } - - if (typeSymbol is INamedTypeSymbol namedTypedSymbol) - { - 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) - { - isReplaced = true; - - if (!_context.ReplacedTypes.ContainsKey(typeArgumentAsString)) - { - _context.ReplacedTypes.Add(typeArgumentAsString, exist.InterfaceName); - } - - propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, exist.InterfaceName); - } - } - - return propertyTypeAsStringToBeModified; - } - - return typeSymbolAsString; - } - - protected INamedTypeSymbol 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); +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace ProxyInterfaceSourceGenerator.FileGenerators +{ + internal abstract class BaseGenerator + { + protected readonly Context _context; + + public BaseGenerator(Context context) + { + _context = context; + } + + 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)) + { + _context.ReplacedTypes.Add(typeSymbolAsString, existing.InterfaceName); + } + + isReplaced = true; + return existing.InterfaceName; + } + + if (typeSymbol is INamedTypeSymbol namedTypedSymbol) + { + 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) + { + isReplaced = true; + + if (!_context.ReplacedTypes.ContainsKey(typeArgumentAsString)) + { + _context.ReplacedTypes.Add(typeArgumentAsString, exist.InterfaceName); + } + + propertyTypeAsStringToBeModified = propertyTypeAsStringToBeModified.Replace(typeArgumentAsString, exist.InterfaceName); + } + } + + return propertyTypeAsStringToBeModified; + } + + return typeSymbolAsString; + } + + protected INamedTypeSymbol 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) { return symbol; @@ -86,10 +86,10 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators { return symbol; } - } - } - - 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 387e286..8d85676 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/FileData.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/FileData.cs @@ -1,6 +1,6 @@ -namespace ProxyInterfaceSourceGenerator.FileGenerators -{ - internal record FileData(string FileName, string Text) - { - } +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 d719b8f..6c1b8dc 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFileGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/IFileGenerator.cs @@ -1,7 +1,7 @@ -namespace ProxyInterfaceSourceGenerator.FileGenerators -{ - internal interface IFileGenerator - { - FileData GenerateFile(); - } +namespace ProxyInterfaceSourceGenerator.FileGenerators +{ + internal interface IFileGenerator + { + FileData GenerateFile(); + } } \ No newline at end of file diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs index b41a808..1219da8 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/IFilesGenerator.cs @@ -1,9 +1,9 @@ -using System.Collections.Generic; - -namespace ProxyInterfaceSourceGenerator.FileGenerators -{ - internal interface IFilesGenerator - { - IEnumerable GenerateFiles(); - } +using System.Collections.Generic; + +namespace ProxyInterfaceSourceGenerator.FileGenerators +{ + internal interface IFilesGenerator + { + IEnumerable GenerateFiles(); + } } \ No newline at end of file diff --git a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs b/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs index ee422dc..7845034 100644 --- a/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs +++ b/src/ProxyInterfaceSourceGenerator/FileGenerators/PartialInterfacesGenerator.cs @@ -1,11 +1,10 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text; using Microsoft.CodeAnalysis; using ProxyInterfaceSourceGenerator.Enums; using ProxyInterfaceSourceGenerator.Extensions; using ProxyInterfaceSourceGenerator.SyntaxReceiver; using ProxyInterfaceSourceGenerator.Utils; +using System.Collections.Generic; +using System.Text; namespace ProxyInterfaceSourceGenerator.FileGenerators { @@ -83,7 +82,7 @@ namespace {ns} 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(); } diff --git a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxyData.cs b/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxyData.cs index 9729900..11c9039 100644 --- a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxyData.cs +++ b/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxyData.cs @@ -1,9 +1,9 @@ -using System.Collections.Generic; +using System.Collections.Generic; -namespace ProxyInterfaceSourceGenerator.SyntaxReceiver -{ - internal record ProxyData(string Namespace, string InterfaceName, string RawTypeName, string TypeName, List Usings, bool ProxyAll) - { - public string FileName => TypeName.Replace('.', '_').Replace('`', '_'); - } +namespace ProxyInterfaceSourceGenerator.SyntaxReceiver +{ + internal record ProxyData(string Namespace, string InterfaceName, string RawTypeName, string TypeName, List Usings, bool ProxyAll) + { + public string FileName => TypeName.Replace('.', '_').Replace('`', '_'); + } } \ No newline at end of file diff --git a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs b/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs index 0047e60..81f9d13 100644 --- a/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs +++ b/src/ProxyInterfaceSourceGenerator/SyntaxReceiver/ProxySyntaxReceiver.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis; @@ -51,7 +51,7 @@ namespace ProxyInterfaceSourceGenerator.SyntaxReceiver ns = namespaceDeclarationSyntax.Name.ToString(); usings.Add(ns); } - + if (SyntaxNodeUtils.TryGetParentSyntax(interfaceDeclarationSyntax, out CompilationUnitSyntax? cc)) { foreach (var @using in cc.Usings) diff --git a/src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs b/src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs index e9701fe..cbdf2b2 100644 --- a/src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs +++ b/src/ProxyInterfaceSourceGenerator/Utils/MemberHelper.cs @@ -1,70 +1,70 @@ -using Microsoft.CodeAnalysis; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace ProxyInterfaceSourceGenerator.Utils -{ - internal static class MemberHelper - { - private static string[] _excludedMethods = new string[] { "ToString", "GetHashCode" }; - - public static IEnumerable GetPublicProperties(INamedTypeSymbol classSymbol, params Func[] filters) - { - var allFilters = new List>(filters); - allFilters.Add(p => p.Kind == SymbolKind.Property); - - return GetPublicMembers(classSymbol, allFilters.ToArray()); - } - - public static IEnumerable GetPublicMethods(INamedTypeSymbol classSymbol, Func? filter = null) - { - if (filter is null) - { - filter = _ => true; - } - - return GetPublicMembers(classSymbol, - m => m.Kind == SymbolKind.Method, - m => m.MethodKind == MethodKind.Ordinary, - m => !_excludedMethods.Contains(m.Name), - filter); - } - - // TODO : do we need also to check for "SanitizedName()" here? - private static IEnumerable GetPublicMembers(INamedTypeSymbol classSymbol, params Func[] filters) where T : ISymbol - { - var membersQuery = classSymbol.GetMembers().OfType() - .Where(m => m.DeclaredAccessibility == Accessibility.Public); - - foreach (var filter in filters) - { - membersQuery = membersQuery.Where(filter); - } - - var members = membersQuery.ToList(); - - 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; - } - } +using Microsoft.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ProxyInterfaceSourceGenerator.Utils +{ + internal static class MemberHelper + { + private static string[] _excludedMethods = new string[] { "ToString", "GetHashCode" }; + + public static IEnumerable GetPublicProperties(INamedTypeSymbol classSymbol, params Func[] filters) + { + var allFilters = new List>(filters); + allFilters.Add(p => p.Kind == SymbolKind.Property); + + return GetPublicMembers(classSymbol, allFilters.ToArray()); + } + + public static IEnumerable GetPublicMethods(INamedTypeSymbol classSymbol, Func? filter = null) + { + if (filter is null) + { + filter = _ => true; + } + + return GetPublicMembers(classSymbol, + m => m.Kind == SymbolKind.Method, + m => m.MethodKind == MethodKind.Ordinary, + m => !_excludedMethods.Contains(m.Name), + filter); + } + + // TODO : do we need also to check for "SanitizedName()" here? + private static IEnumerable GetPublicMembers(INamedTypeSymbol classSymbol, params Func[] filters) where T : ISymbol + { + var membersQuery = classSymbol.GetMembers().OfType() + .Where(m => m.DeclaredAccessibility == Accessibility.Public); + + foreach (var filter in filters) + { + membersQuery = membersQuery.Where(filter); + } + + var members = membersQuery.ToList(); + + 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; + } + } } \ No newline at end of file