Add support for using a simple type-name (#22)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
namespace ProxyInterfaceConsumer
|
||||
namespace DifferentNamespace
|
||||
{
|
||||
public class Address
|
||||
{
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
namespace ProxyInterfaceConsumer
|
||||
using DifferentNamespace;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace ProxyInterfaceConsumer
|
||||
{
|
||||
// [ProxyInterfaceGenerator.Proxy(typeof(ProxyInterfaceConsumer.Address))]
|
||||
[ProxyInterfaceGenerator.Proxy(typeof(Address))]
|
||||
public partial interface IAddress
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using DifferentNamespace;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ProxyInterfaceConsumer
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// https://stackoverflow.com/questions/61573959/how-to-resolve-error-notnullwhen-attribute-is-inaccessible-due-to-its-protectio
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter will not be null even if the corresponding type allows it.</summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
|
||||
internal sealed class NotNullWhenAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes the attribute with the specified return value condition.</summary>
|
||||
/// <param name="returnValue">
|
||||
/// The return value condition. If the method returns this value, the associated parameter will not be null.
|
||||
/// </param>
|
||||
public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
|
||||
|
||||
/// <summary>Gets the return value condition.</summary>
|
||||
public bool ReturnValue { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
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<T>(this SyntaxNode? syntaxNode, out T? result) where T : SyntaxNode
|
||||
public static bool TryGetParentSyntax<T>(this SyntaxNode? syntaxNode, [NotNullWhen(true)] out T? result) where T : SyntaxNode
|
||||
{
|
||||
result = null;
|
||||
|
||||
@@ -25,7 +26,7 @@ namespace ProxyInterfaceSourceGenerator.Extensions
|
||||
|
||||
if (syntaxNode.GetType() == typeof(T))
|
||||
{
|
||||
result = syntaxNode as T;
|
||||
result = (T)syntaxNode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
@@ -67,16 +68,28 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
return typeSymbolAsString;
|
||||
}
|
||||
|
||||
protected INamedTypeSymbol GetNamedTypeSymbolByFullName(string fullName)
|
||||
protected INamedTypeSymbol GetNamedTypeSymbolByFullName(string name, IEnumerable<string>? usings = null)
|
||||
{
|
||||
// The GetTypeByMetadataName method returns null if no type matches the full name or if 2 or more types (in different assemblies) match the full name.
|
||||
var symbol = _context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName(fullName);
|
||||
if (symbol is null)
|
||||
{
|
||||
throw new Exception($"The type '{fullName}' is not found.");
|
||||
var symbol = _context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName(name);
|
||||
if (symbol is not null)
|
||||
{
|
||||
return symbol;
|
||||
}
|
||||
|
||||
if (usings is not null)
|
||||
{
|
||||
foreach (var @using in usings)
|
||||
{
|
||||
symbol = _context.GeneratorExecutionContext.Compilation.GetTypeByMetadataName($"{@using}.{name}");
|
||||
if (symbol is not null)
|
||||
{
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return symbol;
|
||||
throw new Exception($"The type '{name}' is not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
|
||||
private FileData GenerateFile(ProxyData pd)
|
||||
{
|
||||
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName);
|
||||
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName, pd.Usings);
|
||||
var interfaceName = targetClassSymbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.InterfaceName);
|
||||
|
||||
var file = new FileData(
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace ProxyInterfaceSourceGenerator.FileGenerators
|
||||
|
||||
private FileData GenerateFile(ProxyData pd)
|
||||
{
|
||||
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName);
|
||||
var targetClassSymbol = GetNamedTypeSymbolByFullName(pd.TypeName, pd.Usings);
|
||||
var interfaceName = targetClassSymbol.ResolveInterfaceNameWithOptionalTypeConstraints(pd.InterfaceName);
|
||||
var className = targetClassSymbol.ResolveProxyClassName();
|
||||
var constructorName = $"{targetClassSymbol.Name}Proxy";
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
namespace ProxyInterfaceSourceGenerator.SyntaxReceiver
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ProxyInterfaceSourceGenerator.SyntaxReceiver
|
||||
{
|
||||
internal record ProxyData(string Namespace, string InterfaceName, string RawTypeName, string TypeName, bool ProxyAll)
|
||||
internal record ProxyData(string Namespace, string InterfaceName, string RawTypeName, string TypeName, List<string> Usings, bool ProxyAll)
|
||||
{
|
||||
public string FileName => TypeName.Replace('.', '_').Replace('`', '_');
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
@@ -20,9 +21,9 @@ namespace ProxyInterfaceSourceGenerator.SyntaxReceiver
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryGet(InterfaceDeclarationSyntax interfaceDeclarationSyntax, out ProxyData data)
|
||||
private static bool TryGet(InterfaceDeclarationSyntax interfaceDeclarationSyntax, [NotNullWhen(true)] out ProxyData? data)
|
||||
{
|
||||
data = new(string.Empty, string.Empty, string.Empty, string.Empty, false);
|
||||
data = null;
|
||||
|
||||
if (interfaceDeclarationSyntax.Modifiers.Select(m => m.ToString()).Except(Modifiers).Count() != 0)
|
||||
{
|
||||
@@ -42,27 +43,39 @@ namespace ProxyInterfaceSourceGenerator.SyntaxReceiver
|
||||
return false;
|
||||
}
|
||||
|
||||
var usings = new List<string>();
|
||||
|
||||
string ns = string.Empty;
|
||||
if (SyntaxNodeUtils.TryGetParentSyntax(interfaceDeclarationSyntax, out NamespaceDeclarationSyntax namespaceDeclarationSyntax))
|
||||
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();
|
||||
string rawTypeName = ((TypeOfExpressionSyntax)argumentList.Arguments[0].Expression).Type.ToString();
|
||||
|
||||
data = new
|
||||
(
|
||||
ns,
|
||||
interfaceDeclarationSyntax.Identifier.ToString(),
|
||||
rawTypename,
|
||||
ResolveType(rawTypename),
|
||||
rawTypeName,
|
||||
ConvertTypeName(rawTypeName),
|
||||
usings,
|
||||
false //bool.Parse(argumentList.Arguments[1].Expression.GetText().ToString())
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string ResolveType(string typeName)
|
||||
private static string ConvertTypeName(string typeName)
|
||||
{
|
||||
return !(typeName.Contains('<') && typeName.Contains('>')) ?
|
||||
typeName :
|
||||
|
||||
Reference in New Issue
Block a user