-- Copyright (c) Microsoft. All rights reserved. -- Licensed under the MIT license. See LICENSE file in the project root for full license information. {-# LANGUAGE QuasiQuotes, OverloadedStrings, RecordWildCards #-} module Language.Bond.Codegen.Cs.Grpc_cs ( grpc_cs) where import Data.Maybe import Data.Monoid import Prelude import qualified Data.Text.Lazy as L import Text.Shakespeare.Text import Language.Bond.Syntax.Types import Language.Bond.Util import Language.Bond.Codegen.Util import Language.Bond.Codegen.TypeMapping import qualified Language.Bond.Codegen.Cs.Util as CS -- | Codegen template for generating code containing declarations of -- of services including proxies and services files for gRPC integration. grpc_cs :: MappingContext -> String -> [Import] -> [Declaration] -> (String, L.Text) grpc_cs cs _ _ declarations = ("_grpc.cs", [lt| #{CS.disableCscWarnings} #{CS.disableReSharperWarnings} namespace #{csNamespace} { using System.Collections.Generic; #{doubleLineSep 1 grpc declarations} } // #{csNamespace} |]) where csNamespace = sepBy "." toText $ getNamespace cs idl = MappingContext idlTypeMapping [] [] [] grpc s@Service{..} = [lt|#{CS.typeAttributes cs s}public static class #{declName}#{generics} #{genericsWhere} { static readonly string ServiceName = "#{getDeclTypeName idl s}"; #{doubleLineSep 2 methodDeclaration serviceMethods} public abstract class #{declName}Base { #{doubleLineSep 3 serverBaseMethods serviceMethods} } public class #{declName}Client : global::Grpc.Core.ClientBase<#{declName}Client> { public #{declName}Client(global::Grpc.Core.Channel channel) : base(channel) { } protected #{declName}Client() : base() { } protected #{declName}Client(global::Grpc.Core.ClientBase.ClientBaseConfiguration configuration) : base(configuration) { } #{doubleLineSep 3 clientMethods serviceMethods} protected override #{declName}Client NewInstance(global::Grpc.Core.ClientBase.ClientBaseConfiguration configuration) { return new #{declName}Client(configuration); } } public static global::Grpc.Core.ServerServiceDefinition BindService(#{declName}Base serviceImpl) { return global::Grpc.Core.ServerServiceDefinition.CreateBuilder() #{newlineSep 5 serviceMethodBuilder serviceMethods} .Build(); } } |] where methodNames = map methodName serviceMethods uniqImplName name = uniqueName (name ++ "_impl") methodNames getMessageTypeName t = maybe "global::Bond.Void" (getTypeName cs) t generics = angles $ sepBy ", " paramName declParams genericsWhere = sepBy " " addWhere declParams where addWhere a = [lt|where #{paramName a} : class|] methodDeclaration Function{..} = [lt|static readonly global::Grpc.Core.Method, global::Bond.Grpc.IMessage<#{getMessageTypeName methodResult}>> Method_#{methodName} = new global::Grpc.Core.Method, global::Bond.Grpc.IMessage<#{getMessageTypeName methodResult}>>( global::Grpc.Core.MethodType.Unary, ServiceName, "#{methodName}", global::Bond.Grpc.Marshaller<#{getMessageTypeName methodInput}>.Instance, global::Bond.Grpc.Marshaller<#{getMessageTypeName methodResult}>.Instance);|] methodDeclaration Event{..} = [lt|static readonly global::Grpc.Core.Method, global::Bond.Grpc.IMessage<#{getMessageTypeName Nothing}>> Method_#{methodName} = new global::Grpc.Core.Method, global::Bond.Grpc.IMessage<#{getMessageTypeName Nothing}>>( global::Grpc.Core.MethodType.Unary, ServiceName, "#{methodName}", global::Bond.Grpc.Marshaller<#{getMessageTypeName methodInput}>.Instance, global::Bond.Grpc.Marshaller<#{getMessageTypeName Nothing}>.Instance);|] serverBaseMethods Function{..} = [lt|#{CS.schemaAttributes 3 methodAttributes}public abstract global::System.Threading.Tasks.Task> #{methodName}(global::Bond.Grpc.IMessage<#{getMessageTypeName methodInput}> request, global::Grpc.Core.ServerCallContext context);|] serverBaseMethods Event{..} = [lt|#{CS.schemaAttributes 3 methodAttributes}public abstract global::System.Threading.Tasks.Task #{methodName}(global::Bond.Grpc.IMessage<#{getMessageTypeName methodInput}> request, global::Grpc.Core.ServerCallContext context); internal global::System.Threading.Tasks.Task> #{uniqImplName methodName}(global::Bond.Grpc.IMessage<#{getMessageTypeName methodInput}> request, global::Grpc.Core.ServerCallContext context) { return global::Bond.Grpc.Internal.NothingCallHandler.Handle(#{methodName}, request, context); }|] firstParam Nothing = mempty firstParam t = [lt|#{getMessageTypeName t} request, |] requestOrVoidConstructor Nothing = [lt|global::Bond.Grpc.Message.Void|] requestOrVoidConstructor _ = [lt|global::Bond.Grpc.Message.From(request)|] clientMethods Function{..} = [lt|#{CS.schemaAttributes 3 methodAttributes}public virtual global::Grpc.Core.AsyncUnaryCall> #{methodName}Async(#{firstParam methodInput}global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) { var message = #{requestOrVoidConstructor methodInput}; return #{methodName}Async(message, new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken)); } public virtual global::Grpc.Core.AsyncUnaryCall> #{methodName}Async(global::Bond.Grpc.IMessage<#{getMessageTypeName methodInput}> request, global::Grpc.Core.CallOptions options) { return CallInvoker.AsyncUnaryCall(Method_#{methodName}, null, options, request); }|] clientMethods Event{..} = [lt|#{CS.schemaAttributes 3 methodAttributes}public virtual void #{methodName}Async(#{firstParam methodInput}global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) { var message = #{requestOrVoidConstructor methodInput}; #{methodName}Async(message, new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken)); } public virtual void #{methodName}Async(global::Bond.Grpc.IMessage<#{getMessageTypeName methodInput}> request, global::Grpc.Core.CallOptions options) { global::Bond.Grpc.Internal.NothingCallInvoker.NothingCall(CallInvoker, Method_#{methodName}, null, options, request); }|] serviceMethodBuilder Function{..} = [lt|.AddMethod(Method_#{methodName}, serviceImpl.#{methodName})|] serviceMethodBuilder Event{..} = [lt|.AddMethod(Method_#{methodName}, serviceImpl.#{uniqImplName methodName})|] grpc _ = mempty