private (MessageDescription RequestType, int[] DataIndexes, MessageDescription?HeaderType, int[] HeaderIndexes) GetRequestType() { if (Method.Parameters.Length == 0) { return(MessageDescription.Empty(), Array.Empty <int>(), null, Array.Empty <int>()); } var dataParameters = new List <ITypeSymbol>(); var dataParameterIndexes = new List <int>(); var streamingIndex = -1; for (var i = 0; i < Method.Parameters.Length; i++) { var parameter = Method.Parameters[i]; if (IsDataParameter(parameter.TypeSymbol)) { if (SyntaxTools.IsAsyncEnumerable(parameter.TypeSymbol)) { streamingIndex = i; } else { dataParameters.Add(parameter.TypeSymbol); dataParameterIndexes.Add(i); } } } if (streamingIndex >= 0) { var requestType = CreateMessage(Method.Parameters[streamingIndex].TypeSymbol.GenericTypeArguments()[0]); MessageDescription?headerType = null; if (dataParameters.Count > 0) { headerType = CreateMessage(dataParameters.ToArray()); } return( requestType, new[] { streamingIndex }, headerType, dataParameterIndexes.ToArray()); } return( CreateMessage(dataParameters.ToArray()), dataParameterIndexes.ToArray(), null, Array.Empty <int>()); }
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 void ValidateSignature() { if (Method.TypeArguments.Length != 0) { ThrowInvalidSignature(); } var hasInputStreaming = false; for (var i = 0; i < Method.Parameters.Length; i++) { var parameter = Method.Parameters[i]; if (parameter.IsOut || parameter.IsRef) { ThrowInvalidSignature(); } if (IsDataParameter(parameter.TypeSymbol)) { if (SyntaxTools.IsAsyncEnumerable(parameter.TypeSymbol)) { if (hasInputStreaming) { ThrowInvalidSignature(); } hasInputStreaming = true; } } else if (!IsContextParameter(parameter.TypeSymbol)) { ThrowInvalidSignature(); } } }
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 IsAsyncEnumerable(Type type, bool expected) { var symbol = Compilation.GetTypeByMetadataName(type); SyntaxTools.IsAsyncEnumerable(symbol).ShouldBe(expected); }