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

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 Example.Shared;
@@ -5,7 +6,6 @@ namespace Example.Backend
{
public class PagesList : IPagesList
{
public IReadOnlyList<IPage> 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<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 string Name;
public string GetName()
{
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.");
return new Page {Text = text};
var page = new Page { Text = text };
OnPrint?.Invoke(page);
return page;
}
public event Action<IPage>? 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);
}
}
}
+13 -1
View File
@@ -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<IPage> Print(string text, CancellationToken cancellationToken)
public async Task<IPage> Print(string text, bool some, CancellationToken cancellationToken)
{
Console.WriteLine($"Printed: {text}");
await Task.Yield();
return new ClientBasedPage();
}
public event Action<IPage>? OnPrint;
public void Dispose()
{
+1 -1
View File
@@ -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();
+3 -1
View File
@@ -10,6 +10,8 @@ namespace Example.Shared
IReadOnlyList<T> Collection { get; }
T Get(int index);
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
{
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" />
</ItemGroup>
<ItemGroup>
<None Remove="test.tpt" />
<EmbeddedResource Include="test.tpt" />
</ItemGroup>
</Project>
+31 -11
View File
@@ -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,6 +22,12 @@ namespace mROA.Codegen
private void GenerateCode(GeneratorExecutionContext context, Compilation compilation,
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 frontendContextRepo = new List<string>();
@@ -33,16 +41,21 @@ namespace mROA.Codegen
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<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;
methods.Add((namespaceName + "." + originalName, method));
var sb = new StringBuilder();
@@ -52,13 +65,16 @@ namespace mROA.Codegen
bool isAsync;
bool isVoid;
List<IParameterSymbol>? 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 = $@"// <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,
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<IMethodSymbol> CollectMethods(INamedTypeSymbol type)
private List<IMethodSymbol> CollectMembers(INamedTypeSymbol type)
{
var methods = type.GetMembers().OfType<IMethodSymbol>().ToList();
foreach (var inner in type.AllInterfaces)
@@ -267,6 +286,7 @@ namespace mROA.Codegen
methods.AddRange(inner.GetMembers().OfType<IMethodSymbol>());
}
methods.RemoveAll(m => m.Name == "Dispose");
return methods.OrderBy(i => i.Name).ToList();
}
}
+1
View File
@@ -0,0 +1 @@
test text