From 8d082d1ed474918d93fd2264642e2e9e2098feb2 Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Fri, 7 Mar 2025 09:01:21 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B5=D1=81=D0=BA=D0=BE=D0=BB=D1=8C=D0=BA=D0=B8?= =?UTF-8?q?=D1=85=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B2=20=D0=BA=D0=BE=D0=B4=D0=B3=D0=B5=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Example.Backend/PagesList.cs | 12 +++++- Example.Backend/Printer.cs | 12 ++++-- Example.Frontend/ClientBasedPrinter.cs | 14 ++++++- Example.Frontend/Program.cs | 2 +- Example.Shared/IDataList.cs | 4 +- Example.Shared/IPrinter.cs | 3 +- mROA.Codegen/mROA.Codegen.csproj | 5 +++ mROA.Codegen/mROASourceGenerator.cs | 52 ++++++++++++++++++-------- mROA.Codegen/test.tpt | 1 + 9 files changed, 80 insertions(+), 25 deletions(-) create mode 100644 mROA.Codegen/test.tpt diff --git a/Example.Backend/PagesList.cs b/Example.Backend/PagesList.cs index 6505303..3e02b77 100644 --- a/Example.Backend/PagesList.cs +++ b/Example.Backend/PagesList.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Example.Shared; @@ -5,7 +6,6 @@ namespace Example.Backend { public class PagesList : IPagesList { - public IReadOnlyList Collection { get; } public IPage Get(int index) { throw new System.NotImplementedException(); @@ -16,9 +16,17 @@ namespace Example.Backend throw new System.NotImplementedException(); } - public void Set(int index, IPage item) + public void Remove(int index, IPage item) { throw new System.NotImplementedException(); } + + public event Action? OnAdd; + public event Action? OnRemove; + + public void Dispose() + { + // TODO release managed resources here + } } } \ No newline at end of file diff --git a/Example.Backend/Printer.cs b/Example.Backend/Printer.cs index 242b174..170ba16 100644 --- a/Example.Backend/Printer.cs +++ b/Example.Backend/Printer.cs @@ -9,20 +9,26 @@ namespace Example.Backend public class Printer : IPrinter { public string Name; + public string GetName() { return Name; } - public async Task Print(string text, CancellationToken cancellationToken = default) + public async Task Print(string text, bool some, CancellationToken cancellationToken = default) { // throw new Exception("The method or operation is not implemented."); - return new Page {Text = text}; + var page = new Page { Text = text }; + OnPrint?.Invoke(page); + return page; } + public event Action? OnPrint; + public void Dispose() { - Console.WriteLine("Dispose printer with name {0}, Dispose works, Dispose works, Dispose works, Dispose works,", Name); + Console.WriteLine( + "Dispose printer with name {0}, Dispose works, Dispose works, Dispose works, Dispose works,", Name); } } } \ No newline at end of file diff --git a/Example.Frontend/ClientBasedPrinter.cs b/Example.Frontend/ClientBasedPrinter.cs index 4d9c661..888e802 100644 --- a/Example.Frontend/ClientBasedPrinter.cs +++ b/Example.Frontend/ClientBasedPrinter.cs @@ -8,6 +8,16 @@ namespace Example.Frontend { public class ClientBasedPrinter : IPrinter { + public int Prop { get; set; } + public int get_Prop() + { + return 1; + } + + public int set_Prop(int value) + { + return 1; + } public string GetName() { Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)"); @@ -15,13 +25,15 @@ namespace Example.Frontend return "ClientBasedPrinter from mroa"; } - public async Task Print(string text, CancellationToken cancellationToken) + public async Task Print(string text, bool some, CancellationToken cancellationToken) { Console.WriteLine($"Printed: {text}"); await Task.Yield(); return new ClientBasedPage(); } + public event Action? OnPrint; + public void Dispose() { diff --git a/Example.Frontend/Program.cs b/Example.Frontend/Program.cs index d47c620..427df96 100644 --- a/Example.Frontend/Program.cs +++ b/Example.Frontend/Program.cs @@ -72,7 +72,7 @@ class Program Console.WriteLine(string.Join(", ", names)); - var page = disposingPrinter.Print("Test Page", new CancellationToken()).GetAwaiter().GetResult(); + var page = disposingPrinter.Print("Test Page", false, CancellationToken.None).GetAwaiter().GetResult(); Console.WriteLine("Page printed"); Console.WriteLine(page.ToString()); var data = page.GetData(); diff --git a/Example.Shared/IDataList.cs b/Example.Shared/IDataList.cs index c0e2cc7..eb62728 100644 --- a/Example.Shared/IDataList.cs +++ b/Example.Shared/IDataList.cs @@ -10,6 +10,8 @@ namespace Example.Shared IReadOnlyList Collection { get; } T Get(int index); void Add(T item); - void Set(int index, T item); + void Remove(int index, T item); + event Action OnAdd; + event Action OnRemove; } } \ No newline at end of file diff --git a/Example.Shared/IPrinter.cs b/Example.Shared/IPrinter.cs index c71c540..383961d 100644 --- a/Example.Shared/IPrinter.cs +++ b/Example.Shared/IPrinter.cs @@ -10,6 +10,7 @@ namespace Example.Shared public interface IPrinter : IDisposable, IShared { string GetName(); - Task Print(string text, CancellationToken cancellationToken); + Task Print(string text, bool someParameter, CancellationToken cancellationToken); + event Action OnPrint; } } \ No newline at end of file diff --git a/mROA.Codegen/mROA.Codegen.csproj b/mROA.Codegen/mROA.Codegen.csproj index 2a23fd6..c9257fd 100644 --- a/mROA.Codegen/mROA.Codegen.csproj +++ b/mROA.Codegen/mROA.Codegen.csproj @@ -31,6 +31,11 @@ + + + + + diff --git a/mROA.Codegen/mROASourceGenerator.cs b/mROA.Codegen/mROASourceGenerator.cs index 7881618..1fd31b3 100644 --- a/mROA.Codegen/mROASourceGenerator.cs +++ b/mROA.Codegen/mROASourceGenerator.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.IO; using System.Linq; +using System.Reflection; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -20,45 +22,59 @@ namespace mROA.Codegen private void GenerateCode(GeneratorExecutionContext context, Compilation compilation, ImmutableArray classes) { + // For future + // var asm = Assembly.GetAssembly(typeof(mROASourceGenerator)); + // var files = asm.GetManifestResourceNames(); + // var test = asm.GetManifestResourceStream("mROA.Codegen.test.tpt"); + // var reader = new StreamReader(test); + // var allText = reader.ReadToEnd(); var methods = new List<(string, IMethodSymbol)>(); var frontendContextRepo = new List(); var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList(); foreach (var classDeclarationSyntax in declarations) - { + { var semanticModel = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree); if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol) continue; - + var namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); var className = classDeclarationSyntax.Identifier.Text; - var methodBody = CollectMethods(classSymbol); + var innerMembers = CollectMembers(classSymbol); + var associated = innerMembers.Select(i => i.AssociatedSymbol).Where(i => i != null).Select(i => i!).Distinct(SymbolEqualityComparer.Default).ToList(); var originalName = className; - + className = className.TrimStart('I') + "RemoteEndpoint"; - var methodsText = new List(); - - foreach (var method in methodBody) + var remoteEndpointMember = new List(); + + foreach (var method in innerMembers.OfType()) { + if (method.MethodKind is MethodKind.EventAdd or MethodKind.EventRemove) + continue; + + var index = methods.Count; methods.Add((namespaceName + "." + originalName, method)); var sb = new StringBuilder(); - + bool isParametrized; bool isAsync; bool isVoid; + List? parameters; + switch (method.ReturnType) { case INamedTypeSymbol namedType: isAsync = namedType.Name == "Task"; isVoid = isAsync && namedType.TypeParameters.Length == 0 || namedType.Name == "Void"; - isParametrized = method.Parameters.Length == 1 && !isAsync || - method.Parameters.Length == 2 && isAsync; + parameters = method.Parameters.ToList(); + parameters.RemoveAll(i => i.Type.Name is "CancellationToken" or "RequestContext"); + isParametrized = parameters.Count != 0; break; case IArrayTypeSymbol: isAsync = false; @@ -77,8 +93,10 @@ namespace mROA.Codegen var prefix = isAsync ? "await " : ""; - var postfix = !isAsync ? (isVoid ? ".Wait()" : ".GetAwaiter().GetResult()") : ""; - var parameterLink = isParametrized ? ", " + method.Parameters.First().Name : string.Empty; + var postfix = !isAsync ? isVoid ? ".Wait()" : ".GetAwaiter().GetResult()" : ""; + var parameterLink = isParametrized + ? ", new object[] {" + string.Join(", ", method.Parameters.Select(i => i.Name)) + "}" + : string.Empty; var tokenInsert = isAsync ? isParametrized ? ", cancellationToken : " + method.Parameters[1].Name @@ -97,7 +115,7 @@ namespace mROA.Codegen sb.AppendLine("\t\t}"); - methodsText.Add(sb.ToString()); + remoteEndpointMember.Add(sb.ToString()); } var code = $@"// @@ -116,7 +134,7 @@ namespace {namespaceName} {{ }} - {string.Join("\r\n\t", methodsText)} + {string.Join("\r\n\t", remoteEndpointMember)} }} }} "; @@ -243,7 +261,8 @@ namespace mROA.Codegen private bool ContainsSOIAttribute(SyntaxList attributes, GeneratorExecutionContext context, InterfaceDeclarationSyntax interfaceDeclarationSyntax) { - foreach (var attributeSyntax in attributes.SelectMany(attributeListSyntax => attributeListSyntax.Attributes)) + foreach (var attributeSyntax in + attributes.SelectMany(attributeListSyntax => attributeListSyntax.Attributes)) { if (context.Compilation.GetSemanticModel(interfaceDeclarationSyntax.SyntaxTree) .GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol) @@ -259,7 +278,7 @@ namespace mROA.Codegen return false; } - private List CollectMethods(INamedTypeSymbol type) + private List CollectMembers(INamedTypeSymbol type) { var methods = type.GetMembers().OfType().ToList(); foreach (var inner in type.AllInterfaces) @@ -267,6 +286,7 @@ namespace mROA.Codegen methods.AddRange(inner.GetMembers().OfType()); } + methods.RemoveAll(m => m.Name == "Dispose"); return methods.OrderBy(i => i.Name).ToList(); } } diff --git a/mROA.Codegen/test.tpt b/mROA.Codegen/test.tpt new file mode 100644 index 0000000..c53ad17 --- /dev/null +++ b/mROA.Codegen/test.tpt @@ -0,0 +1 @@ +test text \ No newline at end of file