diff --git a/mROA.Codegen/CodeTemplate.cs b/mROA.Codegen/CodeTemplate.cs deleted file mode 100644 index f0b3a85..0000000 --- a/mROA.Codegen/CodeTemplate.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using mROA.CodegenTools; -using mROA.CodegenTools.Reading; - -namespace mROA.Codegen -{ - public class CodeTemplate - { - private const string MethodRepoTemplateName = "MethodRepo.cstmpl"; - private const string ProxyTemplateName = "Proxy.cstmpl"; - private const string RemoteTypeBinderTemplateName = "RemoteTypeBinder.cstmpl"; - private const string PartialInterfaceTemplateName = "PartialInterface.cstmpl"; - private const string IndexProviderTemplateName = "IndexProvider.cstmpl"; - private const string SyncInvokerTag = "syncInvoker"; - - private TemplateDocument? _proxy; - private TemplateDocument? _indexerProvider; - private TemplateDocument? _remoteTypeBinder; - private TemplateDocument? _partialInterface; - private TemplateDocument? _methodRepo; - private TemplateDocument? _methodInvoker; - - public TemplateDocument Proxy => _proxy - ?? throw new InvalidOperationException(); - public TemplateDocument IndexerProvider => _indexerProvider - ?? throw new InvalidOperationException(); - public TemplateDocument RemoteTypeBinder => _remoteTypeBinder - ?? throw new InvalidOperationException(); - public TemplateDocument PartialInterface => _partialInterface - ?? throw new InvalidOperationException(); - public TemplateDocument MethodRepo => _methodRepo - ?? throw new InvalidOperationException(); - public TemplateDocument MethodInvoker => _methodInvoker - ?? throw new InvalidOperationException(); - - public void LoadTemplates() - { - _proxy = TemplateReader.FromEmbeddedResource(ProxyTemplateName); - _indexerProvider = TemplateReader.FromEmbeddedResource(IndexProviderTemplateName); - _remoteTypeBinder = TemplateReader.FromEmbeddedResource(RemoteTypeBinderTemplateName); - _partialInterface = TemplateReader.FromEmbeddedResource(PartialInterfaceTemplateName); - _methodRepo = TemplateReader.FromEmbeddedResource(MethodRepoTemplateName); - - var innerMethodSection = MethodRepo[SyncInvokerTag] as InnerTemplateSection - ?? throw new InvalidOperationException(); - _methodInvoker = innerMethodSection.InnerTemplate; - } - } -} \ No newline at end of file diff --git a/mROA.Codegen/TemplateDocumentExtensions.cs b/mROA.Codegen/TemplateDocumentExtensions.cs new file mode 100644 index 0000000..8889bd1 --- /dev/null +++ b/mROA.Codegen/TemplateDocumentExtensions.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Templates/EventBinderTemplate.cs b/mROA.Codegen/Templates/EventBinderTemplate.cs new file mode 100644 index 0000000..5c325cb --- /dev/null +++ b/mROA.Codegen/Templates/EventBinderTemplate.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Templates/IndexProviderTemplate.cs b/mROA.Codegen/Templates/IndexProviderTemplate.cs new file mode 100644 index 0000000..cac9637 --- /dev/null +++ b/mROA.Codegen/Templates/IndexProviderTemplate.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Templates/InvokerTemplate.cs b/mROA.Codegen/Templates/InvokerTemplate.cs new file mode 100644 index 0000000..4373de2 --- /dev/null +++ b/mROA.Codegen/Templates/InvokerTemplate.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Templates/MethodRepoTemplate.cs b/mROA.Codegen/Templates/MethodRepoTemplate.cs new file mode 100644 index 0000000..8f028b6 --- /dev/null +++ b/mROA.Codegen/Templates/MethodRepoTemplate.cs @@ -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 = "invoke"; + + 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); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Templates/ObjectBinderTemplate.cs b/mROA.Codegen/Templates/ObjectBinderTemplate.cs new file mode 100644 index 0000000..57221b4 --- /dev/null +++ b/mROA.Codegen/Templates/ObjectBinderTemplate.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Templates/PartialInterfaceTemplate.cs b/mROA.Codegen/Templates/PartialInterfaceTemplate.cs new file mode 100644 index 0000000..2441e2a --- /dev/null +++ b/mROA.Codegen/Templates/PartialInterfaceTemplate.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Templates/ProxyTemplate.cs b/mROA.Codegen/Templates/ProxyTemplate.cs new file mode 100644 index 0000000..d66f03e --- /dev/null +++ b/mROA.Codegen/Templates/ProxyTemplate.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Templates/RemoteTypeBinderTemplate.cs b/mROA.Codegen/Templates/RemoteTypeBinderTemplate.cs new file mode 100644 index 0000000..9aa9add --- /dev/null +++ b/mROA.Codegen/Templates/RemoteTypeBinderTemplate.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Templates/TemplateView.cs b/mROA.Codegen/Templates/TemplateView.cs new file mode 100644 index 0000000..75fa1d4 --- /dev/null +++ b/mROA.Codegen/Templates/TemplateView.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/mROASourceGenerator.cs b/mROA.Codegen/mROASourceGenerator.cs index 48c4c94..881ab21 100644 --- a/mROA.Codegen/mROASourceGenerator.cs +++ b/mROA.Codegen/mROASourceGenerator.cs @@ -9,7 +9,7 @@ using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using mROA.CodegenTools; +using mROA.Codegen.Templates; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. @@ -31,15 +31,11 @@ namespace mROA.Codegen private static readonly Predicate ParameterFilterForType = i => i.Name is "CancellationToken" or "RequestContext"; - - private readonly CodeTemplate _codeTemplate = new(); - + private int _currentInternalCallIndex; public void Initialize(IncrementalGeneratorInitializationContext context) { - _codeTemplate.LoadTemplates(); - var syntaxes = context.SyntaxProvider.CreateSyntaxProvider( NodeIsInterfaceWithSharedObjectInterfaceAttribute, TransformToInterfaceDeclarationSyntax); @@ -69,9 +65,15 @@ namespace mROA.Codegen private void GenerateCode(SourceProductionContext context, Compilation compilation, ImmutableArray classes) { + var methodRepoTemplate = new MethodRepoTemplate(); + var typeBinder = new RemoteTypeBinderTemplate(); + var indexProviderTemplate = new IndexProviderTemplate(); var totalMethods = new List(); - _codeTemplate.IndexerProvider.AddDefine("namespace", compilation.AssemblyName!); + if (compilation.AssemblyName == null) + throw new InvalidOperationException(); + + indexProviderTemplate.DefineNamespace(compilation.AssemblyName); var invokers = new List(); var declarations = classes.ToList(); var apiLevel = 0; @@ -99,7 +101,7 @@ namespace mROA.Codegen className = className.TrimStart('I') + "Proxy"; - var classTemplate = (TemplateDocument)_codeTemplate.Proxy.Clone(); + var proxyTemplate = new ProxyTemplate(); var propertiesAccessMethods = new List<(string, IMethodSymbol)>(); int startInvokers = invokers.Count; @@ -107,11 +109,11 @@ namespace mROA.Codegen switch (method.MethodKind) { case MethodKind.PropertyGet or MethodKind.PropertySet: - GeneratePropertyMethod(method, propertiesAccessMethods, invokers, + GeneratePropertyMethod(methodRepoTemplate, method, propertiesAccessMethods, invokers, classSymbol); continue; default: - GenerateDeclaredMethod(classTemplate, method, invokers, classSymbol); + GenerateDeclaredMethod(proxyTemplate, methodRepoTemplate, method, invokers, classSymbol); break; } @@ -132,43 +134,40 @@ namespace mROA.Codegen impl = $"public {propertySymbol.Type.ToUnityString()} {symbol.Name} {{ {getter.Item1} {setter.Item1} }}"; - classTemplate.Insert("methods", impl); + proxyTemplate.InsertMethods(impl); // declaredMethods.Add(impl); break; case IEventSymbol eventSymbol: - classTemplate.Insert("methods", - $"public event {eventSymbol.Type.ToUnityString()}? {eventSymbol.Name};"); + proxyTemplate.InsertMethods($"public event {eventSymbol.Type.ToUnityString()}? {eventSymbol.Name};"); // declaredMethods.Add( // $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};"); break; } - GenerateEventImplementation(classTemplate, classSymbol, invokers, context); + GenerateEventImplementation(proxyTemplate, methodRepoTemplate, typeBinder, classSymbol, invokers, context); var endInvokers = invokers.Count; - _codeTemplate.IndexerProvider.Insert("indexSpan", - $"{{ typeof({originalName}), new[] {{ {CodegenUtilities.JoinWithComa(Enumerable.Range(startInvokers, endInvokers - startInvokers).Select(i => i.ToString()))} }} }},"); - classTemplate.AddDefine("className", className); - classTemplate.AddDefine("originalName", originalName); - classTemplate.AddDefine("namespaceName", namespaceName); + indexProviderTemplate.InsertIndexSpan($"{{ typeof({originalName}), new[] {{ {CodegenUtilities.JoinWithComa(Enumerable.Range(startInvokers, endInvokers - startInvokers).Select(i => i.ToString()))} }} }},"); + proxyTemplate.DefineClassName(className); + proxyTemplate.DefineOriginalName(originalName); + proxyTemplate.DefineNamespaceName(namespaceName); - var code = classTemplate.Compile(); + var code = proxyTemplate.Compile(); // Add the source code to the compilation. #if !DONT_ADD context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8)); #endif - _codeTemplate.IndexerProvider.Insert("remoteTypePair", - $"{{ typeof({classSymbol.ToUnityString()}), (id, r, c, indices) => new {namespaceName}.{className}(id, r, c, indices) }}"); + indexProviderTemplate.InsertRemoteTypePair($"{{ typeof({classSymbol.ToUnityString()}), (id, r, c, indices) => new {namespaceName}.{className}(id, r, c, indices) }}"); } if (totalMethods.Count != 0) { - var coCodegenRepoCode = _codeTemplate.MethodRepo.Compile(); - _codeTemplate.IndexerProvider.AddDefine("level", apiLevel.ToString()); - _codeTemplate.IndexerProvider.AddDefine("len", invokers.Count.ToString()); + var coCodegenRepoCode = methodRepoTemplate.Compile(); + indexProviderTemplate.DefineLevel(apiLevel.ToString()); + indexProviderTemplate.DefineLen(invokers.Count.ToString()); - var providerCode = _codeTemplate.IndexerProvider.Compile(); + var providerCode = indexProviderTemplate.Compile(); #if !DONT_ADD context.AddSource("GeneratedInvokersCollection.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8)); @@ -177,16 +176,16 @@ namespace mROA.Codegen #endif } - if (_codeTemplate.IndexerProvider["remoteTypePair+"] != null) + if (indexProviderTemplate.IsRemoteTypePairInserted()) { - var frontendRepoCode = _codeTemplate.RemoteTypeBinder.Compile(); + var frontendRepoCode = typeBinder.Compile(); #if !DONT_ADD context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(frontendRepoCode, Encoding.UTF8)); #endif } } - private void GenerateEventImplementation(TemplateDocument classTemplate, INamedTypeSymbol classSymbol, + private void GenerateEventImplementation(ProxyTemplate proxyTemplate, MethodRepoTemplate methodRepoTemplate, RemoteTypeBinderTemplate remoteTypeBinder, INamedTypeSymbol classSymbol, List invokers, SourceProductionContext context) { var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers()) @@ -194,28 +193,26 @@ namespace mROA.Codegen if (events.Count == 0) return; - var interfaceTemplate = (TemplateDocument)_codeTemplate.PartialInterface.Clone(); - interfaceTemplate.AddDefine("name", classSymbol.Name); - interfaceTemplate.AddDefine("namespace", classSymbol.ContainingNamespace.ToDisplayString()); - var objectBinderTemplate = - (TemplateDocument)((InnerTemplateSection)_codeTemplate.RemoteTypeBinder["objectBinderTemplate"]!) - .InnerTemplate - .Clone(); + var partialInterfaceTemplate = new PartialInterfaceTemplate(); + partialInterfaceTemplate.DefineName(classSymbol.Name); + partialInterfaceTemplate.DefineNamespace(classSymbol.ContainingNamespace.ToDisplayString()); + + var objectBinderTemplate = remoteTypeBinder.CloneInnerObjectBinder(); foreach (var currentEvent in events) { var additionalMethod = GenerateMethodExternalCaller(currentEvent, out var signature); - classTemplate.Insert("methods", additionalMethod); + proxyTemplate.InsertMethods(additionalMethod); // declaredMethods.Add(additionalMethod); - interfaceTemplate.Insert("signature", signature); - GenerateEventCode(currentEvent, invokers, classSymbol); - GenerateBinderCode(currentEvent, classSymbol, objectBinderTemplate); + partialInterfaceTemplate.InsertSignature(signature); + GenerateEventCode(methodRepoTemplate, currentEvent, invokers, classSymbol); + GenerateBinderCode(objectBinderTemplate, currentEvent, classSymbol); } - - objectBinderTemplate.AddDefine("type", classSymbol.ToUnityString()); - var partialInterface = interfaceTemplate.Compile(); + + objectBinderTemplate.DefineType(classSymbol.ToUnityString()); + var partialInterface = partialInterfaceTemplate.Compile(); var binder = objectBinderTemplate.Compile(); - _codeTemplate.RemoteTypeBinder.Insert("eventBinder", binder); + remoteTypeBinder.InsertEventBinder(binder); #if !DONT_ADD context.AddSource($"{classSymbol.Name}.g.cs", SourceText.From(partialInterface, Encoding.UTF8)); @@ -239,7 +236,7 @@ namespace mROA.Codegen return caller; } - private void GenerateDeclaredMethod(TemplateDocument classTemplate, IMethodSymbol method, List invokers, + private void GenerateDeclaredMethod(ProxyTemplate proxyTemplate, MethodRepoTemplate methodRepoTemplate, IMethodSymbol method, List invokers, INamedTypeSymbol baseInterface) { var sb = new StringBuilder(); @@ -311,7 +308,7 @@ namespace mROA.Codegen sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";"); sb.AppendLine("\t\t}"); - classTemplate.Insert("methods", sb.ToString()); + proxyTemplate.InsertMethods(sb.ToString()); // declaredMethods.Add(sb.ToString()); var parameterTypes = string.Join(", ", @@ -356,38 +353,35 @@ namespace mROA.Codegen if (isAsync) { - var invokerTemplate = - (TemplateDocument)((InnerTemplateSection)_codeTemplate.MethodRepo["asyncInvoker"]!).InnerTemplate - .Clone(); - invokerTemplate.AddDefine("isVoid", isVoid.ToString().ToLower()); - invokerTemplate.AddDefine("returnType", CodegenUtilities.ExtractTaskType(method.ReturnType)); - invokerTemplate.AddDefine("parametersType", parameterTypes); - invokerTemplate.AddDefine("suitableType", baseInterface.ToUnityString()); - invokerTemplate.AddDefine("funcInvoking", funcInvoking); - invokerTemplate.AddDefine("isTrusted", (!isUntrusted).ToString().ToLower()); + var invokerTemplate = methodRepoTemplate.CloneInnerAsyncInvoker(); + invokerTemplate.DefineIsVoid(isVoid.ToString().ToLower()); + invokerTemplate.DefineReturnType(CodegenUtilities.ExtractTaskType(method.ReturnType)); + invokerTemplate.DefineParametersType(parameterTypes); + invokerTemplate.DefineSuitableType(baseInterface.ToUnityString()); + invokerTemplate.DefineFuncInvoking(funcInvoking); + invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower()); backend = invokerTemplate.Compile(); } else { - var invokerTemplate = (TemplateDocument)_codeTemplate.MethodInvoker.Clone(); - invokerTemplate.AddDefine("isVoid", isVoid.ToString().ToLower()); - invokerTemplate.AddDefine("returnType", isVoid ? "void" : method.ReturnType.ToUnityString()); - invokerTemplate.AddDefine("parametersType", parameterTypes); - invokerTemplate.AddDefine("suitableType", baseInterface.ToUnityString()); - invokerTemplate.AddDefine("funcInvoking", funcInvoking); - invokerTemplate.AddDefine("isTrusted", (!isUntrusted).ToString().ToLower()); + var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker(); + invokerTemplate.DefineIsVoid(isVoid.ToString().ToLower()); + invokerTemplate.DefineReturnType(isVoid ? "void" : method.ReturnType.ToUnityString()); + invokerTemplate.DefineParametersType(parameterTypes); + invokerTemplate.DefineSuitableType(baseInterface.ToUnityString()); + invokerTemplate.DefineFuncInvoking(funcInvoking); + invokerTemplate.DefineIsTrusted((!isUntrusted).ToString().ToLower()); backend = invokerTemplate.Compile(); } - _codeTemplate.MethodRepo.Insert("invoker", backend); + methodRepoTemplate.InsertInvoke(backend); invokers.Add(backend); } - private void GenerateBinderCode(IEventSymbol eventSymbol, INamedTypeSymbol baseType, TemplateDocument document) + private void GenerateBinderCode(ObjectBinderTemplate objectBinderTemplate, IEventSymbol eventSymbol, INamedTypeSymbol baseType) { - var eventBinderTemplate = - (TemplateDocument)((InnerTemplateSection)document["eventBinderTemplate"]!).InnerTemplate.Clone(); + var eventBinderTemplate = objectBinderTemplate.CloneInnerEventBinder(); var index = _currentInternalCallIndex; var parameters = (eventSymbol.Type as INamedTypeSymbol)!.TypeArguments.ToList(); @@ -399,25 +393,24 @@ namespace mROA.Codegen var transferParameters = CodegenUtilities.JoinWithComa(parameters.Select(i => (i, pi++)) .Where(i => !ParameterFilterForType(i.i)) .Select(i => "p" + i.Item2)); - + var requestIndex = parameters.FindIndex(i => i.Name == "RequestContext"); if (requestIndex != -1) { 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.AddDefine("eventName", eventSymbol.Name); - eventBinderTemplate.AddDefine("parametersDeclaration", parametersDeclaration); - eventBinderTemplate.AddDefine("commandId", - $"context.CallIndexProvider.GetIndices(typeof({baseType.ToUnityString()}))[{index}]"); - eventBinderTemplate.AddDefine("transferParameters", transferParameters); + eventBinderTemplate.DefineType(baseType.ToUnityString()); + eventBinderTemplate.DefineEventName(eventSymbol.Name); + eventBinderTemplate.DefineParametersDeclaration(parametersDeclaration); + eventBinderTemplate.DefineCommandIdTag($"context.CallIndexProvider.GetIndices(typeof({baseType.ToUnityString()}))[{index}]"); + eventBinderTemplate.DefineTransferParameters(transferParameters); var eventBinderCode = eventBinderTemplate.Compile(); - document.Insert("eventBinder", eventBinderCode); + objectBinderTemplate.InsertEventBinder(eventBinderCode); } - private void GenerateEventCode(IEventSymbol eventSymbol, List invokers, ITypeSymbol baseInterface) + private void GenerateEventCode(MethodRepoTemplate methodRepoTemplate, IEventSymbol eventSymbol, List invokers, ITypeSymbol baseInterface) { var level = "\t\t\t"; @@ -453,21 +446,21 @@ namespace mROA.Codegen {level} return null; {level} }}"; - var invokerTemplate = (TemplateDocument)_codeTemplate.MethodInvoker.Clone(); - invokerTemplate.AddDefine("isVoid", "true"); - invokerTemplate.AddDefine("returnType", "void"); - invokerTemplate.AddDefine("parametersType", parameterTypes); - invokerTemplate.AddDefine("suitableType", baseInterface.ToUnityString()); - invokerTemplate.AddDefine("funcInvoking", funcInvoking); - invokerTemplate.AddDefine("isTrusted", "true"); + var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker(); + invokerTemplate.DefineIsVoid("true"); + invokerTemplate.DefineReturnType("void"); + invokerTemplate.DefineParametersType(parameterTypes); + invokerTemplate.DefineSuitableType(baseInterface.ToUnityString()); + invokerTemplate.DefineFuncInvoking(funcInvoking); + invokerTemplate.DefineIsTrusted("true"); var backend = invokerTemplate.Compile(); - _codeTemplate.MethodRepo.Insert("invoker", backend); + methodRepoTemplate.InsertInvoke(backend); invokers.Add(backend); } - private void GeneratePropertyMethod(IMethodSymbol method, - List<(string, IMethodSymbol)> propsCollection, List invokers, INamedTypeSymbol baseInterace) + private void GeneratePropertyMethod(MethodRepoTemplate methodRepoTemplate, IMethodSymbol method, + List<(string, IMethodSymbol)> propsCollection, List invokers, INamedTypeSymbol baseInterface) { string frontend; string backend; @@ -485,26 +478,25 @@ namespace mROA.Codegen method.Parameters.Select(p => CodegenUtilities.Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]"))); - var invokerTemplate = (TemplateDocument)_codeTemplate.MethodInvoker.Clone(); - invokerTemplate.AddDefine("isVoid", "false"); - invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString()); - invokerTemplate.AddDefine("parametersType", parameterTypes); - invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString()); - invokerTemplate.AddDefine("funcInvoking", - $"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}]"); - invokerTemplate.AddDefine("isTrusted", "true"); + var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker(); + invokerTemplate.DefineIsVoid("false"); + invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString()); + invokerTemplate.DefineParametersType(parameterTypes); + invokerTemplate.DefineSuitableType(baseInterface.ToUnityString()); + invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}]"); + invokerTemplate.DefineIsTrusted("true"); backend = invokerTemplate.Compile(); } else { - var invokerTemplate = (TemplateDocument)_codeTemplate.MethodInvoker.Clone(); - invokerTemplate.AddDefine("isVoid", "false"); - invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString()); - invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString()); - invokerTemplate.AddDefine("funcInvoking", - $"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name}"); - invokerTemplate.AddDefine("isTrusted", "true"); + var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker(); + invokerTemplate.DefineIsVoid("false"); + invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString()); + invokerTemplate.DefineParametersType(""); + invokerTemplate.DefineSuitableType(baseInterface.ToUnityString()); + invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name}"); + invokerTemplate.DefineIsTrusted("true"); backend = invokerTemplate.Compile(); } @@ -527,31 +519,26 @@ namespace mROA.Codegen var valueInsert = CodegenUtilities.Caster(method.Parameters.Last().Type, "parameters[" + (method.Parameters.Length - 1) + "]"); - var invokerTemplate = (TemplateDocument)_codeTemplate.MethodInvoker.Clone(); - - - invokerTemplate.AddDefine("isVoid", "true"); - invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString()); - invokerTemplate.AddDefine("parametersType", parameterTypes); - invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString()); - invokerTemplate.AddDefine("funcInvoking", - $"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}] = {valueInsert}"); - invokerTemplate.AddDefine("isTrusted", "true"); + + var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker(); + invokerTemplate.DefineIsVoid("true"); + invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString()); + invokerTemplate.DefineParametersType(parameterTypes); + invokerTemplate.DefineSuitableType(baseInterface.ToUnityString()); + invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}] = {valueInsert}"); + invokerTemplate.DefineIsTrusted("true"); backend = invokerTemplate.Compile(); } else { - var invokerTemplate = (TemplateDocument)_codeTemplate.MethodInvoker.Clone(); - - invokerTemplate.AddDefine("isVoid", "true"); - invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString()); - invokerTemplate.AddDefine("parametersType", - $"typeof({method.Parameters.First().Type.ToUnityString()})"); - invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString()); - invokerTemplate.AddDefine("funcInvoking", - $"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name} = {CodegenUtilities.Caster((method.AssociatedSymbol as IPropertySymbol)!.Type, "parameters[0]")}"); - invokerTemplate.AddDefine("isTrusted", "true"); + var invokerTemplate = methodRepoTemplate.CloneInnerSyncInvoker(); + invokerTemplate.DefineIsVoid("true"); + invokerTemplate.DefineReturnType(method.ReturnType.ToUnityString()); + invokerTemplate.DefineParametersType($"typeof({method.Parameters.First().Type.ToUnityString()})"); + invokerTemplate.DefineSuitableType(baseInterface.ToUnityString()); + invokerTemplate.DefineFuncInvoking($"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name} = {CodegenUtilities.Caster((method.AssociatedSymbol as IPropertySymbol)!.Type, "parameters[0]")}"); + invokerTemplate.DefineIsTrusted("true"); backend = invokerTemplate.Compile(); } @@ -561,7 +548,7 @@ namespace mROA.Codegen } propsCollection.Add((frontend, method)); - _codeTemplate.MethodRepo.Insert("invoker", backend); + methodRepoTemplate.InsertInvoke(backend); invokers.Add(backend); } }