Skip to content

Add the ability to set feature flags #139

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

Merged
merged 1 commit into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions Sources/_OpenAPIGeneratorCore/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
/// A single generator pipeline run produces exactly one file, so for
/// generating multiple files, create multiple configuration values, each with
/// a different generator mode.
///
/// TODO: Rename to something more specific, like "GeneratorConfig"
public struct Config {

/// The generator mode to use.
Expand All @@ -28,14 +26,22 @@ public struct Config {
/// Additional imports to add to each generated file.
public var additionalImports: [String]

/// Additional pre-release features to enable.
public var featureFlags: FeatureFlags

/// Creates a configuration with the specified generator mode and imports.
/// - Parameters:
/// - mode: The mode to use for generation.
/// - additionalImports: Additional imports to add to each generated
/// file.
public init(mode: GeneratorMode, additionalImports: [String] = []) {
/// - additionalImports: Additional imports to add to each generated file.
/// - featureFlags: Additional pre-release features to enable.
public init(
mode: GeneratorMode,
additionalImports: [String] = [],
featureFlags: FeatureFlags = []
) {
self.mode = mode
self.additionalImports = additionalImports
self.featureFlags = featureFlags
}
}

Expand Down
39 changes: 39 additions & 0 deletions Sources/_OpenAPIGeneratorCore/FeatureFlags.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftOpenAPIGenerator open source project
//
// Copyright (c) 2023 Apple Inc. and the SwiftOpenAPIGenerator project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

/// A feature that can be explicitly enabled before being released.
///
/// Commonly used to get early feedback on breaking changes, before
/// they are enabled by default, which can only be done in a major version.
///
/// Once a feature is enabled unconditionally in the next major version,
/// the corresponding feature flag should be removed at the same time.
///
/// For example: a breaking feature is being built while version 0.1 is out,
/// and is hidden behind a feature flag. Once ready, the feature is
/// enabled unconditionally on main and the feature flag removed, and version
/// 0.2 is tagged. (This is for pre-1.0 versioning, would be 1.0 and 2.0 after
/// 1.0 is released.)
public enum FeatureFlag: String, Hashable, Equatable, Codable, CaseIterable {

/// Multiple request and response body content types.
///
/// Tracking issues:
/// - https://github.com/apple/swift-openapi-generator/issues/6
/// - https://github.com/apple/swift-openapi-generator/issues/7
case multipleContentTypes
}

/// A set of enabled feature flags.
public typealias FeatureFlags = Set<FeatureFlag>
1 change: 1 addition & 0 deletions Sources/swift-openapi-generator/Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ extension URL: ExpressibleByArgument {
}

extension GeneratorMode: ExpressibleByArgument {}
extension FeatureFlag: ExpressibleByArgument {}

extension CaseIterable where Self: RawRepresentable, Self.RawValue == String {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ extension _GenerateOptions {
let config = try loadedConfig()
let sortedModes = try resolvedModes(config)
let resolvedAdditionalImports = resolvedAdditionalImports(config)
let resolvedFeatureFlags = resolvedFeatureFlags(config)
let configs: [Config] = sortedModes.map {
.init(
mode: $0,
additionalImports: resolvedAdditionalImports
additionalImports: resolvedAdditionalImports,
featureFlags: resolvedFeatureFlags
)
}
let diagnostics: any DiagnosticCollector
Expand All @@ -57,6 +59,7 @@ extension _GenerateOptions {
- OpenAPI document path: \(doc.path)
- Configuration path: \(self.config?.path ?? "<none>")
- Generator modes: \(sortedModes.map(\.rawValue).joined(separator: ", "))
- Feature flags: \(resolvedFeatureFlags.isEmpty ? "<none>" : resolvedFeatureFlags.map(\.rawValue).joined(separator: ", "))
- Output file names: \(sortedModes.map(\.outputFileName).joined(separator: ", "))
- Output directory: \(outputDirectory.path)
- Diagnostics output path: \(diagnosticsOutputPath?.path ?? "<none - logs to stderr>")
Expand Down
14 changes: 13 additions & 1 deletion Sources/swift-openapi-generator/GenerateOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ struct _GenerateOptions: ParsableArguments {
)
var mode: [GeneratorMode] = []

@Option(help: "Additional imports to add to all generated files.")
@Option(help: "Additional import to add to all generated files.")
var additionalImport: [String] = []

@Option(help: "Pre-release feature to enable. Options: \(FeatureFlag.prettyListing).")
var featureFlag: [FeatureFlag] = []

@Option(
help: "When specified, writes out the diagnostics into a YAML file instead of emitting them to standard error."
)
Expand Down Expand Up @@ -77,6 +80,15 @@ extension _GenerateOptions {
return []
}

/// Returns a list of the feature flags requested by the user.
/// - Parameter config: The configuration specified by the user.
func resolvedFeatureFlags(_ config: _UserConfig?) -> FeatureFlags {
if !featureFlag.isEmpty {
return Set(featureFlag)
}
return Set(config?.featureFlags ?? [])
}

/// Returns the configuration requested by the user.
///
/// - Returns: Loaded configuration, if found and parsed successfully.
Expand Down
3 changes: 3 additions & 0 deletions Sources/swift-openapi-generator/UserConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ struct _UserConfig: Codable {
/// A list of names of additional imports that are added to every
/// generated Swift file.
var additionalImports: [String]?

/// A set of features to explicitly enable.
var featureFlags: FeatureFlags?
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@ struct TestConfig: Encodable {
var docFilePath: String
var mode: GeneratorMode
var additionalImports: [String]?
var featureFlags: FeatureFlags?
var referenceOutputDirectory: String
}

extension TestConfig {
var asConfig: Config {
.init(
mode: mode,
additionalImports: additionalImports ?? []
additionalImports: additionalImports ?? [],
featureFlags: featureFlags ?? []
)
}
}
Expand Down Expand Up @@ -134,6 +136,7 @@ class FileBasedReferenceTests: XCTestCase {
docFilePath: "Docs/\(name.fileName)",
mode: mode,
additionalImports: [],
featureFlags: [],
referenceOutputDirectory: "ReferenceSources/\(name.directoryName)"
)
)
Expand Down