Добавлена поддержка нескольких параметров в кодген

This commit is contained in:
2025-03-07 09:01:21 +03:00
parent c802f337c7
commit 8d082d1ed4
9 changed files with 80 additions and 25 deletions
+10 -2
View File
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Example.Shared; using Example.Shared;
@@ -5,7 +6,6 @@ namespace Example.Backend
{ {
public class PagesList : IPagesList public class PagesList : IPagesList
{ {
public IReadOnlyList<IPage> Collection { get; }
public IPage Get(int index) public IPage Get(int index)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
@@ -16,9 +16,17 @@ namespace Example.Backend
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
public void Set(int index, IPage item) public void Remove(int index, IPage item)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
public event Action<IPage>? OnAdd;
public event Action<IPage>? OnRemove;
public void Dispose()
{
// TODO release managed resources here
}
} }
} }
+9 -3
View File
@@ -9,20 +9,26 @@ namespace Example.Backend
public class Printer : IPrinter public class Printer : IPrinter
{ {
public string Name; public string Name;
public string GetName() public string GetName()
{ {
return Name; return Name;
} }
public async Task<IPage> Print(string text, CancellationToken cancellationToken = default) public async Task<IPage> Print(string text, bool some, CancellationToken cancellationToken = default)
{ {
// throw new Exception("The method or operation is not implemented."); // 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<IPage>? OnPrint;
public void Dispose() 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);
} }
} }
} }
+13 -1
View File
@@ -8,6 +8,16 @@ namespace Example.Frontend
{ {
public class ClientBasedPrinter : IPrinter 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() public string GetName()
{ {
Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)"); Console.WriteLine("ClientBasedPrinter called from server!!!!!!!!!!! Vova likes that:)");
@@ -15,13 +25,15 @@ namespace Example.Frontend
return "ClientBasedPrinter from mroa"; return "ClientBasedPrinter from mroa";
} }
public async Task<IPage> Print(string text, CancellationToken cancellationToken) public async Task<IPage> Print(string text, bool some, CancellationToken cancellationToken)
{ {
Console.WriteLine($"Printed: {text}"); Console.WriteLine($"Printed: {text}");
await Task.Yield(); await Task.Yield();
return new ClientBasedPage(); return new ClientBasedPage();
} }
public event Action<IPage>? OnPrint;
public void Dispose() public void Dispose()
{ {
+1 -1
View File
@@ -72,7 +72,7 @@ class Program
Console.WriteLine(string.Join(", ", names)); 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 printed");
Console.WriteLine(page.ToString()); Console.WriteLine(page.ToString());
var data = page.GetData(); var data = page.GetData();
+3 -1
View File
@@ -10,6 +10,8 @@ namespace Example.Shared
IReadOnlyList<T> Collection { get; } IReadOnlyList<T> Collection { get; }
T Get(int index); T Get(int index);
void Add(T item); void Add(T item);
void Set(int index, T item); void Remove(int index, T item);
event Action<T> OnAdd;
event Action<T> OnRemove;
} }
} }
+2 -1
View File
@@ -10,6 +10,7 @@ namespace Example.Shared
public interface IPrinter : IDisposable, IShared public interface IPrinter : IDisposable, IShared
{ {
string GetName(); string GetName();
Task<IPage> Print(string text, CancellationToken cancellationToken); Task<IPage> Print(string text, bool someParameter, CancellationToken cancellationToken);
event Action<IPage> OnPrint;
} }
} }
+5
View File
@@ -32,5 +32,10 @@
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" /> <None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Remove="test.tpt" />
<EmbeddedResource Include="test.tpt" />
</ItemGroup>
</Project> </Project>
+31 -11
View File
@@ -1,7 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -20,6 +22,12 @@ namespace mROA.Codegen
private void GenerateCode(GeneratorExecutionContext context, Compilation compilation, private void GenerateCode(GeneratorExecutionContext context, Compilation compilation,
ImmutableArray<InterfaceDeclarationSyntax> classes) ImmutableArray<InterfaceDeclarationSyntax> 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 methods = new List<(string, IMethodSymbol)>();
var frontendContextRepo = new List<string>(); var frontendContextRepo = new List<string>();
@@ -33,16 +41,21 @@ namespace mROA.Codegen
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
var className = classDeclarationSyntax.Identifier.Text; 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; var originalName = className;
className = className.TrimStart('I') + "RemoteEndpoint"; className = className.TrimStart('I') + "RemoteEndpoint";
var methodsText = new List<string>(); var remoteEndpointMember = new List<string>();
foreach (var method in methodBody) foreach (var method in innerMembers.OfType<IMethodSymbol>())
{ {
if (method.MethodKind is MethodKind.EventAdd or MethodKind.EventRemove)
continue;
var index = methods.Count; var index = methods.Count;
methods.Add((namespaceName + "." + originalName, method)); methods.Add((namespaceName + "." + originalName, method));
var sb = new StringBuilder(); var sb = new StringBuilder();
@@ -52,13 +65,16 @@ namespace mROA.Codegen
bool isAsync; bool isAsync;
bool isVoid; bool isVoid;
List<IParameterSymbol>? parameters;
switch (method.ReturnType) switch (method.ReturnType)
{ {
case INamedTypeSymbol namedType: case INamedTypeSymbol namedType:
isAsync = namedType.Name == "Task"; isAsync = namedType.Name == "Task";
isVoid = isAsync && namedType.TypeParameters.Length == 0 || namedType.Name == "Void"; isVoid = isAsync && namedType.TypeParameters.Length == 0 || namedType.Name == "Void";
isParametrized = method.Parameters.Length == 1 && !isAsync || parameters = method.Parameters.ToList();
method.Parameters.Length == 2 && isAsync; parameters.RemoveAll(i => i.Type.Name is "CancellationToken" or "RequestContext");
isParametrized = parameters.Count != 0;
break; break;
case IArrayTypeSymbol: case IArrayTypeSymbol:
isAsync = false; isAsync = false;
@@ -77,8 +93,10 @@ namespace mROA.Codegen
var prefix = isAsync ? "await " : ""; var prefix = isAsync ? "await " : "";
var postfix = !isAsync ? (isVoid ? ".Wait()" : ".GetAwaiter().GetResult()") : ""; var postfix = !isAsync ? isVoid ? ".Wait()" : ".GetAwaiter().GetResult()" : "";
var parameterLink = isParametrized ? ", " + method.Parameters.First().Name : string.Empty; var parameterLink = isParametrized
? ", new object[] {" + string.Join(", ", method.Parameters.Select(i => i.Name)) + "}"
: string.Empty;
var tokenInsert = isAsync var tokenInsert = isAsync
? isParametrized ? isParametrized
? ", cancellationToken : " + method.Parameters[1].Name ? ", cancellationToken : " + method.Parameters[1].Name
@@ -97,7 +115,7 @@ namespace mROA.Codegen
sb.AppendLine("\t\t}"); sb.AppendLine("\t\t}");
methodsText.Add(sb.ToString()); remoteEndpointMember.Add(sb.ToString());
} }
var code = $@"// <auto-generated/> var code = $@"// <auto-generated/>
@@ -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<AttributeListSyntax> attributes, GeneratorExecutionContext context, private bool ContainsSOIAttribute(SyntaxList<AttributeListSyntax> attributes, GeneratorExecutionContext context,
InterfaceDeclarationSyntax interfaceDeclarationSyntax) 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) if (context.Compilation.GetSemanticModel(interfaceDeclarationSyntax.SyntaxTree)
.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol) .GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
@@ -259,7 +278,7 @@ namespace mROA.Codegen
return false; return false;
} }
private List<IMethodSymbol> CollectMethods(INamedTypeSymbol type) 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) foreach (var inner in type.AllInterfaces)
@@ -267,6 +286,7 @@ namespace mROA.Codegen
methods.AddRange(inner.GetMembers().OfType<IMethodSymbol>()); methods.AddRange(inner.GetMembers().OfType<IMethodSymbol>());
} }
methods.RemoveAll(m => m.Name == "Dispose");
return methods.OrderBy(i => i.Name).ToList(); return methods.OrderBy(i => i.Name).ToList();
} }
} }
+1
View File
@@ -0,0 +1 @@
test text