Генерация кода для геттеров и сеттеров свойств и индексаторов
This commit is contained in:
@@ -8,6 +8,7 @@ namespace Example.Shared
|
|||||||
public interface IDataList<T> : IShared, IDisposable
|
public interface IDataList<T> : IShared, IDisposable
|
||||||
{
|
{
|
||||||
IReadOnlyList<T> Collection { get; }
|
IReadOnlyList<T> Collection { get; }
|
||||||
|
T this[int index] { get; set; }
|
||||||
T Get(int index);
|
T Get(int index);
|
||||||
void Add(T item);
|
void Add(T item);
|
||||||
void Remove(int index, T item);
|
void Remove(int index, T item);
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ namespace mROA.Codegen
|
|||||||
// var test = asm.GetManifestResourceStream("mROA.Codegen.test.tpt");
|
// var test = asm.GetManifestResourceStream("mROA.Codegen.test.tpt");
|
||||||
// var reader = new StreamReader(test);
|
// var reader = new StreamReader(test);
|
||||||
// var allText = reader.ReadToEnd();
|
// var allText = reader.ReadToEnd();
|
||||||
var methods = new List<(string, IMethodSymbol)>();
|
|
||||||
var frontendContextRepo = new List<string>();
|
var frontendContextRepo = new List<string>();
|
||||||
|
|
||||||
|
List<IMethodSymbol> innerMethods = new List<IMethodSymbol>();
|
||||||
var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList();
|
var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList();
|
||||||
foreach (var classDeclarationSyntax in declarations)
|
foreach (var classDeclarationSyntax in declarations)
|
||||||
{
|
{
|
||||||
@@ -41,81 +41,36 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
|
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
|
||||||
var className = classDeclarationSyntax.Identifier.Text;
|
var className = classDeclarationSyntax.Identifier.Text;
|
||||||
var innerMembers = CollectMembers(classSymbol);
|
innerMethods = CollectMembers(classSymbol)
|
||||||
var associated = innerMembers.Select(i => i.AssociatedSymbol).Where(i => i != null).Select(i => i!).Distinct(SymbolEqualityComparer.Default).ToList();
|
.Where(i => i.MethodKind != MethodKind.EventAdd || i.MethodKind != MethodKind.EventRemove)
|
||||||
|
.ToList();
|
||||||
|
var associated = innerMethods.Select(i => i.AssociatedSymbol as IPropertySymbol).Where(i => i != null)
|
||||||
|
.Select(i => i!).Distinct(SymbolEqualityComparer.Default).Cast<IPropertySymbol>().ToList();
|
||||||
|
|
||||||
var originalName = className;
|
var originalName = className;
|
||||||
|
|
||||||
className = className.TrimStart('I') + "RemoteEndpoint";
|
className = className.TrimStart('I') + "RemoteEndpoint";
|
||||||
|
|
||||||
var remoteEndpointMember = new List<string>();
|
|
||||||
|
var declaredMethods = new List<string>();
|
||||||
foreach (var method in innerMembers.OfType<IMethodSymbol>())
|
var propertiesAccessMethods = new List<(string, IMethodSymbol)>();
|
||||||
|
var propertiesImplementations = new List<string>(associated.Count);
|
||||||
|
foreach (var method in innerMethods)
|
||||||
{
|
{
|
||||||
if (method.MethodKind is MethodKind.EventAdd or MethodKind.EventRemove)
|
switch (method.MethodKind)
|
||||||
continue;
|
|
||||||
|
|
||||||
|
|
||||||
var index = methods.Count;
|
|
||||||
methods.Add((namespaceName + "." + originalName, method));
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
|
|
||||||
bool isParametrized;
|
|
||||||
|
|
||||||
bool isAsync;
|
|
||||||
bool isVoid;
|
|
||||||
|
|
||||||
List<IParameterSymbol>? parameters;
|
|
||||||
|
|
||||||
switch (method.ReturnType)
|
|
||||||
{
|
{
|
||||||
case INamedTypeSymbol namedType:
|
case MethodKind.PropertyGet or MethodKind.PropertySet:
|
||||||
isAsync = namedType.Name == "Task";
|
GeneratePropertyMethod(method, innerMethods, propertiesAccessMethods);
|
||||||
isVoid = isAsync && namedType.TypeParameters.Length == 0 || namedType.Name == "Void";
|
|
||||||
parameters = method.Parameters.ToList();
|
|
||||||
parameters.RemoveAll(i => i.Type.Name is "CancellationToken" or "RequestContext");
|
|
||||||
isParametrized = parameters.Count != 0;
|
|
||||||
break;
|
|
||||||
case IArrayTypeSymbol:
|
|
||||||
isAsync = false;
|
|
||||||
isVoid = false;
|
|
||||||
isParametrized = method.Parameters.Length != 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
continue;
|
continue;
|
||||||
|
default:
|
||||||
|
GenerateDeclaretedMethod(method, declaredMethods, innerMethods);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Creating signature
|
foreach (var prop in associated)
|
||||||
sb.AppendLine("public" + (isAsync
|
{
|
||||||
? " async "
|
var start = $"public {prop.Type.ToDisplayString()} {prop.Name}";
|
||||||
: " ") +
|
|
||||||
$"{method.ReturnType.ToDisplayString()} {method.Name}({string.Join(", ", method.Parameters.Select(ToFullString))}){{");
|
|
||||||
|
|
||||||
|
|
||||||
var prefix = isAsync ? "await " : "";
|
|
||||||
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
|
|
||||||
: ", cancellationToken : " + method.Parameters[0].Name
|
|
||||||
: String.Empty;
|
|
||||||
var caller = isVoid
|
|
||||||
? $"CallAsync({index}{parameterLink}{tokenInsert})"
|
|
||||||
: isAsync
|
|
||||||
? $"GetResultAsync<{ExtractTaskType(method.ReturnType)}>({index}{parameterLink}{tokenInsert})"
|
|
||||||
: $"GetResultAsync<{ToFullString(method.ReturnType)}>({index}{parameterLink}{tokenInsert})";
|
|
||||||
|
|
||||||
if (!isVoid)
|
|
||||||
prefix = "return " + prefix;
|
|
||||||
|
|
||||||
sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";");
|
|
||||||
|
|
||||||
sb.AppendLine("\t\t}");
|
|
||||||
|
|
||||||
remoteEndpointMember.Add(sb.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var code = $@"// <auto-generated/>
|
var code = $@"// <auto-generated/>
|
||||||
@@ -134,7 +89,7 @@ namespace {namespaceName}
|
|||||||
{{
|
{{
|
||||||
}}
|
}}
|
||||||
|
|
||||||
{string.Join("\r\n\t", remoteEndpointMember)}
|
{string.Join("\r\n\t", declaredMethods)}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
";
|
";
|
||||||
@@ -147,7 +102,7 @@ namespace {namespaceName}
|
|||||||
$"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}");
|
$"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (methods.Count != 0)
|
if (innerMethods.Count != 0)
|
||||||
{
|
{
|
||||||
var methodsStringed = Array.Empty<string>();
|
var methodsStringed = Array.Empty<string>();
|
||||||
|
|
||||||
@@ -210,6 +165,101 @@ namespace mROA.Codegen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GenerateDeclaretedMethod(IMethodSymbol method, List<string> declaretedMethods,
|
||||||
|
List<IMethodSymbol> methods)
|
||||||
|
{
|
||||||
|
var index = methods.IndexOf(method);
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
bool isParametrized;
|
||||||
|
|
||||||
|
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";
|
||||||
|
parameters = method.Parameters.ToList();
|
||||||
|
parameters.RemoveAll(i => i.Type.Name is "CancellationToken" or "RequestContext");
|
||||||
|
isParametrized = parameters.Count != 0;
|
||||||
|
break;
|
||||||
|
case IArrayTypeSymbol:
|
||||||
|
isAsync = false;
|
||||||
|
isVoid = false;
|
||||||
|
isParametrized = method.Parameters.Length != 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Creating signature
|
||||||
|
sb.AppendLine("public" + (isAsync
|
||||||
|
? " async "
|
||||||
|
: " ") +
|
||||||
|
$"{method.ReturnType.ToDisplayString()} {method.Name}({string.Join(", ", method.Parameters.Select(ToFullString))}){{");
|
||||||
|
|
||||||
|
|
||||||
|
var prefix = isAsync ? "await " : "";
|
||||||
|
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
|
||||||
|
: ", cancellationToken : " + method.Parameters[0].Name
|
||||||
|
: String.Empty;
|
||||||
|
var caller = isVoid
|
||||||
|
? $"CallAsync({index}{parameterLink}{tokenInsert})"
|
||||||
|
: isAsync
|
||||||
|
? $"GetResultAsync<{ExtractTaskType(method.ReturnType)}>({index}{parameterLink}{tokenInsert})"
|
||||||
|
: $"GetResultAsync<{ToFullString(method.ReturnType)}>({index}{parameterLink}{tokenInsert})";
|
||||||
|
|
||||||
|
if (!isVoid)
|
||||||
|
prefix = "return " + prefix;
|
||||||
|
|
||||||
|
sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";");
|
||||||
|
|
||||||
|
sb.AppendLine("\t\t}");
|
||||||
|
|
||||||
|
declaretedMethods.Add(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GeneratePropertyMethod(IMethodSymbol method, List<IMethodSymbol> methods,
|
||||||
|
List<(string, IMethodSymbol)> propsCollection)
|
||||||
|
{
|
||||||
|
var index = methods.IndexOf(method);
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
if (method.MethodKind == MethodKind.PropertyGet)
|
||||||
|
{
|
||||||
|
var parametersArray = "";
|
||||||
|
if (method.Parameters.Length != 0)
|
||||||
|
{
|
||||||
|
parametersArray = $", new object[] {{{string.Join(", ", method.Parameters.Select(p => p.Name))}}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine(
|
||||||
|
$"get => GetResultAsync<{method.ReturnType.ToDisplayString()}>({index}{parametersArray}).Wait();");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var parametersArray = "";
|
||||||
|
if (method.Parameters.Length != 0)
|
||||||
|
{
|
||||||
|
parametersArray = ", " + string.Join(", ", method.Parameters.Select(p => p.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine(
|
||||||
|
$"set => CallAsync({index}, new object[] {{ value{parametersArray} }}).GetAwaiter().GetResult();");
|
||||||
|
}
|
||||||
|
|
||||||
|
propsCollection.Add((sb.ToString(), method));
|
||||||
|
}
|
||||||
|
|
||||||
private static string ToFullString(IParameterSymbol parameter)
|
private static string ToFullString(IParameterSymbol parameter)
|
||||||
=> /*parameter.Type.ContainingNamespace is null*/
|
=> /*parameter.Type.ContainingNamespace is null*/
|
||||||
/*?*/ parameter.ToDisplayString();
|
/*?*/ parameter.ToDisplayString();
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ namespace mROA.Implementation.Frontend
|
|||||||
messageType: MessageType.CancelRequest, token: token);
|
messageType: MessageType.CancelRequest, token: token);
|
||||||
|
|
||||||
Task.WaitAny(defaultRequest, cancelRequest);
|
Task.WaitAny(defaultRequest, cancelRequest);
|
||||||
|
|
||||||
#if TRACE
|
#if TRACE
|
||||||
Console.WriteLine("Request received");
|
Console.WriteLine("Request received");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user