Merge pull request #4 from YaslePoy/codegen-refactoring
Codegen refactoring
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using mROA.CodegenTools;
|
||||||
|
|
||||||
|
namespace mROA.Codegen
|
||||||
|
{
|
||||||
|
public static class TemplateDocumentExtensions
|
||||||
|
{
|
||||||
|
public static TemplateDocument CloneInnerTemplate(this TemplateDocument template, string tag)
|
||||||
|
{
|
||||||
|
var innerTemplate = template[tag] as InnerTemplateSection
|
||||||
|
?? throw new InvalidOperationException();
|
||||||
|
var clone = innerTemplate.InnerTemplate.Clone();
|
||||||
|
return (TemplateDocument)clone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using mROA.CodegenTools;
|
||||||
|
|
||||||
|
namespace mROA.Codegen.Templates
|
||||||
|
{
|
||||||
|
public class EventBinderTemplate : TemplateView
|
||||||
|
{
|
||||||
|
private const string CallFilterTag = "callFilter";
|
||||||
|
private const string TypeTag = "type";
|
||||||
|
private const string EventNameTag = "eventName";
|
||||||
|
private const string ParametersDeclarationTag = "parametersDeclaration";
|
||||||
|
private const string CommandIdTag = "commandId";
|
||||||
|
private const string TransferParametersTag = "transferParameters";
|
||||||
|
|
||||||
|
public EventBinderTemplate(TemplateDocument template) : base(template) { }
|
||||||
|
|
||||||
|
public void DefineCallFilter(string value)
|
||||||
|
{
|
||||||
|
Define(CallFilterTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineType(string value)
|
||||||
|
{
|
||||||
|
Define(TypeTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineEventName(string value)
|
||||||
|
{
|
||||||
|
Define(EventNameTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineParametersDeclaration(string value)
|
||||||
|
{
|
||||||
|
Define(ParametersDeclarationTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineCommandIdTag(string value)
|
||||||
|
{
|
||||||
|
Define(CommandIdTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineTransferParameters(string value)
|
||||||
|
{
|
||||||
|
Define(TransferParametersTag, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
namespace mROA.Codegen.Templates
|
||||||
|
{
|
||||||
|
public class IndexProviderTemplate : TemplateView
|
||||||
|
{
|
||||||
|
private const string TemplateFile = "IndexProvider.cstmpl";
|
||||||
|
|
||||||
|
private const string NamespaceTag = "namespace";
|
||||||
|
private const string LevelTag = "level";
|
||||||
|
private const string LenTag = "len";
|
||||||
|
private const string IndexSpanTag = "indexSpan";
|
||||||
|
private const string RemoteTypePairTag = "remoteTypePair";
|
||||||
|
|
||||||
|
public IndexProviderTemplate() : base(TemplateFile) { }
|
||||||
|
|
||||||
|
public void DefineNamespace(string value)
|
||||||
|
{
|
||||||
|
Define(NamespaceTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineLevel(string value)
|
||||||
|
{
|
||||||
|
Define(LevelTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineLen(string value)
|
||||||
|
{
|
||||||
|
Define(LenTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InsertIndexSpan(string value)
|
||||||
|
{
|
||||||
|
Insert(IndexSpanTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InsertRemoteTypePair(string value)
|
||||||
|
{
|
||||||
|
Insert(RemoteTypePairTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRemoteTypePairInserted()
|
||||||
|
{
|
||||||
|
return Inserted(RemoteTypePairTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using mROA.CodegenTools;
|
||||||
|
|
||||||
|
namespace mROA.Codegen.Templates
|
||||||
|
{
|
||||||
|
public class InvokerTemplate : TemplateView
|
||||||
|
{
|
||||||
|
private const string IsVoidTag = "isVoid";
|
||||||
|
private const string ReturnTypeTag = "returnType";
|
||||||
|
private const string ParametersTypeTag = "parametersType";
|
||||||
|
private const string SuitableTypeTag = "suitableType";
|
||||||
|
private const string FuncInvokingTag = "funcInvoking";
|
||||||
|
private const string IsTrustedTag = "isTrusted";
|
||||||
|
|
||||||
|
public InvokerTemplate(TemplateDocument template) : base(template) { }
|
||||||
|
|
||||||
|
public void DefineIsVoid(string value)
|
||||||
|
{
|
||||||
|
Define(IsVoidTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineReturnType(string value)
|
||||||
|
{
|
||||||
|
Define(ReturnTypeTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineParametersType(string value)
|
||||||
|
{
|
||||||
|
Define(ParametersTypeTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineSuitableType(string value)
|
||||||
|
{
|
||||||
|
Define(SuitableTypeTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineFuncInvoking(string value)
|
||||||
|
{
|
||||||
|
Define(FuncInvokingTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineIsTrusted(string value)
|
||||||
|
{
|
||||||
|
Define(IsTrustedTag, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
namespace mROA.Codegen.Templates
|
||||||
|
{
|
||||||
|
public class MethodRepoTemplate : TemplateView
|
||||||
|
{
|
||||||
|
private const string TemplateFile = "MethodRepo.cstmpl";
|
||||||
|
|
||||||
|
private const string SyncInvokerTemplate = "syncInvoker";
|
||||||
|
private const string AsyncInvokerTemplate = "asyncInvoker";
|
||||||
|
|
||||||
|
private const string InvokerTag = "invoker";
|
||||||
|
|
||||||
|
public MethodRepoTemplate() : base(TemplateFile) { }
|
||||||
|
|
||||||
|
public void InsertInvoke(string value)
|
||||||
|
{
|
||||||
|
Insert(InvokerTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvokerTemplate CloneInnerSyncInvoker()
|
||||||
|
{
|
||||||
|
var template = CloneInner(SyncInvokerTemplate);
|
||||||
|
return new InvokerTemplate(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvokerTemplate CloneInnerAsyncInvoker()
|
||||||
|
{
|
||||||
|
var template = CloneInner(AsyncInvokerTemplate);
|
||||||
|
return new InvokerTemplate(template);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using mROA.CodegenTools;
|
||||||
|
|
||||||
|
namespace mROA.Codegen.Templates
|
||||||
|
{
|
||||||
|
public partial class ObjectBinderTemplate : TemplateView
|
||||||
|
{
|
||||||
|
private const string EventBinderTemplateTag = "eventBinderTemplate";
|
||||||
|
|
||||||
|
private const string TypeTag = "type";
|
||||||
|
private const string EventBinderTag = "eventBinder";
|
||||||
|
|
||||||
|
public ObjectBinderTemplate(TemplateDocument template) : base(template) { }
|
||||||
|
|
||||||
|
public void DefineType(string value)
|
||||||
|
{
|
||||||
|
Define(TypeTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InsertEventBinder(string value)
|
||||||
|
{
|
||||||
|
Insert(EventBinderTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventBinderTemplate CloneInnerEventBinder()
|
||||||
|
{
|
||||||
|
var template = CloneInner(EventBinderTemplateTag);
|
||||||
|
return new EventBinderTemplate(template);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
namespace mROA.Codegen.Templates
|
||||||
|
{
|
||||||
|
public class PartialInterfaceTemplate : TemplateView
|
||||||
|
{
|
||||||
|
private const string TemplateFile = "PartialInterface.cstmpl";
|
||||||
|
|
||||||
|
private const string NameTag = "name";
|
||||||
|
private const string NamespaceTag = "namespace";
|
||||||
|
private const string SignatureTag = "signature";
|
||||||
|
|
||||||
|
public PartialInterfaceTemplate() : base(TemplateFile) { }
|
||||||
|
|
||||||
|
public void DefineName(string value)
|
||||||
|
{
|
||||||
|
Define(NameTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineNamespace(string value)
|
||||||
|
{
|
||||||
|
Define(NamespaceTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InsertSignature(string value)
|
||||||
|
{
|
||||||
|
Insert(SignatureTag, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
namespace mROA.Codegen.Templates
|
||||||
|
{
|
||||||
|
public class ProxyTemplate : TemplateView
|
||||||
|
{
|
||||||
|
private const string TemplateFile = "Proxy.cstmpl";
|
||||||
|
|
||||||
|
private const string ClassNameTag = "className";
|
||||||
|
private const string OriginalNameTag = "originalName";
|
||||||
|
private const string NamespaceNameTag= "namespaceName";
|
||||||
|
private const string MethodsTag = "methods";
|
||||||
|
|
||||||
|
public ProxyTemplate() : base(TemplateFile) { }
|
||||||
|
|
||||||
|
public void DefineClassName(string value)
|
||||||
|
{
|
||||||
|
Define(ClassNameTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineOriginalName(string value)
|
||||||
|
{
|
||||||
|
Define(OriginalNameTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineNamespaceName(string value)
|
||||||
|
{
|
||||||
|
Define(NamespaceNameTag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InsertMethods(string value)
|
||||||
|
{
|
||||||
|
Insert(MethodsTag, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
namespace mROA.Codegen.Templates
|
||||||
|
{
|
||||||
|
public class RemoteTypeBinderTemplate : TemplateView
|
||||||
|
{
|
||||||
|
private const string TemplateFile = "RemoteTypeBinder.cstmpl";
|
||||||
|
|
||||||
|
private const string ObjectBinderTemplateTag = "objectBinderTemplate";
|
||||||
|
private const string EventBinderTag = "eventBinder";
|
||||||
|
|
||||||
|
public RemoteTypeBinderTemplate() : base(TemplateFile) { }
|
||||||
|
|
||||||
|
public ObjectBinderTemplate CloneInnerObjectBinder()
|
||||||
|
{
|
||||||
|
var template = CloneInner(ObjectBinderTemplateTag);
|
||||||
|
return new ObjectBinderTemplate(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InsertEventBinder(string value)
|
||||||
|
{
|
||||||
|
Insert(EventBinderTag, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using mROA.CodegenTools;
|
||||||
|
using mROA.CodegenTools.Reading;
|
||||||
|
|
||||||
|
namespace mROA.Codegen.Templates
|
||||||
|
{
|
||||||
|
public abstract class TemplateView
|
||||||
|
{
|
||||||
|
private readonly TemplateDocument _template;
|
||||||
|
|
||||||
|
protected TemplateView(string templateFile)
|
||||||
|
{
|
||||||
|
_template = TemplateReader.FromEmbeddedResource(templateFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TemplateView(TemplateDocument template)
|
||||||
|
{
|
||||||
|
_template = template;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Compile()
|
||||||
|
{
|
||||||
|
return _template.Compile();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Define(string tag, string value)
|
||||||
|
{
|
||||||
|
_template.AddDefine(tag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Insert(string tag, string value)
|
||||||
|
{
|
||||||
|
_template.Insert(tag, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool Inserted(string tag)
|
||||||
|
{
|
||||||
|
return _template[$"{tag}+"] != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TemplateDocument CloneInner(string tag)
|
||||||
|
{
|
||||||
|
return _template.CloneInnerTemplate(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+192
-212
@@ -5,11 +5,11 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
using mROA.CodegenTools;
|
using mROA.Codegen.Templates;
|
||||||
using mROA.CodegenTools.Reading;
|
|
||||||
|
|
||||||
|
|
||||||
namespace mROA.Codegen
|
namespace mROA.Codegen
|
||||||
@@ -23,29 +23,56 @@ namespace mROA.Codegen
|
|||||||
[Generator]
|
[Generator]
|
||||||
public class mROAGenerator : IIncrementalGenerator
|
public class mROAGenerator : IIncrementalGenerator
|
||||||
{
|
{
|
||||||
|
private const string SharedObjectInterfaceAttributeName = "SharedObjectInterface";
|
||||||
|
|
||||||
private static readonly Predicate<IParameterSymbol> ParameterFilter =
|
private static readonly Predicate<IParameterSymbol> ParameterFilter =
|
||||||
i => i.Type.Name is "CancellationToken" or "RequestContext";
|
i => i.Type.Name is "CancellationToken" or "RequestContext";
|
||||||
|
|
||||||
private static readonly Predicate<ITypeSymbol> ParameterFilterForType =
|
private static readonly Predicate<ITypeSymbol> ParameterFilterForType =
|
||||||
i => i.Name is "CancellationToken" or "RequestContext";
|
i => i.Name is "CancellationToken" or "RequestContext";
|
||||||
|
|
||||||
private TemplateDocument _indexerTemplate;
|
|
||||||
private TemplateDocument _binderTemplate;
|
|
||||||
private TemplateDocument _classTemplate;
|
|
||||||
private TemplateDocument _classTemplateOriginal;
|
|
||||||
private TemplateDocument _interfaceTemplate;
|
|
||||||
private TemplateDocument _interfaceTemplateOriginal;
|
|
||||||
private TemplateDocument _methodInvokerOriginal;
|
|
||||||
private TemplateDocument _methodRepoTemplate;
|
|
||||||
private int _currentInternalCallIndex;
|
private int _currentInternalCallIndex;
|
||||||
|
|
||||||
|
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
var syntaxes = context.SyntaxProvider.CreateSyntaxProvider(
|
||||||
|
NodeIsInterfaceWithSharedObjectInterfaceAttribute,
|
||||||
|
TransformToInterfaceDeclarationSyntax);
|
||||||
|
|
||||||
|
var incrementalValueProvider = context.CompilationProvider.Combine(syntaxes.Collect());
|
||||||
|
context.RegisterSourceOutput(incrementalValueProvider,
|
||||||
|
(productionContext, pair) => GenerateCode(productionContext, pair.Left, pair.Right));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InterfaceDeclarationSyntax TransformToInterfaceDeclarationSyntax(GeneratorSyntaxContext context,
|
||||||
|
CancellationToken _)
|
||||||
|
{
|
||||||
|
if (context.Node is not InterfaceDeclarationSyntax interfaceSyntax)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
return interfaceSyntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool NodeIsInterfaceWithSharedObjectInterfaceAttribute(SyntaxNode node, CancellationToken _)
|
||||||
|
{
|
||||||
|
if (node is not InterfaceDeclarationSyntax interfaceSyntax)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var attributes = interfaceSyntax.AttributeLists.SelectMany(list => list.Attributes);
|
||||||
|
return attributes.Any(attribute => attribute.ToFullString() == SharedObjectInterfaceAttributeName);
|
||||||
|
}
|
||||||
|
|
||||||
private void GenerateCode(SourceProductionContext context, Compilation compilation,
|
private void GenerateCode(SourceProductionContext context, Compilation compilation,
|
||||||
ImmutableArray<InterfaceDeclarationSyntax> classes)
|
ImmutableArray<InterfaceDeclarationSyntax> classes)
|
||||||
{
|
{
|
||||||
|
var methodRepoTemplate = new MethodRepoTemplate();
|
||||||
|
var typeBinder = new RemoteTypeBinderTemplate();
|
||||||
|
var indexProviderTemplate = new IndexProviderTemplate();
|
||||||
var totalMethods = new List<IMethodSymbol>();
|
var totalMethods = new List<IMethodSymbol>();
|
||||||
|
|
||||||
_indexerTemplate.AddDefine("namespace", compilation.AssemblyName!);
|
if (compilation.AssemblyName == null)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
|
||||||
|
indexProviderTemplate.DefineNamespace(compilation.AssemblyName);
|
||||||
var invokers = new List<string>();
|
var invokers = new List<string>();
|
||||||
var declarations = classes.ToList();
|
var declarations = classes.ToList();
|
||||||
var apiLevel = 0;
|
var apiLevel = 0;
|
||||||
@@ -59,7 +86,7 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
|
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
|
||||||
var className = classDeclarationSyntax.Identifier.Text;
|
var className = classDeclarationSyntax.Identifier.Text;
|
||||||
var innerMethods = CollectMembers(classSymbol);
|
var innerMethods = CodegenUtilities.CollectMembers(classSymbol);
|
||||||
var associated = innerMethods.Select(i => i.AssociatedSymbol).Where(i => i != null)
|
var associated = innerMethods.Select(i => i.AssociatedSymbol).Where(i => i != null)
|
||||||
.Distinct(SymbolEqualityComparer.Default).Cast<ISymbol>().ToList();
|
.Distinct(SymbolEqualityComparer.Default).Cast<ISymbol>().ToList();
|
||||||
|
|
||||||
@@ -73,7 +100,7 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
className = className.TrimStart('I') + "Proxy";
|
className = className.TrimStart('I') + "Proxy";
|
||||||
|
|
||||||
_classTemplate = (TemplateDocument)_classTemplateOriginal.Clone();
|
var proxyTemplate = new ProxyTemplate();
|
||||||
var propertiesAccessMethods = new List<(string, IMethodSymbol)>();
|
var propertiesAccessMethods = new List<(string, IMethodSymbol)>();
|
||||||
|
|
||||||
int startInvokers = invokers.Count;
|
int startInvokers = invokers.Count;
|
||||||
@@ -81,11 +108,11 @@ namespace mROA.Codegen
|
|||||||
switch (method.MethodKind)
|
switch (method.MethodKind)
|
||||||
{
|
{
|
||||||
case MethodKind.PropertyGet or MethodKind.PropertySet:
|
case MethodKind.PropertyGet or MethodKind.PropertySet:
|
||||||
GeneratePropertyMethod(method, propertiesAccessMethods, invokers,
|
GeneratePropertyMethod(methodRepoTemplate, method, propertiesAccessMethods, invokers,
|
||||||
classSymbol);
|
classSymbol);
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
GenerateDeclaredMethod(method, invokers, classSymbol);
|
GenerateDeclaredMethod(proxyTemplate, methodRepoTemplate, method, invokers, classSymbol);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,101 +133,99 @@ namespace mROA.Codegen
|
|||||||
impl =
|
impl =
|
||||||
$"public {propertySymbol.Type.ToUnityString()} {symbol.Name} {{ {getter.Item1} {setter.Item1} }}";
|
$"public {propertySymbol.Type.ToUnityString()} {symbol.Name} {{ {getter.Item1} {setter.Item1} }}";
|
||||||
|
|
||||||
_classTemplate.Insert("methods", impl);
|
proxyTemplate.InsertMethods(impl);
|
||||||
// declaredMethods.Add(impl);
|
// declaredMethods.Add(impl);
|
||||||
break;
|
break;
|
||||||
case IEventSymbol eventSymbol:
|
case IEventSymbol eventSymbol:
|
||||||
_classTemplate.Insert("methods",
|
proxyTemplate.InsertMethods($"public event {eventSymbol.Type.ToUnityString()}? {eventSymbol.Name};");
|
||||||
$"public event {eventSymbol.Type.ToUnityString()}? {eventSymbol.Name};");
|
|
||||||
// declaredMethods.Add(
|
// declaredMethods.Add(
|
||||||
// $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};");
|
// $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateEventImplementation(classSymbol, invokers, context);
|
GenerateEventImplementation(proxyTemplate, methodRepoTemplate, typeBinder, classSymbol, invokers, context);
|
||||||
var endInvokers = invokers.Count;
|
var endInvokers = invokers.Count;
|
||||||
_indexerTemplate.Insert("indexSpan", $"{{ typeof({originalName}), new[] {{ {JoinWithComa(Enumerable.Range(startInvokers, endInvokers - startInvokers).Select(i => i.ToString()))} }} }},");
|
indexProviderTemplate.InsertIndexSpan($"{{ typeof({originalName}), new[] {{ {CodegenUtilities.JoinWithComa(Enumerable.Range(startInvokers, endInvokers - startInvokers).Select(i => i.ToString()))} }} }},");
|
||||||
_classTemplate.AddDefine("className", className);
|
proxyTemplate.DefineClassName(className);
|
||||||
_classTemplate.AddDefine("originalName", originalName);
|
proxyTemplate.DefineOriginalName(originalName);
|
||||||
_classTemplate.AddDefine("namespaceName", namespaceName);
|
proxyTemplate.DefineNamespaceName(namespaceName);
|
||||||
|
|
||||||
var code = _classTemplate.Compile();
|
var code = proxyTemplate.Compile();
|
||||||
|
|
||||||
|
|
||||||
// Add the source code to the compilation.
|
// Add the source code to the compilation.
|
||||||
#if !DONT_ADD
|
#if !DONT_ADD
|
||||||
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
|
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
|
||||||
#endif
|
#endif
|
||||||
_indexerTemplate.Insert("remoteTypePair",
|
indexProviderTemplate.InsertRemoteTypePair($"{{ typeof({classSymbol.ToUnityString()}), (id, r, c, indices) => new {namespaceName}.{className}(id, r, c, indices) }}");
|
||||||
$"{{ typeof({classSymbol.ToUnityString()}), (id, r, c, indices) => new {namespaceName}.{className}(id, r, c, indices) }}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalMethods.Count != 0)
|
if (totalMethods.Count != 0)
|
||||||
{
|
{
|
||||||
var coCodegenRepoCode = _methodRepoTemplate.Compile();
|
var coCodegenRepoCode = methodRepoTemplate.Compile();
|
||||||
_indexerTemplate.AddDefine("level", apiLevel.ToString());
|
indexProviderTemplate.DefineLevel(apiLevel.ToString());
|
||||||
_indexerTemplate.AddDefine("len", invokers.Count.ToString());
|
indexProviderTemplate.DefineLen(invokers.Count.ToString());
|
||||||
|
|
||||||
var providerCode = _indexerTemplate.Compile();
|
var providerCode = indexProviderTemplate.Compile();
|
||||||
#if !DONT_ADD
|
#if !DONT_ADD
|
||||||
context.AddSource("GeneratedInvokersCollection.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8));
|
context.AddSource("GeneratedInvokersCollection.g.cs",
|
||||||
|
SourceText.From(coCodegenRepoCode, Encoding.UTF8));
|
||||||
context.AddSource("GeneratedIndexProvider.g.cs", SourceText.From(providerCode, Encoding.UTF8));
|
context.AddSource("GeneratedIndexProvider.g.cs", SourceText.From(providerCode, Encoding.UTF8));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_indexerTemplate["remoteTypePair+"] != null)
|
if (indexProviderTemplate.IsRemoteTypePairInserted())
|
||||||
{
|
{
|
||||||
var frontendRepoCode = _binderTemplate.Compile();
|
var frontendRepoCode = typeBinder.Compile();
|
||||||
#if !DONT_ADD
|
#if !DONT_ADD
|
||||||
context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(frontendRepoCode, Encoding.UTF8));
|
context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(frontendRepoCode, Encoding.UTF8));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateEventImplementation(INamedTypeSymbol classSymbol, List<string> invokers,
|
private void GenerateEventImplementation(ProxyTemplate proxyTemplate, MethodRepoTemplate methodRepoTemplate, RemoteTypeBinderTemplate remoteTypeBinder, INamedTypeSymbol classSymbol,
|
||||||
SourceProductionContext context)
|
List<string> invokers, SourceProductionContext context)
|
||||||
{
|
{
|
||||||
var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers())
|
var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers())
|
||||||
.OfType<IEventSymbol>().ToList();
|
.OfType<IEventSymbol>().ToList();
|
||||||
if (events.Count == 0)
|
if (events.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_interfaceTemplate = (TemplateDocument)_interfaceTemplateOriginal.Clone();
|
var partialInterfaceTemplate = new PartialInterfaceTemplate();
|
||||||
_interfaceTemplate.AddDefine("name", classSymbol.Name);
|
partialInterfaceTemplate.DefineName(classSymbol.Name);
|
||||||
_interfaceTemplate.AddDefine("namespace", classSymbol.ContainingNamespace.ToDisplayString());
|
partialInterfaceTemplate.DefineNamespace(classSymbol.ContainingNamespace.ToDisplayString());
|
||||||
var objectBinderTemplate =
|
|
||||||
(TemplateDocument)((InnerTemplateSection)_binderTemplate["objectBinderTemplate"]!).InnerTemplate
|
var objectBinderTemplate = remoteTypeBinder.CloneInnerObjectBinder();
|
||||||
.Clone();
|
|
||||||
foreach (var currentEvent in events)
|
foreach (var currentEvent in events)
|
||||||
{
|
{
|
||||||
var additionalMethod = GenerateMethodExternalCaller(currentEvent, out var signature);
|
var additionalMethod = GenerateMethodExternalCaller(currentEvent, out var signature);
|
||||||
_classTemplate.Insert("methods", additionalMethod);
|
proxyTemplate.InsertMethods(additionalMethod);
|
||||||
|
|
||||||
// declaredMethods.Add(additionalMethod);
|
// declaredMethods.Add(additionalMethod);
|
||||||
_interfaceTemplate.Insert("signature", signature);
|
partialInterfaceTemplate.InsertSignature(signature);
|
||||||
GenerateEventCode(currentEvent, invokers, classSymbol);
|
GenerateEventCode(methodRepoTemplate, currentEvent, invokers, classSymbol);
|
||||||
GenerateBinderCode(currentEvent, invokers, classSymbol, objectBinderTemplate);
|
GenerateBinderCode(objectBinderTemplate, currentEvent, classSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
objectBinderTemplate.AddDefine("type", classSymbol.ToUnityString());
|
objectBinderTemplate.DefineType(classSymbol.ToUnityString());
|
||||||
var partialInterface = _interfaceTemplate.Compile();
|
var partialInterface = partialInterfaceTemplate.Compile();
|
||||||
var binder = objectBinderTemplate.Compile();
|
var binder = objectBinderTemplate.Compile();
|
||||||
_binderTemplate.Insert("eventBinder", binder);
|
remoteTypeBinder.InsertEventBinder(binder);
|
||||||
|
|
||||||
#if !DONT_ADD
|
#if !DONT_ADD
|
||||||
context.AddSource($"{classSymbol.Name}.g.cs", SourceText.From(partialInterface, Encoding.UTF8));
|
context.AddSource($"{classSymbol.Name}.g.cs", SourceText.From(partialInterface, Encoding.UTF8));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenerateMethodExternalCaller(IEventSymbol eventSymbol, out string interfaceSignature)
|
private static string GenerateMethodExternalCaller(IEventSymbol eventSymbol, out string interfaceSignature)
|
||||||
{
|
{
|
||||||
var level = "\t\t";
|
const string level = "\t\t";
|
||||||
var parameters = ((INamedTypeSymbol)eventSymbol.Type).TypeArguments;
|
var parameters = ((INamedTypeSymbol)eventSymbol.Type).TypeArguments;
|
||||||
var parameterIndex = 0;
|
var parameterIndex = 0;
|
||||||
var parametersDeclaration =
|
var parametersDeclaration =
|
||||||
string.Join(", ", parameters.Select(i => $"{i.ToUnityString()} p{parameterIndex++}"));
|
string.Join(", ", parameters.Select(i => $"{i.ToUnityString()} p{parameterIndex++}"));
|
||||||
var signature = $@"public void {EventExternalName(eventSymbol)}({parametersDeclaration})";
|
var signature = $"public void {CodegenUtilities.EventExternalName(eventSymbol)}({parametersDeclaration})";
|
||||||
interfaceSignature = signature + ";";
|
interfaceSignature = signature + ";";
|
||||||
var caller = $@"{signature}
|
var caller = $@"{signature}
|
||||||
{level}{{
|
{level}{{
|
||||||
@@ -210,22 +235,8 @@ namespace mROA.Codegen
|
|||||||
return caller;
|
return caller;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string EventExternalName(IEventSymbol eventSymbol)
|
private void GenerateDeclaredMethod(ProxyTemplate proxyTemplate, MethodRepoTemplate methodRepoTemplate, IMethodSymbol method, List<string> invokers,
|
||||||
{
|
INamedTypeSymbol baseInterface)
|
||||||
return $"{eventSymbol.Name}External";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string Caster(ITypeSymbol type, string inner)
|
|
||||||
{
|
|
||||||
if (!type.IsValueType)
|
|
||||||
return inner +
|
|
||||||
" as " +
|
|
||||||
type.ToUnityString();
|
|
||||||
return $"({type.ToUnityString()})" + inner;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GenerateDeclaredMethod(IMethodSymbol method, List<string> invokers,
|
|
||||||
INamedTypeSymbol baseInterace)
|
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
@@ -259,9 +270,9 @@ namespace mROA.Codegen
|
|||||||
sb.AppendLine("public" + (isAsync
|
sb.AppendLine("public" + (isAsync
|
||||||
? " async "
|
? " async "
|
||||||
: " ") +
|
: " ") +
|
||||||
$"{method.ReturnType.ToUnityString()} {method.Name}({string.Join(", ", method.Parameters.Select(ToFullString))}){{");
|
$"{method.ReturnType.ToUnityString()} {method.Name}({string.Join(", ", method.Parameters.Select(CodegenUtilities.ToFullString))}){{");
|
||||||
|
|
||||||
var isUntrusted = method.GetAttributes().Any(i => i.AttributeClass.Name == "UntrustedAttribute");
|
var isUntrusted = method.GetAttributes().Any(i => i.AttributeClass?.Name == "UntrustedAttribute");
|
||||||
|
|
||||||
var prefix = isAsync ? "await " : "";
|
var prefix = isAsync ? "await " : "";
|
||||||
var postfix = !isAsync ? isVoid ? ".Wait()" : ".GetAwaiter().GetResult()" : "";
|
var postfix = !isAsync ? isVoid ? ".Wait()" : ".GetAwaiter().GetResult()" : "";
|
||||||
@@ -286,18 +297,17 @@ namespace mROA.Codegen
|
|||||||
caller = isVoid
|
caller = isVoid
|
||||||
? $"CallAsync(CallIndices[{_currentInternalCallIndex++}]{parameterLink}{tokenInsert})"
|
? $"CallAsync(CallIndices[{_currentInternalCallIndex++}]{parameterLink}{tokenInsert})"
|
||||||
: isAsync
|
: isAsync
|
||||||
? $"GetResultAsync<{ExtractTaskType(method.ReturnType)}>(CallIndices[{_currentInternalCallIndex++}]{parameterLink}{tokenInsert})"
|
? $"GetResultAsync<{CodegenUtilities.ExtractTaskType(method.ReturnType)}>(CallIndices[{_currentInternalCallIndex++}]{parameterLink}{tokenInsert})"
|
||||||
: $"GetResultAsync<{ToFullString(method.ReturnType)}>(CallIndices[{_currentInternalCallIndex++}]{parameterLink}{tokenInsert})";
|
: $"GetResultAsync<{CodegenUtilities.ToFullString(method.ReturnType)}>(CallIndices[{_currentInternalCallIndex++}]{parameterLink}{tokenInsert})";
|
||||||
|
|
||||||
if (!isVoid)
|
if (!isVoid)
|
||||||
prefix = "return " + prefix;
|
prefix = "return " + prefix;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";");
|
sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";");
|
||||||
|
|
||||||
sb.AppendLine("\t\t}");
|
sb.AppendLine("\t\t}");
|
||||||
_classTemplate.Insert("methods", sb.ToString());
|
proxyTemplate.InsertMethods(sb.ToString());
|
||||||
|
|
||||||
// declaredMethods.Add(sb.ToString());
|
// declaredMethods.Add(sb.ToString());
|
||||||
var parameterTypes = string.Join(", ",
|
var parameterTypes = string.Join(", ",
|
||||||
@@ -316,7 +326,7 @@ namespace mROA.Codegen
|
|||||||
parametersInsertList.Add("(RequestContext)special[0]");
|
parametersInsertList.Add("(RequestContext)special[0]");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
parametersInsertList.Add(Caster(parameter.Type,
|
parametersInsertList.Add(CodegenUtilities.Caster(parameter.Type,
|
||||||
$"parameters[{parameters.IndexOf(parameter)}]"));
|
$"parameters[{parameters.IndexOf(parameter)}]"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -342,78 +352,70 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
if (isAsync)
|
if (isAsync)
|
||||||
{
|
{
|
||||||
var invokerTemplate =
|
var invokerTemplate = methodRepoTemplate.CloneInnerAsyncInvoker();
|
||||||
(TemplateDocument)((InnerTemplateSection)_methodRepoTemplate["asyncInvoker"]!).InnerTemplate
|
invokerTemplate.DefineIsVoid(isVoid.ToString().ToLower());
|
||||||
.Clone();
|
invokerTemplate.DefineReturnType(CodegenUtilities.ExtractTaskType(method.ReturnType));
|
||||||
invokerTemplate.AddDefine("isVoid", isVoid.ToString().ToLower());
|
invokerTemplate.DefineParametersType(parameterTypes);
|
||||||
invokerTemplate.AddDefine("returnType", ExtractTaskType(method.ReturnType));
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
|
||||||
invokerTemplate.AddDefine("funcInvoking", funcInvoking);
|
|
||||||
invokerTemplate.AddDefine("isTrusted", (!isUntrusted).ToString().ToLower());
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker();
|
||||||
invokerTemplate.AddDefine("isVoid", isVoid.ToString().ToLower());
|
invokerTemplate.DefineIsVoid(isVoid.ToString().ToLower());
|
||||||
invokerTemplate.AddDefine("returnType", isVoid ? "void" : method.ReturnType.ToUnityString());
|
invokerTemplate.DefineReturnType(isVoid ? "void" : method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
invokerTemplate.DefineParametersType(parameterTypes);
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.AddDefine("funcInvoking", funcInvoking);
|
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
||||||
invokerTemplate.AddDefine("isTrusted", (!isUntrusted).ToString().ToLower());
|
invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower());
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
_methodRepoTemplate.Insert("invoker", backend);
|
methodRepoTemplate.InsertInvoke(backend);
|
||||||
|
|
||||||
invokers.Add(backend);
|
invokers.Add(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateBinderCode(IEventSymbol eventSymbol, List<string> invokers, INamedTypeSymbol baseType,
|
private void GenerateBinderCode(ObjectBinderTemplate objectBinderTemplate, IEventSymbol eventSymbol, INamedTypeSymbol baseType)
|
||||||
TemplateDocument document)
|
|
||||||
{
|
{
|
||||||
var eventBinderTemplate =
|
var eventBinderTemplate = objectBinderTemplate.CloneInnerEventBinder();
|
||||||
(TemplateDocument)((InnerTemplateSection)document["eventBinderTemplate"]!).InnerTemplate.Clone();
|
|
||||||
|
|
||||||
var index = _currentInternalCallIndex;
|
var index = _currentInternalCallIndex;
|
||||||
var parameters = (eventSymbol.Type as INamedTypeSymbol)!.TypeArguments.ToList();
|
var parameters = (eventSymbol.Type as INamedTypeSymbol)!.TypeArguments.ToList();
|
||||||
var parametersDeclaration = string.Join(", ",
|
var parametersDeclaration = string.Join(", ",
|
||||||
JoinWithComa(Enumerable.Range(0, parameters.Count).Select(i => "p" + i)));
|
CodegenUtilities.JoinWithComa(Enumerable.Range(0, parameters.Count).Select(i => "p" + i)));
|
||||||
|
|
||||||
|
|
||||||
int pi = 0;
|
var pi = 0;
|
||||||
var transferParameters =
|
var transferParameters = CodegenUtilities.JoinWithComa(parameters.Select(i => (i, pi++))
|
||||||
JoinWithComa(parameters.Select(i => (i, pi++)).Where(i => !ParameterFilterForType(i.i))
|
.Where(i => !ParameterFilterForType(i.i))
|
||||||
.Select(i => "p" + i.Item2));
|
.Select(i => "p" + i.Item2));
|
||||||
|
|
||||||
var requestIndex = parameters.FindIndex(i => i.Name == "RequestContext");
|
var requestIndex = parameters.FindIndex(i => i.Name == "RequestContext");
|
||||||
if (requestIndex != -1)
|
if (requestIndex != -1)
|
||||||
{
|
{
|
||||||
var callFilter = $"\n\r\t\t\tif(ownerId == p{requestIndex}.OwnerId) return;";
|
var callFilter = $"\n\r\t\t\tif(ownerId == p{requestIndex}.OwnerId) return;";
|
||||||
eventBinderTemplate.AddDefine("callFilter", callFilter);
|
eventBinderTemplate.DefineCallFilter(callFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
eventBinderTemplate.AddDefine("type", baseType.ToUnityString());
|
eventBinderTemplate.DefineType(baseType.ToUnityString());
|
||||||
eventBinderTemplate.AddDefine("eventName", eventSymbol.Name);
|
eventBinderTemplate.DefineEventName(eventSymbol.Name);
|
||||||
eventBinderTemplate.AddDefine("parametersDeclaration", parametersDeclaration);
|
eventBinderTemplate.DefineParametersDeclaration(parametersDeclaration);
|
||||||
eventBinderTemplate.AddDefine("commandId", $"context.CallIndexProvider.GetIndices(typeof({baseType.ToUnityString()}))[{index}]");
|
eventBinderTemplate.DefineCommandIdTag($"context.CallIndexProvider.GetIndices(typeof({baseType.ToUnityString()}))[{index}]");
|
||||||
eventBinderTemplate.AddDefine("transferParameters", transferParameters);
|
eventBinderTemplate.DefineTransferParameters(transferParameters);
|
||||||
var eventBinderCode = eventBinderTemplate.Compile();
|
var eventBinderCode = eventBinderTemplate.Compile();
|
||||||
document.Insert("eventBinder", eventBinderCode);
|
objectBinderTemplate.InsertEventBinder(eventBinderCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string JoinWithComa(IEnumerable<string> parts)
|
private void GenerateEventCode(MethodRepoTemplate methodRepoTemplate, IEventSymbol eventSymbol, List<string> invokers, ITypeSymbol baseInterface)
|
||||||
{
|
|
||||||
return string.Join(", ", parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GenerateEventCode(IEventSymbol eventSymbol, List<string> invokers, ITypeSymbol baseInterface)
|
|
||||||
{
|
{
|
||||||
var level = "\t\t\t";
|
var level = "\t\t\t";
|
||||||
|
|
||||||
int pi = 0;
|
int pi = 0;
|
||||||
var parameters = ((INamedTypeSymbol)eventSymbol.Type).TypeArguments.Select(i => (i, pi++)).ToImmutableArray();
|
var parameters = ((INamedTypeSymbol)eventSymbol.Type).TypeArguments.Select(i => (i, pi++))
|
||||||
|
.ToImmutableArray();
|
||||||
var parsingParameters = parameters.RemoveAll(i => ParameterFilterForType(i.i)).ToList();
|
var parsingParameters = parameters.RemoveAll(i => ParameterFilterForType(i.i)).ToList();
|
||||||
var parameterTypes = string.Join(", ",
|
var parameterTypes = string.Join(", ",
|
||||||
$"{string.Join(", ", parsingParameters.Select(p => $"typeof({p.i.ToUnityString()})"))}");
|
$"{string.Join(", ", parsingParameters.Select(p => $"typeof({p.i.ToUnityString()})"))}");
|
||||||
@@ -430,7 +432,7 @@ namespace mROA.Codegen
|
|||||||
parametersInsertList.Add("(RequestContext)special[0]");
|
parametersInsertList.Add("(RequestContext)special[0]");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
parametersInsertList.Add(Caster(parameter.i,
|
parametersInsertList.Add(CodegenUtilities.Caster(parameter.i,
|
||||||
$"parameters[{parameter.Item2}]"));
|
$"parameters[{parameter.Item2}]"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -439,25 +441,25 @@ namespace mROA.Codegen
|
|||||||
var parametersInsert = string.Join(", ", parametersInsertList);
|
var parametersInsert = string.Join(", ", parametersInsertList);
|
||||||
|
|
||||||
var funcInvoking = $@"{{
|
var funcInvoking = $@"{{
|
||||||
{level} (i as {baseInterface.ToUnityString()}).{EventExternalName(eventSymbol)}({parametersInsert});
|
{level} (i as {baseInterface.ToUnityString()}).{CodegenUtilities.EventExternalName(eventSymbol)}({parametersInsert});
|
||||||
{level} return null;
|
{level} return null;
|
||||||
{level} }}";
|
{level} }}";
|
||||||
|
|
||||||
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker();
|
||||||
invokerTemplate.AddDefine("isVoid", "true");
|
invokerTemplate.DefineIsVoid("true");
|
||||||
invokerTemplate.AddDefine("returnType", "void");
|
invokerTemplate.DefineReturnType("void");
|
||||||
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
invokerTemplate.DefineParametersType(parameterTypes);
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterface.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.AddDefine("funcInvoking", funcInvoking);
|
invokerTemplate.DefineFuncInvoking(funcInvoking);
|
||||||
invokerTemplate.AddDefine("isTrusted", "true");
|
invokerTemplate.DefineIsTrusted("true");
|
||||||
var backend = invokerTemplate.Compile();
|
var backend = invokerTemplate.Compile();
|
||||||
_methodRepoTemplate.Insert("invoker", backend);
|
methodRepoTemplate.InsertInvoke(backend);
|
||||||
|
|
||||||
invokers.Add(backend);
|
invokers.Add(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GeneratePropertyMethod(IMethodSymbol method,
|
private void GeneratePropertyMethod(MethodRepoTemplate methodRepoTemplate, IMethodSymbol method,
|
||||||
List<(string, IMethodSymbol)> propsCollection, List<string> invokers, INamedTypeSymbol baseInterace)
|
List<(string, IMethodSymbol)> propsCollection, List<string> invokers, INamedTypeSymbol baseInterface)
|
||||||
{
|
{
|
||||||
string frontend;
|
string frontend;
|
||||||
string backend;
|
string backend;
|
||||||
@@ -473,28 +475,27 @@ namespace mROA.Codegen
|
|||||||
$"{string.Join(", ", method.Parameters.Select(p => "typeof(" + p.Type.ToUnityString() + ")"))}");
|
$"{string.Join(", ", method.Parameters.Select(p => "typeof(" + p.Type.ToUnityString() + ")"))}");
|
||||||
var parameterInserts = string.Join(", ",
|
var parameterInserts = string.Join(", ",
|
||||||
method.Parameters.Select(p =>
|
method.Parameters.Select(p =>
|
||||||
Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]")));
|
CodegenUtilities.Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]")));
|
||||||
|
|
||||||
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker();
|
||||||
invokerTemplate.AddDefine("isVoid", "false");
|
invokerTemplate.DefineIsVoid("false");
|
||||||
invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString());
|
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
invokerTemplate.DefineParametersType(parameterTypes);
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.AddDefine("funcInvoking",
|
invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}]");
|
||||||
$"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}]");
|
invokerTemplate.DefineIsTrusted("true");
|
||||||
invokerTemplate.AddDefine("isTrusted", "true");
|
|
||||||
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker();
|
||||||
invokerTemplate.AddDefine("isVoid", "false");
|
invokerTemplate.DefineIsVoid("false");
|
||||||
invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString());
|
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
invokerTemplate.DefineParametersType("");
|
||||||
invokerTemplate.AddDefine("funcInvoking",
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
$"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name}");
|
invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name}");
|
||||||
invokerTemplate.AddDefine("isTrusted", "true");
|
invokerTemplate.DefineIsTrusted("true");
|
||||||
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
@@ -513,86 +514,82 @@ namespace mROA.Codegen
|
|||||||
$"{string.Join(", ", method.Parameters.Select(p => $"typeof({p.Type.ToUnityString()})"))}");
|
$"{string.Join(", ", method.Parameters.Select(p => $"typeof({p.Type.ToUnityString()})"))}");
|
||||||
var parameterInserts = string.Join(", ",
|
var parameterInserts = string.Join(", ",
|
||||||
method.Parameters.Take(method.Parameters.Length - 1).Select(p =>
|
method.Parameters.Take(method.Parameters.Length - 1).Select(p =>
|
||||||
Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]")));
|
CodegenUtilities.Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]")));
|
||||||
|
|
||||||
var valueInsert = Caster(method.Parameters.Last().Type,
|
var valueInsert = CodegenUtilities.Caster(method.Parameters.Last().Type,
|
||||||
"parameters[" + (method.Parameters.Length - 1) + "]");
|
"parameters[" + (method.Parameters.Length - 1) + "]");
|
||||||
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
|
||||||
|
|
||||||
|
var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker();
|
||||||
invokerTemplate.AddDefine("isVoid", "true");
|
invokerTemplate.DefineIsVoid("true");
|
||||||
invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString());
|
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
invokerTemplate.DefineParametersType(parameterTypes);
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
invokerTemplate.AddDefine("funcInvoking",
|
invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}] = {valueInsert}");
|
||||||
$"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}] = {valueInsert}");
|
invokerTemplate.DefineIsTrusted("true");
|
||||||
invokerTemplate.AddDefine("isTrusted", "true");
|
|
||||||
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker();
|
||||||
|
invokerTemplate.DefineIsVoid("true");
|
||||||
invokerTemplate.AddDefine("isVoid", "true");
|
invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString());
|
invokerTemplate.DefineParametersType($"typeof({method.Parameters.First().Type.ToUnityString()})");
|
||||||
invokerTemplate.AddDefine("parametersType",
|
invokerTemplate.DefineSuitableType(baseInterface.ToUnityString());
|
||||||
$"typeof({method.Parameters.First().Type.ToUnityString()})");
|
invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name} = {CodegenUtilities.Caster((method.AssociatedSymbol as IPropertySymbol)!.Type, "parameters[0]")}");
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
invokerTemplate.DefineIsTrusted("true");
|
||||||
invokerTemplate.AddDefine("funcInvoking",
|
|
||||||
$"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name} = {Caster((method.AssociatedSymbol as IPropertySymbol)!.Type, "parameters[0]")}");
|
|
||||||
invokerTemplate.AddDefine("isTrusted", "true");
|
|
||||||
|
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
frontend = $"set => CallAsync(CallIndices[{_currentInternalCallIndex++}], new System.Object[] {{ {parametersArray} }}).Wait();";
|
frontend =
|
||||||
|
$"set => CallAsync(CallIndices[{_currentInternalCallIndex++}], new System.Object[] {{ {parametersArray} }}).Wait();";
|
||||||
}
|
}
|
||||||
|
|
||||||
propsCollection.Add((frontend, method));
|
propsCollection.Add((frontend, method));
|
||||||
_methodRepoTemplate.Insert("invoker", backend);
|
methodRepoTemplate.InsertInvoke(backend);
|
||||||
invokers.Add(backend);
|
invokers.Add(backend);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static string ToFullString(IParameterSymbol parameter)
|
public static class CodegenUtilities
|
||||||
|
{
|
||||||
|
public static string EventExternalName(IEventSymbol eventSymbol)
|
||||||
|
{
|
||||||
|
return $"{eventSymbol.Name}External";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Caster(ITypeSymbol type, string inner)
|
||||||
|
{
|
||||||
|
if (!type.IsValueType)
|
||||||
|
return inner +
|
||||||
|
" as " +
|
||||||
|
type.ToUnityString();
|
||||||
|
return $"({type.ToUnityString()})" + inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string JoinWithComa(IEnumerable<string> parts)
|
||||||
|
{
|
||||||
|
return string.Join(", ", parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToFullString(IParameterSymbol parameter)
|
||||||
{
|
{
|
||||||
return parameter.Type.ToUnityString() + " " + parameter.Name;
|
return parameter.Type.ToUnityString() + " " + parameter.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ToFullString(ITypeSymbol type)
|
public static string ToFullString(ITypeSymbol type)
|
||||||
{
|
{
|
||||||
return type.ToUnityString();
|
return type.ToUnityString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ExtractTaskType(ITypeSymbol taskType)
|
public static string ExtractTaskType(ITypeSymbol taskType)
|
||||||
{
|
{
|
||||||
var generics = ((INamedTypeSymbol)taskType).TypeArguments;
|
var generics = ((INamedTypeSymbol)taskType).TypeArguments;
|
||||||
return generics.Length == 0 ? "void" : generics[0].ToUnityString();
|
return generics.Length == 0 ? "void" : generics[0].ToUnityString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (InterfaceDeclarationSyntax node, bool usefull) ContainsSoiAttribute(
|
public static List<IMethodSymbol> CollectMembers(INamedTypeSymbol type)
|
||||||
GeneratorSyntaxContext context)
|
|
||||||
{
|
|
||||||
var ids = (InterfaceDeclarationSyntax)context.Node;
|
|
||||||
|
|
||||||
// Go through all attributes of the class.
|
|
||||||
foreach (AttributeListSyntax attributeListSyntax in ids.AttributeLists)
|
|
||||||
foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes)
|
|
||||||
{
|
|
||||||
if (context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
|
|
||||||
continue; // if we can't get the symbol, ignore it
|
|
||||||
|
|
||||||
string attributeName = attributeSymbol.ContainingType.ToDisplayString();
|
|
||||||
|
|
||||||
// Check the full name of the [Report] attribute.
|
|
||||||
if (attributeName == $"mROA.Implementation.Attributes.SharedObjectInterfaceAttribute")
|
|
||||||
return (ids,true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ids ,false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<IMethodSymbol> CollectMembers(INamedTypeSymbol type)
|
|
||||||
{
|
{
|
||||||
var methods = type.GetMembers().OfType<IMethodSymbol>().ToList();
|
var methods = type.GetMembers().OfType<IMethodSymbol>().ToList();
|
||||||
foreach (var inner in type.AllInterfaces) methods.AddRange(inner.GetMembers().OfType<IMethodSymbol>());
|
foreach (var inner in type.AllInterfaces) methods.AddRange(inner.GetMembers().OfType<IMethodSymbol>());
|
||||||
@@ -600,34 +597,17 @@ namespace mROA.Codegen
|
|||||||
methods.RemoveAll(m => m.Name == "Dispose");
|
methods.RemoveAll(m => m.Name == "Dispose");
|
||||||
return methods.OrderBy(i => i.Name).ToList();
|
return methods.OrderBy(i => i.Name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
|
||||||
{
|
|
||||||
_methodRepoTemplate = TemplateReader.FromEmbeddedResource("MethodRepo.cstmpl");
|
|
||||||
_methodInvokerOriginal =
|
|
||||||
((InnerTemplateSection)_methodRepoTemplate["syncInvoker"]!).InnerTemplate;
|
|
||||||
_classTemplateOriginal = TemplateReader.FromEmbeddedResource("Proxy.cstmpl");
|
|
||||||
_binderTemplate = TemplateReader.FromEmbeddedResource("RemoteTypeBinder.cstmpl");
|
|
||||||
_interfaceTemplateOriginal = TemplateReader.FromEmbeddedResource("PartialInterface.cstmpl");
|
|
||||||
_indexerTemplate = TemplateReader.FromEmbeddedResource("IndexProvider.cstmpl");
|
|
||||||
|
|
||||||
var syntaxes = context.SyntaxProvider.CreateSyntaxProvider(
|
|
||||||
(static (node, _) => node is InterfaceDeclarationSyntax), static (node, _) => ContainsSoiAttribute(node)).Where(i => i.usefull).Select((node, _) => node.node);
|
|
||||||
|
|
||||||
context.RegisterSourceOutput(context.CompilationProvider.Combine(syntaxes.Collect()), (productionContext, pair) => GenerateCode(productionContext, pair.Left, pair.Right));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CodegenExtentions
|
public static class CodegenExtensions
|
||||||
{
|
{
|
||||||
public static string ToUnityString(this ITypeSymbol type)
|
public static string ToUnityString(this ITypeSymbol type)
|
||||||
{
|
{
|
||||||
var parts = type.ToDisplayParts();
|
var parts = type.ToDisplayParts();
|
||||||
|
|
||||||
if (parts.Any(i => i.Kind == SymbolDisplayPartKind.Keyword))
|
return parts.Any(i => i.Kind == SymbolDisplayPartKind.Keyword)
|
||||||
return parts.ToUnityString();
|
? parts.ToUnityString()
|
||||||
|
: type.ToDisplayString();
|
||||||
return type.ToDisplayString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToUnityString(this IParameterSymbol parameter)
|
public static string ToUnityString(this IParameterSymbol parameter)
|
||||||
@@ -635,7 +615,7 @@ namespace mROA.Codegen
|
|||||||
return parameter.Type.ToUnityString() + " " + parameter.Name;
|
return parameter.Type.ToUnityString() + " " + parameter.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToUnityString(this ImmutableArray<SymbolDisplayPart> parts)
|
private static string ToUnityString(this ImmutableArray<SymbolDisplayPart> parts)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
foreach (var displayPart in parts)
|
foreach (var displayPart in parts)
|
||||||
|
|||||||
Reference in New Issue
Block a user