public OperationDescription(IMethodSymbol method, string serviceName) { ServiceName = serviceName; Method = new MethodDescription(method); ValidateSignature(); OperationName = ServiceContract.GetServiceOperationName(method); (ResponseType, ResponseTypeIndex, HeaderResponseType, HeaderResponseTypeInput) = CreateResponseType(method.ReturnType); (RequestType, RequestTypeInput, HeaderRequestType, HeaderRequestTypeInput) = GetRequestType(); OperationType = GetOperationType(); ContextInput = GetContextInput(); IsAsync = SyntaxTools.IsTask(method.ReturnType); GrpcMethodName = "Method" + OperationName; GrpcMethodInputHeaderName = "MethodInputHeader" + OperationName; GrpcMethodOutputHeaderName = "MethodOutputHeader" + OperationName; }
private MethodType GetOperationType() { var returnType = Method.ReturnTypeSymbol; if (SyntaxTools.IsTask(Method.ReturnTypeSymbol)) { var args = returnType.GenericTypeArguments(); returnType = args.IsEmpty ? returnType : args[0]; } var responseIsStreaming = SyntaxTools.IsAsyncEnumerable(returnType) || (SyntaxTools.IsValueTuple(returnType) && returnType.GenericTypeArguments().Any(SyntaxTools.IsAsyncEnumerable)); var requestIsStreaming = Method.Parameters.Select(i => i.TypeSymbol).Any(SyntaxTools.IsAsyncEnumerable); if (responseIsStreaming) { return(requestIsStreaming ? MethodType.DuplexStreaming : MethodType.ServerStreaming); } return(requestIsStreaming ? MethodType.ClientStreaming : MethodType.Unary); }
private static bool IsDataParameter(ITypeSymbol type) { return(!SyntaxTools.IsTask(type) && !IsContextParameter(type) && !SyntaxTools.IsStream(type)); }
private (MessageDescription ResponseType, int Index, MessageDescription?HeaderType, int[] HeaderIndexes) CreateResponseType(ITypeSymbol returnType) { if (SyntaxTools.IsVoid(returnType)) { return(MessageDescription.Empty(), 0, null, Array.Empty <int>()); } var responseType = returnType; if (SyntaxTools.IsTask(returnType)) { var genericArguments = responseType.GenericTypeArguments(); if (genericArguments.IsEmpty) { return(MessageDescription.Empty(), 0, null, Array.Empty <int>()); } responseType = genericArguments[0]; } if (SyntaxTools.IsValueTuple(responseType) && responseType.GenericTypeArguments().Any(SyntaxTools.IsAsyncEnumerable)) { if (!SyntaxTools.IsTask(returnType)) { ThrowInvalidSignature("Wrap return type with Task<> or ValueTask<>."); } var genericArguments = responseType.GenericTypeArguments(); if (genericArguments.Length == 1) { ThrowInvalidSignature("Unwrap return type from ValueTuple<>."); } var streamIndex = -1; var headerIndexes = new List <int>(); var headerTypes = new List <ITypeSymbol>(); for (var i = 0; i < genericArguments.Length; i++) { var genericArgument = genericArguments[i]; if (SyntaxTools.IsAsyncEnumerable(genericArgument)) { responseType = genericArgument.GenericTypeArguments()[0]; if (streamIndex >= 0 || IsContextParameter(responseType) || !IsDataParameter(responseType)) { ThrowInvalidSignature(); } streamIndex = i; } else if (IsContextParameter(genericArgument) || !IsDataParameter(genericArgument)) { ThrowInvalidSignature(); } else { headerIndexes.Add(i); headerTypes.Add(genericArgument); } } return( CreateMessage(responseType), streamIndex, CreateMessage(headerTypes.ToArray()), headerIndexes.ToArray()); } if (SyntaxTools.IsAsyncEnumerable(responseType)) { responseType = responseType.GenericTypeArguments()[0]; } if (IsContextParameter(responseType) || !IsDataParameter(responseType)) { ThrowInvalidSignature(); } return(CreateMessage(responseType), 0, null, Array.Empty <int>()); }
public void IsTask(Type type, bool expected) { var symbol = Compilation.GetTypeByMetadataName(type); SyntaxTools.IsTask(symbol).ShouldBe(expected); }