StructuredSwift+Server.swift 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. /*
  2. * Copyright 2024, 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. extension FunctionSignatureDescription {
  17. /// ```
  18. /// func <Method>(
  19. /// request: GRPCCore.ServerRequest<Input>,
  20. /// context: GRPCCore.ServerContext
  21. /// ) async throws -> GRPCCore.ServerResponse<Output>
  22. /// ```
  23. static func serverMethod(
  24. accessLevel: AccessModifier? = nil,
  25. name: String,
  26. input: String,
  27. output: String,
  28. streamingInput: Bool,
  29. streamingOutput: Bool,
  30. namer: Namer = Namer()
  31. ) -> Self {
  32. return FunctionSignatureDescription(
  33. accessModifier: accessLevel,
  34. kind: .function(name: name),
  35. parameters: [
  36. ParameterDescription(
  37. label: "request",
  38. type: namer.serverRequest(forType: input, isStreaming: streamingInput)
  39. ),
  40. ParameterDescription(label: "context", type: namer.serverContext),
  41. ],
  42. keywords: [.async, .throws],
  43. returnType: .identifierType(
  44. namer.serverResponse(forType: output, isStreaming: streamingOutput)
  45. )
  46. )
  47. }
  48. }
  49. @available(gRPCSwift 2.0, *)
  50. extension ProtocolDescription {
  51. /// ```
  52. /// protocol <Name>: GRPCCore.RegistrableRPCService {
  53. /// ...
  54. /// }
  55. /// ```
  56. static func streamingService(
  57. accessLevel: AccessModifier? = nil,
  58. name: String,
  59. methods: [MethodDescriptor],
  60. namer: Namer = Namer()
  61. ) -> Self {
  62. func docs(for method: MethodDescriptor) -> String {
  63. let summary = """
  64. /// Handle the "\(method.name.identifyingName)" method.
  65. """
  66. let parameters = """
  67. /// - Parameters:
  68. /// - request: A streaming request of `\(method.inputType)` messages.
  69. /// - context: Context providing information about the RPC.
  70. /// - Throws: Any error which occurred during the processing of the request. Thrown errors
  71. /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted
  72. /// to an internal error.
  73. /// - Returns: A streaming response of `\(method.outputType)` messages.
  74. """
  75. return Docs.interposeDocs(method.documentation, between: summary, and: parameters)
  76. }
  77. return ProtocolDescription(
  78. accessModifier: accessLevel,
  79. name: name,
  80. conformances: [namer.literalNamespacedType("RegistrableRPCService")],
  81. members: methods.map { method in
  82. .commentable(
  83. .preFormatted(docs(for: method)),
  84. .function(
  85. signature: .serverMethod(
  86. name: method.name.functionName,
  87. input: method.inputType,
  88. output: method.outputType,
  89. streamingInput: true,
  90. streamingOutput: true,
  91. namer: namer
  92. )
  93. )
  94. )
  95. }
  96. )
  97. }
  98. }
  99. @available(gRPCSwift 2.0, *)
  100. extension ExtensionDescription {
  101. /// ```
  102. /// extension <ExtensionName> {
  103. /// func registerMethods(with router: inout GRPCCore.RPCRouter) {
  104. /// // ...
  105. /// }
  106. /// }
  107. /// ```
  108. static func registrableRPCServiceDefaultImplementation(
  109. accessLevel: AccessModifier? = nil,
  110. on extensionName: String,
  111. serviceNamespace: String,
  112. methods: [MethodDescriptor],
  113. namer: Namer = Namer(),
  114. serializer: (String) -> String,
  115. deserializer: (String) -> String
  116. ) -> Self {
  117. return ExtensionDescription(
  118. onType: extensionName,
  119. declarations: [
  120. .function(
  121. .registerMethods(
  122. accessLevel: accessLevel,
  123. serviceNamespace: serviceNamespace,
  124. methods: methods,
  125. namer: namer,
  126. serializer: serializer,
  127. deserializer: deserializer
  128. )
  129. )
  130. ]
  131. )
  132. }
  133. }
  134. @available(gRPCSwift 2.0, *)
  135. extension ProtocolDescription {
  136. /// ```
  137. /// protocol <Name>: <StreamingProtocol> {
  138. /// ...
  139. /// }
  140. /// ```
  141. static func service(
  142. accessLevel: AccessModifier? = nil,
  143. name: String,
  144. streamingProtocol: String,
  145. methods: [MethodDescriptor],
  146. namer: Namer = Namer()
  147. ) -> Self {
  148. func docs(for method: MethodDescriptor) -> String {
  149. let summary = """
  150. /// Handle the "\(method.name.identifyingName)" method.
  151. """
  152. let request: String
  153. if method.isInputStreaming {
  154. request = "A streaming request of `\(method.inputType)` messages."
  155. } else {
  156. request = "A request containing a single `\(method.inputType)` message."
  157. }
  158. let returns: String
  159. if method.isOutputStreaming {
  160. returns = "A streaming response of `\(method.outputType)` messages."
  161. } else {
  162. returns = "A response containing a single `\(method.outputType)` message."
  163. }
  164. let parameters = """
  165. /// - Parameters:
  166. /// - request: \(request)
  167. /// - context: Context providing information about the RPC.
  168. /// - Throws: Any error which occurred during the processing of the request. Thrown errors
  169. /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted
  170. /// to an internal error.
  171. /// - Returns: \(returns)
  172. """
  173. return Docs.interposeDocs(method.documentation, between: summary, and: parameters)
  174. }
  175. return ProtocolDescription(
  176. accessModifier: accessLevel,
  177. name: name,
  178. conformances: [streamingProtocol],
  179. members: methods.map { method in
  180. .commentable(
  181. .preFormatted(docs(for: method)),
  182. .function(
  183. signature: .serverMethod(
  184. name: method.name.functionName,
  185. input: method.inputType,
  186. output: method.outputType,
  187. streamingInput: method.isInputStreaming,
  188. streamingOutput: method.isOutputStreaming,
  189. namer: namer
  190. )
  191. )
  192. )
  193. }
  194. )
  195. }
  196. }
  197. extension FunctionCallDescription {
  198. /// ```
  199. /// self.<Name>(request: request, context: context)
  200. /// ```
  201. static func serverMethodCallOnSelf(
  202. name: String,
  203. requestArgument: Expression = .identifierPattern("request")
  204. ) -> Self {
  205. return FunctionCallDescription(
  206. calledExpression: .memberAccess(
  207. MemberAccessDescription(
  208. left: .identifierPattern("self"),
  209. right: name
  210. )
  211. ),
  212. arguments: [
  213. FunctionArgumentDescription(
  214. label: "request",
  215. expression: requestArgument
  216. ),
  217. FunctionArgumentDescription(
  218. label: "context",
  219. expression: .identifierPattern("context")
  220. ),
  221. ]
  222. )
  223. }
  224. }
  225. extension ClosureInvocationDescription {
  226. /// ```
  227. /// { router, context in
  228. /// try await self.<Method>(
  229. /// request: request,
  230. /// context: context
  231. /// )
  232. /// }
  233. /// ```
  234. static func routerHandlerInvokingRPC(method: String) -> Self {
  235. return ClosureInvocationDescription(
  236. argumentNames: ["request", "context"],
  237. body: [
  238. .expression(
  239. .unaryKeyword(
  240. kind: .try,
  241. expression: .unaryKeyword(
  242. kind: .await,
  243. expression: .functionCall(.serverMethodCallOnSelf(name: method))
  244. )
  245. )
  246. )
  247. ]
  248. )
  249. }
  250. }
  251. /// ```
  252. /// router.registerHandler(
  253. /// forMethod: ...,
  254. /// deserializer: ...
  255. /// serializer: ...
  256. /// handler: { request, context in
  257. /// // ...
  258. /// }
  259. /// )
  260. /// ```
  261. extension FunctionCallDescription {
  262. static func registerWithRouter(
  263. serviceNamespace: String,
  264. methodNamespace: String,
  265. methodName: String,
  266. inputDeserializer: String,
  267. outputSerializer: String
  268. ) -> Self {
  269. return FunctionCallDescription(
  270. calledExpression: .memberAccess(
  271. .init(left: .identifierPattern("router"), right: "registerHandler")
  272. ),
  273. arguments: [
  274. FunctionArgumentDescription(
  275. label: "forMethod",
  276. expression: .identifierPattern("\(serviceNamespace).Method.\(methodNamespace).descriptor")
  277. ),
  278. FunctionArgumentDescription(
  279. label: "deserializer",
  280. expression: .identifierPattern(inputDeserializer)
  281. ),
  282. FunctionArgumentDescription(
  283. label: "serializer",
  284. expression: .identifierPattern(outputSerializer)
  285. ),
  286. FunctionArgumentDescription(
  287. label: "handler",
  288. expression: .closureInvocation(.routerHandlerInvokingRPC(method: methodName))
  289. ),
  290. ]
  291. )
  292. }
  293. }
  294. @available(gRPCSwift 2.0, *)
  295. extension FunctionDescription {
  296. /// ```
  297. /// func registerMethods(with router: inout GRPCCore.RPCRouter) {
  298. /// // ...
  299. /// }
  300. /// ```
  301. static func registerMethods(
  302. accessLevel: AccessModifier? = nil,
  303. serviceNamespace: String,
  304. methods: [MethodDescriptor],
  305. namer: Namer = Namer(),
  306. serializer: (String) -> String,
  307. deserializer: (String) -> String
  308. ) -> Self {
  309. return FunctionDescription(
  310. accessModifier: accessLevel,
  311. kind: .function(name: "registerMethods"),
  312. generics: [.member("Transport")],
  313. parameters: [
  314. ParameterDescription(
  315. label: "with",
  316. name: "router",
  317. type: namer.rpcRouter(genericOver: "Transport"),
  318. `inout`: true
  319. )
  320. ],
  321. whereClause: WhereClause(
  322. requirements: [
  323. .conformance("Transport", namer.literalNamespacedType("ServerTransport"))
  324. ]
  325. ),
  326. body: methods.map { method in
  327. .functionCall(
  328. .registerWithRouter(
  329. serviceNamespace: serviceNamespace,
  330. methodNamespace: method.name.typeName,
  331. methodName: method.name.functionName,
  332. inputDeserializer: deserializer(method.inputType),
  333. outputSerializer: serializer(method.outputType)
  334. )
  335. )
  336. }
  337. )
  338. }
  339. }
  340. extension FunctionDescription {
  341. /// ```
  342. /// func <Name>(
  343. /// request: GRPCCore.StreamingServerRequest<Input>
  344. /// context: GRPCCore.ServerContext
  345. /// ) async throws -> GRPCCore.StreamingServerResponse<Output> {
  346. /// let response = try await self.<Name>(
  347. /// request: GRPCCore.ServerRequest(stream: request),
  348. /// context: context
  349. /// )
  350. /// return GRPCCore.StreamingServerResponse(single: response)
  351. /// }
  352. /// ```
  353. static func serverStreamingMethodsCallingMethod(
  354. accessLevel: AccessModifier? = nil,
  355. name: String,
  356. input: String,
  357. output: String,
  358. streamingInput: Bool,
  359. streamingOutput: Bool,
  360. namer: Namer = Namer()
  361. ) -> FunctionDescription {
  362. let signature: FunctionSignatureDescription = .serverMethod(
  363. accessLevel: accessLevel,
  364. name: name,
  365. input: input,
  366. output: output,
  367. // This method converts from the fully streamed version to the specified version.
  368. streamingInput: true,
  369. streamingOutput: true,
  370. namer: namer
  371. )
  372. // Call the underlying function.
  373. let functionCall: Expression = .functionCall(
  374. calledExpression: .memberAccess(
  375. MemberAccessDescription(
  376. left: .identifierPattern("self"),
  377. right: name
  378. )
  379. ),
  380. arguments: [
  381. FunctionArgumentDescription(
  382. label: "request",
  383. expression: streamingInput
  384. ? .identifierPattern("request")
  385. : .functionCall(
  386. calledExpression: .identifierType(
  387. namer.serverRequest(forType: nil, isStreaming: false)
  388. ),
  389. arguments: [
  390. FunctionArgumentDescription(
  391. label: "stream",
  392. expression: .identifierPattern("request")
  393. )
  394. ]
  395. )
  396. ),
  397. FunctionArgumentDescription(
  398. label: "context",
  399. expression: .identifierPattern("context")
  400. ),
  401. ]
  402. )
  403. // Call the function and assign to 'response'.
  404. let response: Declaration = .variable(
  405. kind: .let,
  406. left: "response",
  407. right: .unaryKeyword(
  408. kind: .try,
  409. expression: .unaryKeyword(
  410. kind: .await,
  411. expression: functionCall
  412. )
  413. )
  414. )
  415. // Build the return statement.
  416. let returnExpression: Expression = .unaryKeyword(
  417. kind: .return,
  418. expression: streamingOutput
  419. ? .identifierPattern("response")
  420. : .functionCall(
  421. calledExpression: .identifierType(namer.serverResponse(forType: nil, isStreaming: true)),
  422. arguments: [
  423. FunctionArgumentDescription(
  424. label: "single",
  425. expression: .identifierPattern("response")
  426. )
  427. ]
  428. )
  429. )
  430. return Self(
  431. signature: signature,
  432. body: [.declaration(response), .expression(returnExpression)]
  433. )
  434. }
  435. }
  436. @available(gRPCSwift 2.0, *)
  437. extension ExtensionDescription {
  438. /// ```
  439. /// extension <ExtensionName> {
  440. /// func <Name>(
  441. /// request: GRPCCore.StreamingServerRequest<Input>
  442. /// context: GRPCCore.ServerContext
  443. /// ) async throws -> GRPCCore.StreamingServerResponse<Output> {
  444. /// let response = try await self.<Name>(
  445. /// request: GRPCCore.ServerRequest(stream: request),
  446. /// context: context
  447. /// )
  448. /// return GRPCCore.StreamingServerResponse(single: response)
  449. /// }
  450. /// ...
  451. /// }
  452. /// ```
  453. static func streamingServiceProtocolDefaultImplementation(
  454. accessModifier: AccessModifier? = nil,
  455. on extensionName: String,
  456. methods: [MethodDescriptor],
  457. namer: Namer = Namer()
  458. ) -> Self {
  459. return ExtensionDescription(
  460. onType: extensionName,
  461. declarations: methods.compactMap { method -> Declaration? in
  462. // Bidirectional streaming methods don't need a default implementation as their signatures
  463. // match across the two protocols.
  464. if method.isInputStreaming, method.isOutputStreaming { return nil }
  465. return .function(
  466. .serverStreamingMethodsCallingMethod(
  467. accessLevel: accessModifier,
  468. name: method.name.functionName,
  469. input: method.inputType,
  470. output: method.outputType,
  471. streamingInput: method.isInputStreaming,
  472. streamingOutput: method.isOutputStreaming,
  473. namer: namer
  474. )
  475. )
  476. }
  477. )
  478. }
  479. }
  480. extension FunctionSignatureDescription {
  481. /// ```
  482. /// func <Name>(
  483. /// request: <Input>,
  484. /// context: GRPCCore.ServerContext,
  485. /// ) async throws -> <Output>
  486. /// ```
  487. ///
  488. /// ```
  489. /// func <Name>(
  490. /// request: GRPCCore.RPCAsyncSequence<Input, any Error>,
  491. /// response: GRPCCore.RPCAsyncWriter<Output>
  492. /// context: GRPCCore.ServerContext,
  493. /// ) async throws
  494. /// ```
  495. static func simpleServerMethod(
  496. accessLevel: AccessModifier? = nil,
  497. name: String,
  498. input: String,
  499. output: String,
  500. streamingInput: Bool,
  501. streamingOutput: Bool,
  502. namer: Namer = Namer()
  503. ) -> Self {
  504. var parameters: [ParameterDescription] = [
  505. ParameterDescription(
  506. label: "request",
  507. type: streamingInput ? namer.rpcAsyncSequence(forType: input) : .member(input)
  508. )
  509. ]
  510. if streamingOutput {
  511. parameters.append(
  512. ParameterDescription(
  513. label: "response",
  514. type: namer.rpcWriter(forType: output)
  515. )
  516. )
  517. }
  518. parameters.append(ParameterDescription(label: "context", type: namer.serverContext))
  519. return FunctionSignatureDescription(
  520. accessModifier: accessLevel,
  521. kind: .function(name: name),
  522. parameters: parameters,
  523. keywords: [.async, .throws],
  524. returnType: streamingOutput ? nil : .identifier(.pattern(output))
  525. )
  526. }
  527. }
  528. @available(gRPCSwift 2.0, *)
  529. extension ProtocolDescription {
  530. /// ```
  531. /// protocol SimpleServiceProtocol: <ServiceProtocol> {
  532. /// ...
  533. /// }
  534. /// ```
  535. static func simpleServiceProtocol(
  536. accessModifier: AccessModifier? = nil,
  537. name: String,
  538. serviceProtocol: String,
  539. methods: [MethodDescriptor],
  540. namer: Namer = Namer()
  541. ) -> Self {
  542. func docs(for method: MethodDescriptor) -> String {
  543. let summary = """
  544. /// Handle the "\(method.name.identifyingName)" method.
  545. """
  546. let requestText =
  547. method.isInputStreaming
  548. ? "A stream of `\(method.inputType)` messages."
  549. : "A `\(method.inputType)` message."
  550. var parameters = """
  551. /// - Parameters:
  552. /// - request: \(requestText)
  553. """
  554. if method.isOutputStreaming {
  555. parameters += "\n"
  556. parameters += """
  557. /// - response: A response stream of `\(method.outputType)` messages.
  558. """
  559. }
  560. parameters += "\n"
  561. parameters += """
  562. /// - context: Context providing information about the RPC.
  563. /// - Throws: Any error which occurred during the processing of the request. Thrown errors
  564. /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted
  565. /// to an internal error.
  566. """
  567. if !method.isOutputStreaming {
  568. parameters += "\n"
  569. parameters += """
  570. /// - Returns: A `\(method.outputType)` to respond with.
  571. """
  572. }
  573. return Docs.interposeDocs(method.documentation, between: summary, and: parameters)
  574. }
  575. return ProtocolDescription(
  576. accessModifier: accessModifier,
  577. name: name,
  578. conformances: [serviceProtocol],
  579. members: methods.map { method in
  580. .commentable(
  581. .preFormatted(docs(for: method)),
  582. .function(
  583. signature: .simpleServerMethod(
  584. name: method.name.functionName,
  585. input: method.inputType,
  586. output: method.outputType,
  587. streamingInput: method.isInputStreaming,
  588. streamingOutput: method.isOutputStreaming,
  589. namer: namer
  590. )
  591. )
  592. )
  593. }
  594. )
  595. }
  596. }
  597. extension FunctionCallDescription {
  598. /// ```
  599. /// try await self.<Name>(
  600. /// request: request.message,
  601. /// response: writer,
  602. /// context: context
  603. /// )
  604. /// ```
  605. static func serviceMethodCallingSimpleMethod(
  606. name: String,
  607. input: String,
  608. output: String,
  609. streamingInput: Bool,
  610. streamingOutput: Bool
  611. ) -> Self {
  612. var arguments: [FunctionArgumentDescription] = [
  613. FunctionArgumentDescription(
  614. label: "request",
  615. expression: .identifierPattern("request").dot(streamingInput ? "messages" : "message")
  616. )
  617. ]
  618. if streamingOutput {
  619. arguments.append(
  620. FunctionArgumentDescription(
  621. label: "response",
  622. expression: .identifierPattern("writer")
  623. )
  624. )
  625. }
  626. arguments.append(
  627. FunctionArgumentDescription(
  628. label: "context",
  629. expression: .identifierPattern("context")
  630. )
  631. )
  632. return FunctionCallDescription(
  633. calledExpression: .try(.await(.identifierPattern("self").dot(name))),
  634. arguments: arguments
  635. )
  636. }
  637. }
  638. extension FunctionDescription {
  639. /// ```
  640. /// func <Name>(
  641. /// request: GRPCCore.ServerRequest<Input>,
  642. /// context: GRPCCore.ServerContext
  643. /// ) async throws -> GRPCCore.ServerResponse<Output> {
  644. /// return GRPCCore.ServerResponse<Output>(
  645. /// message: try await self.<Name>(
  646. /// request: request.message,
  647. /// context: context
  648. /// )
  649. /// metadata: [:]
  650. /// )
  651. /// }
  652. /// ```
  653. static func serviceProtocolDefaultImplementation(
  654. accessModifier: AccessModifier? = nil,
  655. name: String,
  656. input: String,
  657. output: String,
  658. streamingInput: Bool,
  659. streamingOutput: Bool,
  660. namer: Namer = Namer()
  661. ) -> Self {
  662. func makeUnaryOutputArguments() -> [FunctionArgumentDescription] {
  663. return [
  664. FunctionArgumentDescription(
  665. label: "message",
  666. expression: .functionCall(
  667. .serviceMethodCallingSimpleMethod(
  668. name: name,
  669. input: input,
  670. output: output,
  671. streamingInput: streamingInput,
  672. streamingOutput: streamingOutput
  673. )
  674. )
  675. ),
  676. FunctionArgumentDescription(label: "metadata", expression: .literal(.dictionary([]))),
  677. ]
  678. }
  679. func makeStreamingOutputArguments() -> [FunctionArgumentDescription] {
  680. return [
  681. FunctionArgumentDescription(label: "metadata", expression: .literal(.dictionary([]))),
  682. FunctionArgumentDescription(
  683. label: "producer",
  684. expression: .closureInvocation(
  685. argumentNames: ["writer"],
  686. body: [
  687. .expression(
  688. .functionCall(
  689. .serviceMethodCallingSimpleMethod(
  690. name: name,
  691. input: input,
  692. output: output,
  693. streamingInput: streamingInput,
  694. streamingOutput: streamingOutput
  695. )
  696. )
  697. ),
  698. .expression(.return(.literal(.dictionary([])))),
  699. ]
  700. )
  701. ),
  702. ]
  703. }
  704. return FunctionDescription(
  705. signature: .serverMethod(
  706. accessLevel: accessModifier,
  707. name: name,
  708. input: input,
  709. output: output,
  710. streamingInput: streamingInput,
  711. streamingOutput: streamingOutput,
  712. namer: namer
  713. ),
  714. body: [
  715. .expression(
  716. .functionCall(
  717. calledExpression: .return(
  718. .identifierType(
  719. namer.serverResponse(forType: output, isStreaming: streamingOutput)
  720. )
  721. ),
  722. arguments: streamingOutput ? makeStreamingOutputArguments() : makeUnaryOutputArguments()
  723. )
  724. )
  725. ]
  726. )
  727. }
  728. }
  729. @available(gRPCSwift 2.0, *)
  730. extension ExtensionDescription {
  731. /// ```
  732. /// extension ServiceProtocol {
  733. /// ...
  734. /// }
  735. /// ```
  736. static func serviceProtocolDefaultImplementation(
  737. accessModifier: AccessModifier? = nil,
  738. on extensionName: String,
  739. methods: [MethodDescriptor],
  740. namer: Namer = Namer()
  741. ) -> Self {
  742. ExtensionDescription(
  743. onType: extensionName,
  744. declarations: methods.map { method in
  745. .function(
  746. .serviceProtocolDefaultImplementation(
  747. accessModifier: accessModifier,
  748. name: method.name.functionName,
  749. input: method.inputType,
  750. output: method.outputType,
  751. streamingInput: method.isInputStreaming,
  752. streamingOutput: method.isOutputStreaming,
  753. namer: namer
  754. )
  755. )
  756. }
  757. )
  758. }
  759. }