CodeGenerationRequest.swift 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * Copyright 2023, 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. /// Describes the services, dependencies and trivia from an IDL file,
  17. /// and the IDL itself through its specific serializer and deserializer.
  18. public struct CodeGenerationRequest {
  19. /// The name of the source file containing the IDL, including the extension if applicable.
  20. public var fileName: String
  21. /// Any comments at the top of the file such as documentation and copyright headers.
  22. /// They will be placed at the top of the generated file. They are already formatted,
  23. /// meaning they contain "///" and new lines.
  24. public var leadingTrivia: String
  25. /// The Swift imports that the generated file depends on. The gRPC specific imports aren't required
  26. /// as they will be added by default in the generated file.
  27. ///
  28. /// - SeeAlso: ``Dependency``.
  29. public var dependencies: [Dependency]
  30. /// A description of each service to generate.
  31. ///
  32. /// - SeeAlso: ``ServiceDescriptor``.
  33. public var services: [ServiceDescriptor]
  34. /// Closure that receives a message type as a `String` and returns a code snippet to
  35. /// initialise a `MessageSerializer` for that type as a `String`.
  36. ///
  37. /// The result is inserted in the generated code, where clients serialize RPC inputs and
  38. /// servers serialize RPC outputs.
  39. ///
  40. /// For example, to serialize Protobuf messages you could specify a serializer as:
  41. /// ```swift
  42. /// request.lookupSerializer = { messageType in
  43. /// "ProtobufSerializer<\(messageType)>()"
  44. /// }
  45. /// ```
  46. public var lookupSerializer: (_ messageType: String) -> String
  47. /// Closure that receives a message type as a `String` and returns a code snippet to
  48. /// initialize a `MessageDeserializer` for that type as a `String`.
  49. ///
  50. /// The result is inserted in the generated code, where clients deserialize RPC outputs and
  51. /// servers deserialize RPC inputs.
  52. ///
  53. /// For example, to serialize Protobuf messages you could specify a serializer as:
  54. /// ```swift
  55. /// request.lookupDeserializer = { messageType in
  56. /// "ProtobufDeserializer<\(messageType)>()"
  57. /// }
  58. /// ```
  59. public var lookupDeserializer: (_ messageType: String) -> String
  60. public init(
  61. fileName: String,
  62. leadingTrivia: String,
  63. dependencies: [Dependency],
  64. services: [ServiceDescriptor],
  65. lookupSerializer: @escaping (String) -> String,
  66. lookupDeserializer: @escaping (String) -> String
  67. ) {
  68. self.fileName = fileName
  69. self.leadingTrivia = leadingTrivia
  70. self.dependencies = dependencies
  71. self.services = services
  72. self.lookupSerializer = lookupSerializer
  73. self.lookupDeserializer = lookupDeserializer
  74. }
  75. /// Represents an import: a module or a specific item from a module.
  76. public struct Dependency {
  77. /// If the dependency is an item, the property's value is the item representation.
  78. /// If the dependency is a module, this property is nil.
  79. public var item: Item? = nil
  80. /// The name of the imported module or of the module an item is imported from.
  81. public var module: String
  82. /// The name of the private interface for an `@_spi` import.
  83. ///
  84. /// For example, if `spi` was "Secret" and the module name was "Foo" then the import
  85. /// would be `@_spi(Secret) import Foo`.
  86. public var spi: String?
  87. /// Requirements for the `@preconcurrency` attribute.
  88. public var preconcurrency: PreconcurrencyRequirement
  89. public init(
  90. item: Item? = nil,
  91. module: String,
  92. spi: String? = nil,
  93. preconcurrency: PreconcurrencyRequirement = .notRequired
  94. ) {
  95. self.item = item
  96. self.module = module
  97. self.spi = spi
  98. self.preconcurrency = preconcurrency
  99. }
  100. /// Represents an item imported from a module.
  101. public struct Item {
  102. /// The keyword that specifies the item's kind (e.g. `func`, `struct`).
  103. public var kind: Kind
  104. /// The name of the imported item.
  105. public var name: String
  106. public init(kind: Kind, name: String) {
  107. self.kind = kind
  108. self.name = name
  109. }
  110. /// Represents the imported item's kind.
  111. public struct Kind {
  112. /// Describes the keyword associated with the imported item.
  113. internal enum Value: String {
  114. case `typealias`
  115. case `struct`
  116. case `class`
  117. case `enum`
  118. case `protocol`
  119. case `let`
  120. case `var`
  121. case `func`
  122. }
  123. internal var value: Value
  124. internal init(_ value: Value) {
  125. self.value = value
  126. }
  127. /// The imported item is a typealias.
  128. public static var `typealias`: Self {
  129. Self(.`typealias`)
  130. }
  131. /// The imported item is a struct.
  132. public static var `struct`: Self {
  133. Self(.`struct`)
  134. }
  135. /// The imported item is a class.
  136. public static var `class`: Self {
  137. Self(.`class`)
  138. }
  139. /// The imported item is an enum.
  140. public static var `enum`: Self {
  141. Self(.`enum`)
  142. }
  143. /// The imported item is a protocol.
  144. public static var `protocol`: Self {
  145. Self(.`protocol`)
  146. }
  147. /// The imported item is a let.
  148. public static var `let`: Self {
  149. Self(.`let`)
  150. }
  151. /// The imported item is a var.
  152. public static var `var`: Self {
  153. Self(.`var`)
  154. }
  155. /// The imported item is a function.
  156. public static var `func`: Self {
  157. Self(.`func`)
  158. }
  159. }
  160. }
  161. /// Describes any requirement for the `@preconcurrency` attribute.
  162. public struct PreconcurrencyRequirement {
  163. internal enum Value {
  164. case required
  165. case notRequired
  166. case requiredOnOS([String])
  167. }
  168. internal var value: Value
  169. internal init(_ value: Value) {
  170. self.value = value
  171. }
  172. /// The attribute is always required.
  173. public static var required: Self {
  174. Self(.required)
  175. }
  176. /// The attribute is not required.
  177. public static var notRequired: Self {
  178. Self(.notRequired)
  179. }
  180. /// The attribute is required only on the named operating systems.
  181. public static func requiredOnOS(_ OSs: [String]) -> PreconcurrencyRequirement {
  182. return Self(.requiredOnOS(OSs))
  183. }
  184. }
  185. }
  186. /// Represents a service described in an IDL file.
  187. public struct ServiceDescriptor: Hashable {
  188. /// Documentation from comments above the IDL service description.
  189. /// It is already formatted, meaning it contains "///" and new lines.
  190. public var documentation: String
  191. /// The service name in different formats.
  192. ///
  193. /// All properties of this object must be unique for each service from within a namespace.
  194. public var name: Name
  195. /// The service namespace in different formats.
  196. ///
  197. /// All different services from within the same namespace must have
  198. /// the same ``Name`` object as this property.
  199. /// For `.proto` files the base name of this object is the package name.
  200. public var namespace: Name
  201. /// A description of each method of a service.
  202. ///
  203. /// - SeeAlso: ``MethodDescriptor``.
  204. public var methods: [MethodDescriptor]
  205. public init(
  206. documentation: String,
  207. name: Name,
  208. namespace: Name,
  209. methods: [MethodDescriptor]
  210. ) {
  211. self.documentation = documentation
  212. self.name = name
  213. self.namespace = namespace
  214. self.methods = methods
  215. }
  216. /// Represents a method described in an IDL file.
  217. public struct MethodDescriptor: Hashable {
  218. /// Documentation from comments above the IDL method description.
  219. /// It is already formatted, meaning it contains "///" and new lines.
  220. public var documentation: String
  221. /// Method name in different formats.
  222. ///
  223. /// All properties of this object must be unique for each method
  224. /// from within a service.
  225. public var name: Name
  226. /// Identifies if the method is input streaming.
  227. public var isInputStreaming: Bool
  228. /// Identifies if the method is output streaming.
  229. public var isOutputStreaming: Bool
  230. /// The generated input type for the described method.
  231. public var inputType: String
  232. /// The generated output type for the described method.
  233. public var outputType: String
  234. public init(
  235. documentation: String,
  236. name: Name,
  237. isInputStreaming: Bool,
  238. isOutputStreaming: Bool,
  239. inputType: String,
  240. outputType: String
  241. ) {
  242. self.documentation = documentation
  243. self.name = name
  244. self.isInputStreaming = isInputStreaming
  245. self.isOutputStreaming = isOutputStreaming
  246. self.inputType = inputType
  247. self.outputType = outputType
  248. }
  249. }
  250. }
  251. /// Represents the name associated with a namespace, service or a method, in three different formats.
  252. public struct Name: Hashable {
  253. /// The base name is the name used for the namespace/service/method in the IDL file, so it should follow
  254. /// the specific casing of the IDL.
  255. ///
  256. /// The base name is also used in the descriptors that identify a specific method or service :
  257. /// `<service_namespace_baseName>.<service_baseName>.<method_baseName>`.
  258. public var base: String
  259. /// The `generatedUpperCase` name is used in the generated code. It is expected
  260. /// to be the UpperCamelCase version of the base name
  261. ///
  262. /// For example, if `base` is "fooBar", then `generatedUpperCase` is "FooBar".
  263. public var generatedUpperCase: String
  264. /// The `generatedLowerCase` name is used in the generated code. It is expected
  265. /// to be the lowerCamelCase version of the base name
  266. ///
  267. /// For example, if `base` is "FooBar", then `generatedLowerCase` is "fooBar".
  268. public var generatedLowerCase: String
  269. public init(base: String, generatedUpperCase: String, generatedLowerCase: String) {
  270. self.base = base
  271. self.generatedUpperCase = generatedUpperCase
  272. self.generatedLowerCase = generatedLowerCase
  273. }
  274. }
  275. }