Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #165 - Enable documentation comment validation in swift-format #188

4 changes: 2 additions & 2 deletions .swift-format
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"prioritizeKeepingFunctionOutputTogether" : false,
"respectsExistingLineBreaks" : true,
"rules" : {
"AllPublicDeclarationsHaveDocumentation" : false,
"AllPublicDeclarationsHaveDocumentation" : true,
"AlwaysUseLowerCamelCase" : false,
"AmbiguousTrailingClosureOverload" : true,
"BeginDocumentationCommentWithOneLineSummary" : false,
Expand Down Expand Up @@ -50,7 +50,7 @@
"UseSynthesizedInitializer" : true,
"UseTripleSlashForDocumentationComments" : true,
"UseWhereClausesInForLoops" : false,
"ValidateDocumentationComments" : false
"ValidateDocumentationComments" : true
},
"spacesAroundRangeFormationOperators" : false,
"tabWidth" : 8,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ struct Handler: APIProtocol {

@main
struct Main {
/// The entry point of the program.
///
/// This is where the execution of the program begins. Any code you want to run
/// when the program starts should be placed within this method.
///
/// Example:
/// ```
/// public static func main() {
/// print("Hello, World!")
/// }
/// ```
/// - Throws: An error of type `Error` if there's an issue creating or running the Vapor application.
public static func main() throws {
// Create a Vapor application.
let app = Vapor.Application()
Expand Down
5 changes: 3 additions & 2 deletions Sources/PetstoreConsumerTestCore/Assertions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Foundation
import XCTest
import OpenAPIRuntime

/// Asserts that the stringified data matches the expected string value.
public func XCTAssertEqualStringifiedData(
_ expression1: @autoclosure () throws -> Data?,
_ expression2: @autoclosure () throws -> String,
Expand All @@ -33,7 +34,7 @@ public func XCTAssertEqualStringifiedData(
XCTFail(error.localizedDescription, file: file, line: line)
}
}

/// Asserts that the stringified data matches the expected string value.
public func XCTAssertEqualStringifiedData<S: Sequence>(
_ expression1: @autoclosure () throws -> S?,
_ expression2: @autoclosure () throws -> String,
Expand All @@ -52,7 +53,7 @@ public func XCTAssertEqualStringifiedData<S: Sequence>(
XCTFail(error.localizedDescription, file: file, line: line)
}
}

/// Asserts that the stringified data matches the expected string value.
public func XCTAssertEqualStringifiedData(
_ expression1: @autoclosure () throws -> HTTPBody?,
_ expression2: @autoclosure () throws -> String,
Expand Down
2 changes: 2 additions & 0 deletions Sources/PetstoreConsumerTestCore/Common.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public enum TestError: Swift.Error, LocalizedError, CustomStringConvertible, Sen
case unexpectedValue(any Sendable)
case unexpectedMissingRequestBody

/// A human-readable description of the error.
public var description: String {
switch self {
case .noHandlerFound(let method, let path):
Expand All @@ -34,6 +35,7 @@ public enum TestError: Swift.Error, LocalizedError, CustomStringConvertible, Sen
}
}

/// A localized description of the error suitable for presenting to the user.
public var errorDescription: String? {
description
}
Expand Down
29 changes: 29 additions & 0 deletions Sources/PetstoreConsumerTestCore/TestClientTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,47 @@ import OpenAPIRuntime
import Foundation
import HTTPTypes

/// A test implementation of the `ClientTransport` protocol.
///
/// The `TestClientTransport` struct provides a way to simulate network calls by
/// utilizing a custom `CallHandler` closure. This allows testing the behavior of
/// client-side API interactions in controlled scenarios.
///
/// Example usage:
/// ```swift
/// let testTransport = TestClientTransport { request, baseURL, operationID in
/// // Simulate response logic here
/// return Response(...)
/// }
///
/// let client = APIClient(transport: testTransport)
/// ```
public struct TestClientTransport: ClientTransport {

/// A typealias representing a call handler closure for processing client requests.
public typealias CallHandler = @Sendable (HTTPRequest, HTTPBody?, URL, String) async throws -> (
HTTPResponse, HTTPBody?
)

/// The call handler responsible for processing client requests.
public let callHandler: CallHandler

/// Initializes a `TestClientTransport` instance with a custom call handler.
///
/// - Parameter callHandler: The closure responsible for processing client requests.
public init(callHandler: @escaping CallHandler) {
self.callHandler = callHandler
}

/// Sends a client request using the test transport.
///
/// - Parameters:
/// - request: The request to send.
/// - body: The optional HTTP body to include in the request.
/// - baseURL: The base URL for the request.
/// - operationID: The ID of the operation being performed.
/// - Returns: The response received from the call handler.
/// - Throws: An error if the call handler encounters an issue.
public func send(
_ request: HTTPRequest,
body: HTTPBody?,
Expand Down
44 changes: 43 additions & 1 deletion Sources/PetstoreConsumerTestCore/TestServerTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,77 @@
import OpenAPIRuntime
import HTTPTypes

/// A test implementation of the `ServerTransport` protocol for simulating server-side API handling.
///
/// The `TestServerTransport` class allows you to define custom operations and handlers that
/// simulate server-side API handling. This is useful for testing and verifying the behavior of
/// your server-related code without the need for actual network interactions.
///
/// Example usage:
/// ```swift
/// let testTransport = TestServerTransport()
/// try testTransport.register { request, metadata in
/// // Simulate server response logic here
/// return Response(...)
/// }
///
/// let server = MyServer(transport: testTransport)
/// ```
public final class TestServerTransport: ServerTransport {

/// Represents the input parameters for an API operation.
public struct OperationInputs: Equatable {
/// The HTTP method of the operation.
public var method: HTTPRequest.Method
/// The path components of the operation's route.
public var path: String

/// Initializes a new instance of `OperationInputs`.
///
/// - Parameters:
/// - method: The HTTP method of the operation.
/// - path: The path components of the operation's route.
public init(method: HTTPRequest.Method, path: String) {
self.method = method
self.path = path
}
}

/// A typealias representing a handler closure for processing server requests.
public typealias Handler = @Sendable (HTTPRequest, HTTPBody?, ServerRequestMetadata) async throws -> (
HTTPResponse, HTTPBody?
)

/// Represents an operation with its inputs and associated handler.
public struct Operation {
/// The input parameters for the API operation.
public var inputs: OperationInputs
/// The closure representing the server operation logic.
public var closure: Handler

/// Initializes a new instance of `Operation`.
///
/// - Parameters:
/// - inputs: The input parameters for the API operation.
/// - closure: The closure representing the server operation logic
public init(inputs: OperationInputs, closure: @escaping Handler) {
self.inputs = inputs
self.closure = closure
}
}

/// Initializes a new instance of `TestServerTransport`.
public init() {}

/// The array of registered operations.
public private(set) var registered: [Operation] = []

/// Registers a new API operation handler with specific parameters.
///
/// - Parameters:
/// - handler: The closure representing the server operation logic.
/// - method: The HTTP method of the operation.
/// - path: The path components of the operation.
/// - Throws: An error if there's an issue registering the operation.
public func register(
_ handler: @Sendable @escaping (HTTPRequest, HTTPBody?, ServerRequestMetadata) async throws -> (
HTTPResponse, HTTPBody?
Expand Down
9 changes: 9 additions & 0 deletions Sources/_OpenAPIGeneratorCore/Diagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,14 @@ public struct Diagnostic: Error, Codable, Sendable {
}

extension Diagnostic.Severity: CustomStringConvertible {
/// A textual representation of the diagnostic severity.
public var description: String {
rawValue
}
}

extension Diagnostic: CustomStringConvertible {
/// A textual representation of the diagnostic, including location, severity, message, and context.
public var description: String {
var prefix = ""
if let location = location {
Expand All @@ -163,6 +165,7 @@ extension Diagnostic: CustomStringConvertible {
}

extension Diagnostic: LocalizedError {
/// A localized description of the diagnostic.
public var errorDescription: String? {
description
}
Expand Down Expand Up @@ -321,6 +324,9 @@ struct PrintingDiagnosticCollector: DiagnosticCollector {
/// Creates a new collector.
public init() {}

/// Emits a diagnostic message by printing it to the standard output.
///
/// - Parameter diagnostic: The diagnostic message to emit.
public func emit(_ diagnostic: Diagnostic) {
print(diagnostic.description)
}
Expand All @@ -331,6 +337,9 @@ public struct StdErrPrintingDiagnosticCollector: DiagnosticCollector, Sendable {
/// Creates a new collector.
public init() {}

/// Emits a diagnostic message to standard error.
///
/// - Parameter diagnostic: The diagnostic message to emit.
public func emit(_ diagnostic: Diagnostic) {
stdErrHandle.write(diagnostic.description)
}
Expand Down
7 changes: 7 additions & 0 deletions Sources/_OpenAPIGeneratorCore/Extensions/Foundation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extension Data {
extension InMemoryInputFile {
/// Creates a new in-memory file by reading the contents at the specified path.
/// - Parameter url: The path to the file to read.
/// - Throws: An error if there's an issue reading the file or initializing the in-memory file.
init(fromFileAt url: URL) throws {
try self.init(absolutePath: url, contents: Data(contentsOf: url))
}
Expand All @@ -50,6 +51,12 @@ extension InMemoryOutputFile {
let stdErrHandle = FileHandle.standardError

extension FileHandle: TextOutputStream {
/// Writes the given string to the file handle.
///
/// This method writes the provided string to the file handle using its UTF-8
/// representation.
///
/// - Parameter string: The string to be written to the file handle.
public func write(_ string: String) {
write(Data(string.utf8))
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/_OpenAPIGeneratorCore/Extensions/OpenAPIKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ extension Either {
/// Returns the contained value, looking it up in the specified
/// OpenAPI components if it contains a reference.
/// - Parameter components: The Components section of the OpenAPI document.
/// - Returns: The resolved value from the `Either` instance.
/// - Throws: An error if there's an issue looking up the value in the components.
func resolve(
in components: OpenAPI.Components
) throws -> B where A == OpenAPI.Reference<B> {
Expand Down
1 change: 1 addition & 0 deletions Sources/_OpenAPIGeneratorCore/Extensions/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ fileprivate extension String {
/// Returns a copy of the string with the first letter modified by
/// the specified closure.
/// - Parameter transformation: A closure that modifies the first letter.
/// - Returns: A new string with the modified first letter, or the original string if no letter is found.
func transformingFirstLetter<T>(_ transformation: (Character) -> T) -> String where T: StringProtocol {
guard let firstLetterIndex = self.firstIndex(where: \.isLetter) else {
return self
Expand Down
1 change: 1 addition & 0 deletions Sources/_OpenAPIGeneratorCore/GeneratorMode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ extension GeneratorMode {
}

extension GeneratorMode: Comparable {
/// Compares modes based on their order.
public static func < (lhs: GeneratorMode, rhs: GeneratorMode) -> Bool {
lhs.order < rhs.order
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/_OpenAPIGeneratorCore/GeneratorPipeline.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct GeneratorPipeline {
/// recoverable diagnostics, such as unsupported features.
/// - Parameter input: The input of the parsing stage.
/// - Returns: The output of the rendering stage.
/// - Throws: An error if a non-recoverable issue occurs during pipeline execution.
func run(_ input: RawInput) throws -> RenderedOutput {
try renderSwiftFilesStage.run(
translateOpenAPIToStructuredSwiftStage.run(
Expand Down Expand Up @@ -97,6 +98,7 @@ public func runGenerator(
/// Creates a new pipeline instance.
/// - Parameters:
/// - parser: An OpenAPI document parser.
/// - validator: A validator for parsed OpenAPI documents.
/// - translator: A translator from OpenAPI to Swift.
/// - renderer: A Swift code renderer.
/// - formatter: A Swift code formatter.
Expand Down
1 change: 1 addition & 0 deletions Sources/_OpenAPIGeneratorCore/GeneratorPipelineStage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct GeneratorPipelineStage<Input, Output> {
/// value or throwing an error.
/// - Parameter input: An input value.
/// - Returns: An output value.
/// - Throws: An error if an issue occurs during the stage execution.
func run(_ input: Input) throws -> Output {
let hookedInput = try self.preTransitionHooks.reduce(input) { try $1($0) }
let output = try self.transition(hookedInput)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public struct InMemoryOutputFile: Sendable {
}

extension InMemoryOutputFile: Comparable {
/// Compares two `InMemoryOutputFile` instances based on `baseName` and contents for ordering.
public static func < (lhs: InMemoryOutputFile, rhs: InMemoryOutputFile) -> Bool {
guard lhs.baseName == rhs.baseName else {
return lhs.baseName < rhs.baseName
Expand Down
Loading