Generator-Client.swift 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. /*
  2. * Copyright 2018, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import Foundation
  17. import SwiftProtobuf
  18. import SwiftProtobufPluginLibrary
  19. extension Generator {
  20. internal func printClient(asynchronousCode: Bool,
  21. synchronousCode: Bool) {
  22. if options.generateNIOImplementation {
  23. printNIOGRPCClient()
  24. } else {
  25. printCGRPCClient(asynchronousCode: asynchronousCode,
  26. synchronousCode: synchronousCode)
  27. if options.generateTestStubs {
  28. printCGRPCClientTestStubs(asynchronousCode: asynchronousCode,
  29. synchronousCode: synchronousCode)
  30. }
  31. }
  32. }
  33. private func printCGRPCClient(asynchronousCode: Bool,
  34. synchronousCode: Bool) {
  35. for method in service.methods {
  36. self.method = method
  37. switch streamingType(method) {
  38. case .unary:
  39. printServiceClientMethodCallUnary()
  40. case .serverStreaming:
  41. printServiceClientMethodCallServerStreaming()
  42. case .clientStreaming:
  43. printServiceClientMethodCallClientStreaming()
  44. case .bidirectionalStreaming:
  45. printServiceClientMethodCallBidiStreaming()
  46. }
  47. }
  48. println()
  49. printServiceClientProtocol(asynchronousCode: asynchronousCode,
  50. synchronousCode: synchronousCode)
  51. println()
  52. printServiceClientProtocolExtension(asynchronousCode: asynchronousCode,
  53. synchronousCode: synchronousCode)
  54. println()
  55. printServiceClientImplementation(asynchronousCode: asynchronousCode,
  56. synchronousCode: synchronousCode)
  57. }
  58. private func printCGRPCClientTestStubs(asynchronousCode: Bool,
  59. synchronousCode: Bool) {
  60. for method in service.methods {
  61. self.method = method
  62. switch streamingType(method) {
  63. case .unary:
  64. printServiceClientMethodCallUnaryTestStub()
  65. case .serverStreaming:
  66. printServiceClientMethodCallServerStreamingTestStub()
  67. case .clientStreaming:
  68. printServiceClientMethodCallClientStreamingTestStub()
  69. case .bidirectionalStreaming:
  70. printServiceClientMethodCallBidiStreamingTestStub()
  71. }
  72. }
  73. println()
  74. printServiceClientTestStubs(asynchronousCode: asynchronousCode, synchronousCode: synchronousCode)
  75. }
  76. private func printServiceClientMethodCallUnary() {
  77. println("\(access) protocol \(callName): ClientCallUnary {}")
  78. println()
  79. println("fileprivate final class \(callName)Base: ClientCallUnaryBase<\(methodInputName), \(methodOutputName)>, \(callName) {")
  80. indent()
  81. println("override class var method: String { return \(methodPath) }")
  82. outdent()
  83. println("}")
  84. println()
  85. }
  86. private func printServiceClientMethodCallUnaryTestStub() {
  87. println()
  88. println("class \(callName)TestStub: ClientCallUnaryTestStub, \(callName) {")
  89. indent()
  90. println("override class var method: String { return \(methodPath) }")
  91. outdent()
  92. println("}")
  93. }
  94. private func printServiceClientMethodCallServerStreaming() {
  95. println("\(access) protocol \(callName): ClientCallServerStreaming {")
  96. indent()
  97. printStreamReceiveMethods(receivedType: methodOutputName)
  98. outdent()
  99. println("}")
  100. println()
  101. printStreamReceiveExtension(extendedType: callName, receivedType: methodOutputName)
  102. println()
  103. println("fileprivate final class \(callName)Base: ClientCallServerStreamingBase<\(methodInputName), \(methodOutputName)>, \(callName) {")
  104. indent()
  105. println("override class var method: String { return \(methodPath) }")
  106. outdent()
  107. println("}")
  108. println()
  109. }
  110. private func printServiceClientMethodCallServerStreamingTestStub() {
  111. println()
  112. println("class \(callName)TestStub: ClientCallServerStreamingTestStub<\(methodOutputName)>, \(callName) {")
  113. indent()
  114. println("override class var method: String { return \(methodPath) }")
  115. outdent()
  116. println("}")
  117. }
  118. private func printServiceClientMethodCallClientStreaming() {
  119. println("\(options.visibility.sourceSnippet) protocol \(callName): ClientCallClientStreaming {")
  120. indent()
  121. printStreamSendMethods(sentType: methodInputName)
  122. println()
  123. println("/// Call this to close the connection and wait for a response. Blocking.")
  124. println("func closeAndReceive() throws -> \(methodOutputName)")
  125. println("/// Call this to close the connection and wait for a response. Nonblocking.")
  126. println("func closeAndReceive(completion: @escaping (ResultOrRPCError<\(methodOutputName)>) -> Void) throws")
  127. outdent()
  128. println("}")
  129. println()
  130. printStreamSendExtension(extendedType: callName, sentType: methodInputName)
  131. println()
  132. println("fileprivate final class \(callName)Base: ClientCallClientStreamingBase<\(methodInputName), \(methodOutputName)>, \(callName) {")
  133. indent()
  134. println("override class var method: String { return \(methodPath) }")
  135. outdent()
  136. println("}")
  137. println()
  138. }
  139. private func printServiceClientMethodCallClientStreamingTestStub() {
  140. println()
  141. println("/// Simple fake implementation of \(callName)")
  142. println("/// stores sent values for later verification and finall returns a previously-defined result.")
  143. println("class \(callName)TestStub: ClientCallClientStreamingTestStub<\(methodInputName), \(methodOutputName)>, \(callName) {")
  144. indent()
  145. println("override class var method: String { return \(methodPath) }")
  146. outdent()
  147. println("}")
  148. }
  149. private func printServiceClientMethodCallBidiStreaming() {
  150. println("\(access) protocol \(callName): ClientCallBidirectionalStreaming {")
  151. indent()
  152. printStreamReceiveMethods(receivedType: methodOutputName)
  153. println()
  154. printStreamSendMethods(sentType: methodInputName)
  155. println()
  156. println("/// Call this to close the sending connection. Blocking.")
  157. println("func closeSend() throws")
  158. println("/// Call this to close the sending connection. Nonblocking.")
  159. println("func closeSend(completion: (() -> Void)?) throws")
  160. outdent()
  161. println("}")
  162. println()
  163. printStreamReceiveExtension(extendedType: callName, receivedType: methodOutputName)
  164. println()
  165. printStreamSendExtension(extendedType: callName, sentType: methodInputName)
  166. println()
  167. println("fileprivate final class \(callName)Base: ClientCallBidirectionalStreamingBase<\(methodInputName), \(methodOutputName)>, \(callName) {")
  168. indent()
  169. println("override class var method: String { return \(methodPath) }")
  170. outdent()
  171. println("}")
  172. println()
  173. }
  174. private func printServiceClientMethodCallBidiStreamingTestStub() {
  175. println()
  176. println("class \(callName)TestStub: ClientCallBidirectionalStreamingTestStub<\(methodInputName), \(methodOutputName)>, \(callName) {")
  177. indent()
  178. println("override class var method: String { return \(methodPath) }")
  179. outdent()
  180. println("}")
  181. }
  182. private func printServiceClientProtocol(asynchronousCode: Bool,
  183. synchronousCode: Bool) {
  184. println("/// Instantiate \(serviceClassName)Client, then call methods of this protocol to make API calls.")
  185. println("\(options.visibility.sourceSnippet) protocol \(serviceClassName): ServiceClient {")
  186. indent()
  187. for method in service.methods {
  188. self.method = method
  189. switch streamingType(method) {
  190. case .unary:
  191. if synchronousCode {
  192. println("/// Synchronous. Unary.")
  193. println("func \(methodFunctionName)(_ request: \(methodInputName), metadata customMetadata: Metadata) throws -> \(methodOutputName)")
  194. }
  195. if asynchronousCode {
  196. println("/// Asynchronous. Unary.")
  197. println("@discardableResult")
  198. println("func \(methodFunctionName)(_ request: \(methodInputName), metadata customMetadata: Metadata, completion: @escaping (\(methodOutputName)?, CallResult) -> Void) throws -> \(callName)")
  199. }
  200. case .serverStreaming:
  201. println("/// Asynchronous. Server-streaming.")
  202. println("/// Send the initial message.")
  203. println("/// Use methods on the returned object to get streamed responses.")
  204. println("func \(methodFunctionName)(_ request: \(methodInputName), metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> \(callName)")
  205. case .clientStreaming:
  206. println("/// Asynchronous. Client-streaming.")
  207. println("/// Use methods on the returned object to stream messages and")
  208. println("/// to close the connection and wait for a final response.")
  209. println("func \(methodFunctionName)(metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> \(callName)")
  210. case .bidirectionalStreaming:
  211. println("/// Asynchronous. Bidirectional-streaming.")
  212. println("/// Use methods on the returned object to stream messages,")
  213. println("/// to wait for replies, and to close the connection.")
  214. println("func \(methodFunctionName)(metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> \(callName)")
  215. }
  216. println()
  217. }
  218. outdent()
  219. println("}")
  220. }
  221. private func printServiceClientProtocolExtension(asynchronousCode: Bool,
  222. synchronousCode: Bool) {
  223. println("\(options.visibility.sourceSnippet) extension \(serviceClassName) {")
  224. indent()
  225. for method in service.methods {
  226. self.method = method
  227. switch streamingType(method) {
  228. case .unary:
  229. if synchronousCode {
  230. println("/// Synchronous. Unary.")
  231. println("func \(methodFunctionName)(_ request: \(methodInputName)) throws -> \(methodOutputName) {")
  232. indent()
  233. println("return try self.\(methodFunctionName)(request, metadata: self.metadata)")
  234. outdent()
  235. println("}")
  236. }
  237. if asynchronousCode {
  238. println("/// Asynchronous. Unary.")
  239. println("@discardableResult")
  240. println("func \(methodFunctionName)(_ request: \(methodInputName), completion: @escaping (\(methodOutputName)?, CallResult) -> Void) throws -> \(callName) {")
  241. indent()
  242. println("return try self.\(methodFunctionName)(request, metadata: self.metadata, completion: completion)")
  243. outdent()
  244. println("}")
  245. }
  246. case .serverStreaming:
  247. println("/// Asynchronous. Server-streaming.")
  248. println("func \(methodFunctionName)(_ request: \(methodInputName), completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  249. indent()
  250. println("return try self.\(methodFunctionName)(request, metadata: self.metadata, completion: completion)")
  251. outdent()
  252. println("}")
  253. case .clientStreaming:
  254. println("/// Asynchronous. Client-streaming.")
  255. println("func \(methodFunctionName)(completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  256. indent()
  257. println("return try self.\(methodFunctionName)(metadata: self.metadata, completion: completion)")
  258. outdent()
  259. println("}")
  260. case .bidirectionalStreaming:
  261. println("/// Asynchronous. Bidirectional-streaming.")
  262. println("func \(methodFunctionName)(completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  263. indent()
  264. println("return try self.\(methodFunctionName)(metadata: self.metadata, completion: completion)")
  265. outdent()
  266. println("}")
  267. }
  268. println()
  269. }
  270. outdent()
  271. println("}")
  272. }
  273. private func printServiceClientImplementation(asynchronousCode: Bool,
  274. synchronousCode: Bool) {
  275. println("\(access) final class \(serviceClassName)Client: ServiceClientBase, \(serviceClassName) {")
  276. indent()
  277. for method in service.methods {
  278. self.method = method
  279. switch streamingType(method) {
  280. case .unary:
  281. if synchronousCode {
  282. println("/// Synchronous. Unary.")
  283. println("\(access) func \(methodFunctionName)(_ request: \(methodInputName), metadata customMetadata: Metadata) throws -> \(methodOutputName) {")
  284. indent()
  285. println("return try \(callName)Base(channel)")
  286. indent()
  287. println(".run(request: request, metadata: customMetadata)")
  288. outdent()
  289. outdent()
  290. println("}")
  291. }
  292. if asynchronousCode {
  293. println("/// Asynchronous. Unary.")
  294. println("@discardableResult")
  295. println("\(access) func \(methodFunctionName)(_ request: \(methodInputName), metadata customMetadata: Metadata, completion: @escaping (\(methodOutputName)?, CallResult) -> Void) throws -> \(callName) {")
  296. indent()
  297. println("return try \(callName)Base(channel)")
  298. indent()
  299. println(".start(request: request, metadata: customMetadata, completion: completion)")
  300. outdent()
  301. outdent()
  302. println("}")
  303. }
  304. case .serverStreaming:
  305. println("/// Asynchronous. Server-streaming.")
  306. println("/// Send the initial message.")
  307. println("/// Use methods on the returned object to get streamed responses.")
  308. println("\(access) func \(methodFunctionName)(_ request: \(methodInputName), metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  309. indent()
  310. println("return try \(callName)Base(channel)")
  311. indent()
  312. println(".start(request: request, metadata: customMetadata, completion: completion)")
  313. outdent()
  314. outdent()
  315. println("}")
  316. case .clientStreaming:
  317. println("/// Asynchronous. Client-streaming.")
  318. println("/// Use methods on the returned object to stream messages and")
  319. println("/// to close the connection and wait for a final response.")
  320. println("\(access) func \(methodFunctionName)(metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  321. indent()
  322. println("return try \(callName)Base(channel)")
  323. indent()
  324. println(".start(metadata: customMetadata, completion: completion)")
  325. outdent()
  326. outdent()
  327. println("}")
  328. case .bidirectionalStreaming:
  329. println("/// Asynchronous. Bidirectional-streaming.")
  330. println("/// Use methods on the returned object to stream messages,")
  331. println("/// to wait for replies, and to close the connection.")
  332. println("\(access) func \(methodFunctionName)(metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  333. indent()
  334. println("return try \(callName)Base(channel)")
  335. indent()
  336. println(".start(metadata: customMetadata, completion: completion)")
  337. outdent()
  338. outdent()
  339. println("}")
  340. }
  341. println()
  342. }
  343. outdent()
  344. println("}")
  345. }
  346. private func printServiceClientTestStubs(asynchronousCode: Bool,
  347. synchronousCode: Bool) {
  348. println("class \(serviceClassName)TestStub: ServiceClientTestStubBase, \(serviceClassName) {")
  349. indent()
  350. for method in service.methods {
  351. self.method = method
  352. switch streamingType(method) {
  353. case .unary:
  354. println("var \(methodFunctionName)Requests: [\(methodInputName)] = []")
  355. println("var \(methodFunctionName)Responses: [\(methodOutputName)] = []")
  356. if synchronousCode {
  357. println("func \(methodFunctionName)(_ request: \(methodInputName), metadata customMetadata: Metadata) throws -> \(methodOutputName) {")
  358. indent()
  359. println("\(methodFunctionName)Requests.append(request)")
  360. println("defer { \(methodFunctionName)Responses.removeFirst() }")
  361. println("return \(methodFunctionName)Responses.first!")
  362. outdent()
  363. println("}")
  364. }
  365. if asynchronousCode {
  366. println("@discardableResult")
  367. println("func \(methodFunctionName)(_ request: \(methodInputName), metadata customMetadata: Metadata, completion: @escaping (\(methodOutputName)?, CallResult) -> Void) throws -> \(callName) {")
  368. indent()
  369. println("fatalError(\"not implemented\")")
  370. outdent()
  371. println("}")
  372. }
  373. case .serverStreaming:
  374. println("var \(methodFunctionName)Requests: [\(methodInputName)] = []")
  375. println("var \(methodFunctionName)Calls: [\(callName)] = []")
  376. println("func \(methodFunctionName)(_ request: \(methodInputName), metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  377. indent()
  378. println("\(methodFunctionName)Requests.append(request)")
  379. println("defer { \(methodFunctionName)Calls.removeFirst() }")
  380. println("return \(methodFunctionName)Calls.first!")
  381. outdent()
  382. println("}")
  383. case .clientStreaming:
  384. println("var \(methodFunctionName)Calls: [\(callName)] = []")
  385. println("func \(methodFunctionName)(metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  386. indent()
  387. println("defer { \(methodFunctionName)Calls.removeFirst() }")
  388. println("return \(methodFunctionName)Calls.first!")
  389. outdent()
  390. println("}")
  391. case .bidirectionalStreaming:
  392. println("var \(methodFunctionName)Calls: [\(callName)] = []")
  393. println("func \(methodFunctionName)(metadata customMetadata: Metadata, completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  394. indent()
  395. println("defer { \(methodFunctionName)Calls.removeFirst() }")
  396. println("return \(methodFunctionName)Calls.first!")
  397. outdent()
  398. println("}")
  399. }
  400. println()
  401. }
  402. outdent()
  403. println("}")
  404. }
  405. private func printNIOGRPCClient() {
  406. println()
  407. printNIOServiceClientProtocol()
  408. println()
  409. printNIOServiceClientImplementation()
  410. }
  411. private func printNIOServiceClientProtocol() {
  412. println("/// Usage: instantiate \(serviceClassName)Client, then call methods of this protocol to make API calls.")
  413. println("\(options.visibility.sourceSnippet) protocol \(serviceClassName) {")
  414. indent()
  415. for method in service.methods {
  416. self.method = method
  417. switch streamingType(method) {
  418. case .unary:
  419. println("func \(methodFunctionName)(_ request: \(methodInputName), callOptions: CallOptions?) -> UnaryClientCall<\(methodInputName), \(methodOutputName)>")
  420. case .serverStreaming:
  421. println("func \(methodFunctionName)(_ request: \(methodInputName), callOptions: CallOptions?, handler: @escaping (\(methodOutputName)) -> Void) -> ServerStreamingClientCall<\(methodInputName), \(methodOutputName)>")
  422. case .clientStreaming:
  423. println("func \(methodFunctionName)(callOptions: CallOptions?) -> ClientStreamingClientCall<\(methodInputName), \(methodOutputName)>")
  424. case .bidirectionalStreaming:
  425. println("func \(methodFunctionName)(callOptions: CallOptions?, handler: @escaping (\(methodOutputName)) -> Void) -> BidirectionalStreamingClientCall<\(methodInputName), \(methodOutputName)>")
  426. }
  427. }
  428. outdent()
  429. println("}")
  430. }
  431. private func printNIOServiceClientImplementation() {
  432. println("\(access) final class \(serviceClassName)Client: GRPCServiceClient, \(serviceClassName) {")
  433. indent()
  434. println("\(access) let client: GRPCClient")
  435. println("\(access) let service = \"\(servicePath)\"")
  436. println("\(access) var defaultCallOptions: CallOptions")
  437. println()
  438. println("/// Creates a client for the \(servicePath) service.")
  439. println("///")
  440. printParameters()
  441. println("/// - client: `GRPCClient` with a connection to the service host.")
  442. println("/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. Defaults to `client.defaultCallOptions`.")
  443. println("\(access) init(client: GRPCClient, defaultCallOptions: CallOptions? = nil) {")
  444. indent()
  445. println("self.client = client")
  446. println("self.defaultCallOptions = defaultCallOptions ?? client.defaultCallOptions")
  447. outdent()
  448. println("}")
  449. println()
  450. for method in service.methods {
  451. self.method = method
  452. switch streamingType(method) {
  453. case .unary:
  454. println("/// Asynchronous unary call to \(method.name).")
  455. println("///")
  456. printParameters()
  457. printRequestParameter()
  458. printCallOptionsParameter()
  459. println("/// - Returns: A `UnaryClientCall` with futures for the metadata, status and response.")
  460. println("\(access) func \(methodFunctionName)(_ request: \(methodInputName), callOptions: CallOptions? = nil) -> UnaryClientCall<\(methodInputName), \(methodOutputName)> {")
  461. indent()
  462. println("return UnaryClientCall(client: client, path: path(forMethod: \"\(method.name)\"), request: request, callOptions: callOptions ?? self.defaultCallOptions)")
  463. outdent()
  464. println("}")
  465. case .serverStreaming:
  466. println("/// Asynchronous server-streaming call to \(method.name).")
  467. println("///")
  468. printParameters()
  469. printRequestParameter()
  470. printCallOptionsParameter()
  471. printHandlerParameter()
  472. println("/// - Returns: A `ServerStreamingClientCall` with futures for the metadata and status.")
  473. println("\(access) func \(methodFunctionName)(_ request: \(methodInputName), callOptions: CallOptions? = nil, handler: @escaping (\(methodOutputName)) -> Void) -> ServerStreamingClientCall<\(methodInputName), \(methodOutputName)> {")
  474. indent()
  475. println("return ServerStreamingClientCall(client: client, path: path(forMethod: \"\(method.name)\"), request: request, callOptions: callOptions ?? self.defaultCallOptions, handler: handler)")
  476. outdent()
  477. println("}")
  478. case .clientStreaming:
  479. println("/// Asynchronous client-streaming call to \(method.name).")
  480. println("///")
  481. printClientStreamingDetails()
  482. println("///")
  483. printParameters()
  484. printCallOptionsParameter()
  485. println("/// - Returns: A `ClientStreamingClientCall` with futures for the metadata, status and response.")
  486. println("\(access) func \(methodFunctionName)(callOptions: CallOptions? = nil) -> ClientStreamingClientCall<\(methodInputName), \(methodOutputName)> {")
  487. indent()
  488. println("return ClientStreamingClientCall(client: client, path: path(forMethod: \"\(method.name)\"), callOptions: callOptions ?? self.defaultCallOptions)")
  489. outdent()
  490. println("}")
  491. case .bidirectionalStreaming:
  492. println("/// Asynchronous bidirectional-streaming call to \(method.name).")
  493. println("///")
  494. printClientStreamingDetails()
  495. println("///")
  496. printParameters()
  497. printCallOptionsParameter()
  498. printHandlerParameter()
  499. println("/// - Returns: A `ClientStreamingClientCall` with futures for the metadata and status.")
  500. println("\(access) func \(methodFunctionName)(callOptions: CallOptions? = nil, handler: @escaping (\(methodOutputName)) -> Void) -> BidirectionalStreamingClientCall<\(methodInputName), \(methodOutputName)> {")
  501. indent()
  502. println("return BidirectionalStreamingClientCall(client: client, path: path(forMethod: \"\(method.name)\"), callOptions: callOptions ?? self.defaultCallOptions, handler: handler)")
  503. outdent()
  504. println("}")
  505. }
  506. println()
  507. }
  508. outdent()
  509. println("}")
  510. }
  511. private func printClientStreamingDetails() {
  512. println("/// Callers should use the `send` method on the returned object to send messages")
  513. println("/// to the server. The caller should send an `.end` after the final message has been sent.")
  514. }
  515. private func printParameters() {
  516. println("/// - Parameters:")
  517. }
  518. private func printRequestParameter() {
  519. println("/// - request: Request to send to \(method.name).")
  520. }
  521. private func printCallOptionsParameter() {
  522. println("/// - callOptions: Call options; `self.defaultCallOptions` is used if `nil`.")
  523. }
  524. private func printHandlerParameter() {
  525. println("/// - handler: A closure called when each response is received from the server.")
  526. }
  527. }