diff --git a/Example.Shared/IDataList.cs b/Example.Shared/IDataList.cs index eb62728..f08bb75 100644 --- a/Example.Shared/IDataList.cs +++ b/Example.Shared/IDataList.cs @@ -8,6 +8,7 @@ namespace Example.Shared public interface IDataList : IShared, IDisposable { IReadOnlyList Collection { get; } + T this[int index] { get; set; } T Get(int index); void Add(T item); void Remove(int index, T item); diff --git a/mROA.Codegen/mROASourceGenerator.cs b/mROA.Codegen/mROASourceGenerator.cs index 1fd31b3..2c31e16 100644 --- a/mROA.Codegen/mROASourceGenerator.cs +++ b/mROA.Codegen/mROASourceGenerator.cs @@ -28,9 +28,9 @@ namespace mROA.Codegen // 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(); + List innerMethods = new List(); var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList(); foreach (var classDeclarationSyntax in declarations) { @@ -41,81 +41,36 @@ namespace mROA.Codegen var namespaceName = classSymbol.ContainingNamespace.ToDisplayString(); var className = classDeclarationSyntax.Identifier.Text; - var innerMembers = CollectMembers(classSymbol); - var associated = innerMembers.Select(i => i.AssociatedSymbol).Where(i => i != null).Select(i => i!).Distinct(SymbolEqualityComparer.Default).ToList(); - + innerMethods = CollectMembers(classSymbol) + .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().ToList(); + var originalName = className; className = className.TrimStart('I') + "RemoteEndpoint"; - var remoteEndpointMember = new List(); - - foreach (var method in innerMembers.OfType()) + + var declaredMethods = new List(); + var propertiesAccessMethods = new List<(string, IMethodSymbol)>(); + var propertiesImplementations = new List(associated.Count); + foreach (var method in innerMethods) { - 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) + switch (method.MethodKind) { - 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: + case MethodKind.PropertyGet or MethodKind.PropertySet: + GeneratePropertyMethod(method, innerMethods, propertiesAccessMethods); continue; + default: + GenerateDeclaretedMethod(method, declaredMethods, innerMethods); + break; } + } - //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}"); - - remoteEndpointMember.Add(sb.ToString()); + foreach (var prop in associated) + { + var start = $"public {prop.Type.ToDisplayString()} {prop.Name}"; } var code = $@"// @@ -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}) }}"); } - if (methods.Count != 0) + if (innerMethods.Count != 0) { var methodsStringed = Array.Empty(); @@ -210,6 +165,101 @@ namespace mROA.Codegen } } + private void GenerateDeclaretedMethod(IMethodSymbol method, List declaretedMethods, + List methods) + { + var index = methods.IndexOf(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"; + 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 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) => /*parameter.Type.ContainingNamespace is null*/ /*?*/ parameter.ToDisplayString(); diff --git a/mROA/Implementation/Frontend/RequestExtractor.cs b/mROA/Implementation/Frontend/RequestExtractor.cs index c08f21a..751e10d 100644 --- a/mROA/Implementation/Frontend/RequestExtractor.cs +++ b/mROA/Implementation/Frontend/RequestExtractor.cs @@ -76,7 +76,6 @@ namespace mROA.Implementation.Frontend messageType: MessageType.CancelRequest, token: token); Task.WaitAny(defaultRequest, cancelRequest); - #if TRACE Console.WriteLine("Request received"); #endif