From fe5399dcb3ca497d4dece90e2ba734fe67874e09 Mon Sep 17 00:00:00 2001 From: dankinsoid <30962149+dankinsoid@users.noreply.github.com> Date: Sun, 19 Nov 2023 21:19:28 +0400 Subject: [PATCH] 3.0.4 --- README.md | 4 +- .../SwiftOpenAPI/OpenAPIDescriptable.swift | 56 +++---------------- .../OpenAPIDescriptionMacro.swift | 52 ++++++++--------- .../SwiftOpenAPIMacrosTests.swift | 2 +- 4 files changed, 33 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index a04e994..53f40e5 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ The main accent in the library is on simplifying the syntax: the active use of l ## Short example ```swift try OpenAPIObject( - openapi: "3.0.3", + openapi: "3.0.4", info: InfoObject( title: "Example API", version: "0.1.0" @@ -163,7 +163,7 @@ import PackageDescription let package = Package( name: "SomeProject", dependencies: [ - .package(url: "https://github.com/dankinsoid/SwiftOpenAPI.git", from: "3.0.3") + .package(url: "https://github.com/dankinsoid/SwiftOpenAPI.git", from: "3.0.4") ], targets: [ .target(name: "SomeProject", dependencies: ["SwiftOpenAPI"]) diff --git a/Sources/SwiftOpenAPI/OpenAPIDescriptable.swift b/Sources/SwiftOpenAPI/OpenAPIDescriptable.swift index d27888a..1845ba4 100644 --- a/Sources/SwiftOpenAPI/OpenAPIDescriptable.swift +++ b/Sources/SwiftOpenAPI/OpenAPIDescriptable.swift @@ -20,9 +20,9 @@ public extension OpenAPIDescriptable { /// for the type and its stored properties. It's particularly useful for generating comprehensive /// OpenAPI documentation directly from your source code. /// -/// Usage: -/// - Apply this macro to any type that requires documentation in the generated OpenAPI documentation. -/// - Ensure each type and its stored properties are well-documented with relevant comments. +/// - Parameters: +/// - codingKeys: The Bool value indicating whether to use a `CodingKeys` enum for properties names. +/// - docCommentsOnly: The Bool value indicating whether to use only documentation comments (`///` and `/**`). /// /// Features: /// - Automatically extracts and synthesizes descriptions from comments on types and stored properties. @@ -31,9 +31,6 @@ public extension OpenAPIDescriptable { /// - Warning: This macro does not process properties with attributes, as it's currently not feasible /// to distinguish between stored and computed properties in such cases. /// -/// - Note: Your type must have a `CodingKeys` enum (which is synthesized implicitly for `Encodable` and `Decodable` types). -/// Otherwise, if you use a custom `Codable` implementation or if the type is not `Codable` at all, use `OpenAPIRawAutoDescriptable`. -/// /// Example: /// ```swift /// /// Description of MyType. @@ -49,47 +46,10 @@ public extension OpenAPIDescriptable { /// API documentation, streamlining the process of maintaining up-to-date and accurate OpenAPI docs. @attached(member, conformances: OpenAPIDescriptable, names: arbitrary) @attached(extension, conformances: OpenAPIDescriptable, names: arbitrary) -public macro OpenAPIAutoDescriptable() = #externalMacro( - module: "SwiftOpenAPIMacros", - type: "OpenAPICodingKeyDescriptionMacro" -) - -/// `OpenAPIRawAutoDescriptable`: An automatic implementation macro for the `OpenAPIDescriptable` protocol. -/// -/// This macro facilitates the automatic implementation of the `OpenAPIRawAutoDescriptable` protocol -/// for any Swift type, utilizing both standard comments (`//`) and documentation comments (`///`) -/// for the type and its stored properties. It's particularly useful for generating comprehensive -/// OpenAPI documentation directly from your source code. -/// -/// Usage: -/// - Apply this macro to any type that requires documentation in the generated OpenAPI documentation. -/// - Ensure each type and its stored properties are well-documented with relevant comments. -/// -/// Features: -/// - Automatically extracts and synthesizes descriptions from comments on types and stored properties. -/// - Simplifies the process of conforming to `OpenAPIDescriptable` by generating necessary implementation details. -/// -/// - Warning: This macro does not process properties with attributes, as it's currently not feasible -/// to distinguish between stored and computed properties in such cases. -/// -/// - Note: If your type has a `CodingKeys` enum, it is better to use the `OpenAPIAutoDescriptable` macro. -/// -/// Example: -/// ```swift -/// /// Description of MyType. -/// @OpenAPIRawAutoDescriptable -/// struct MyType { -/// -/// /// Description of myProperty. -/// var myProperty: String -/// } -/// ``` -/// -/// The `OpenAPIRawAutoDescriptable` significantly reduces the need for boilerplate code in -/// API documentation, streamlining the process of maintaining up-to-date and accurate OpenAPI docs. -@attached(member, conformances: OpenAPIDescriptable, names: arbitrary) -@attached(extension, conformances: OpenAPIDescriptable, names: arbitrary) -public macro OpenAPIRawAutoDescriptable() = #externalMacro( +public macro OpenAPIAutoDescriptable( + codingKeys: Bool = true, + docCommentsOnly: Bool = false +) = #externalMacro( module: "SwiftOpenAPIMacros", - type: "OpenAPIStringDescriptionMacro" + type: "OpenAPIDescriptionMacro" ) diff --git a/Sources/SwiftOpenAPIMacros/OpenAPIDescriptionMacro.swift b/Sources/SwiftOpenAPIMacros/OpenAPIDescriptionMacro.swift index 1c8cf52..f925fbe 100644 --- a/Sources/SwiftOpenAPIMacros/OpenAPIDescriptionMacro.swift +++ b/Sources/SwiftOpenAPIMacros/OpenAPIDescriptionMacro.swift @@ -7,40 +7,18 @@ import SwiftSyntaxMacros struct OpenAPIDescriptionPlugin: CompilerPlugin { let providingMacros: [Macro.Type] = [ - OpenAPIStringDescriptionMacro.self, - OpenAPICodingKeyDescriptionMacro.self + OpenAPIDescriptionMacro.self ] } -public struct OpenAPIStringDescriptionMacro: ExtensionMacro, MemberMacro { - - public static func expansion( - of node: AttributeSyntax, - providingMembersOf declaration: some DeclGroupSyntax, - in context: some MacroExpansionContext - ) throws -> [DeclSyntax] { - try _expansion(of: node, providingMembersOf: declaration, in: context, type: .String) - } - - public static func expansion( - of node: AttributeSyntax, - attachedTo declaration: some DeclGroupSyntax, - providingExtensionsOf type: some TypeSyntaxProtocol, - conformingTo protocols: [TypeSyntax], - in context: some MacroExpansionContext - ) throws -> [ExtensionDeclSyntax] { - [openAPIDescriptableExtension(for: type)] - } -} - -public struct OpenAPICodingKeyDescriptionMacro: ExtensionMacro, MemberMacro { +public struct OpenAPIDescriptionMacro: ExtensionMacro, MemberMacro { public static func expansion( of node: AttributeSyntax, providingMembersOf declaration: some DeclGroupSyntax, in context: some MacroExpansionContext ) throws -> [DeclSyntax] { - try _expansion(of: node, providingMembersOf: declaration, in: context, type: .CodingKeys) + try _expansion(of: node, providingMembersOf: declaration, in: context) } public static func expansion( @@ -57,12 +35,27 @@ public struct OpenAPICodingKeyDescriptionMacro: ExtensionMacro, MemberMacro { private func _expansion( of node: AttributeSyntax, providingMembersOf declaration: some DeclGroupSyntax, - in context: some MacroExpansionContext, - type: DescriptionType + in context: some MacroExpansionContext ) throws -> [DeclSyntax] { + var onlyDocComments = false + var type: DescriptionType = .CodingKeys + node.arguments?.as(LabeledExprListSyntax.self)?.forEach { + switch $0.label?.text { + case "codingKeys": + if $0.expression.as(BooleanLiteralExprSyntax.self)?.literal.text == "false" { + type = .String + } + case "docCommentsOnly": + if $0.expression.as(BooleanLiteralExprSyntax.self)?.literal.text == "true" { + onlyDocComments = true + } + default: + break + } + } let typeDoc = declaration .children(viewMode: .all) - .compactMap { $0.documentation(onlyDocComment: false) } + .compactMap { $0.documentation(onlyDocComment: onlyDocComments) } .first? .wrapped let varDocs = declaration.memberBlock.members.compactMap { member -> (String, String)? in @@ -79,7 +72,6 @@ private func _expansion( guard let identifier = binding.pattern.as(IdentifierPatternSyntax.self) else { continue } - print(binding) name = identifier.identifier.text if let closure = binding.accessorBlock { guard @@ -95,7 +87,7 @@ private func _expansion( let varDocsModifiers = varDocs.map { "\n .add(for: \(type.wrap(name: $0.0)), \($0.1.wrapped))" } - .joined() + .joined() let openAPIDescription: DeclSyntax = """ diff --git a/Tests/SwiftOpenAPITests/SwiftOpenAPIMacrosTests.swift b/Tests/SwiftOpenAPITests/SwiftOpenAPIMacrosTests.swift index 954b626..0c4968f 100644 --- a/Tests/SwiftOpenAPITests/SwiftOpenAPIMacrosTests.swift +++ b/Tests/SwiftOpenAPITests/SwiftOpenAPIMacrosTests.swift @@ -6,7 +6,7 @@ import SwiftOpenAPIMacros @testable import SwiftOpenAPI let testMacros: [String: Macro.Type] = [ - "OpenAPICodingKeyDescriptionMacro": OpenAPICodingKeyDescriptionMacro.self + "OpenAPIDescriptionMacro": OpenAPIDescriptionMacro.self ] final class OpenAPIDescriptionMacroTests: XCTestCase {