-
Notifications
You must be signed in to change notification settings - Fork 132
Command Plugin for generating the source code #98
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
Changes from 31 commits
Commits
Show all changes
106 commits
Select commit
Hold shift + click to select a range
31cf1d5
try generator plugin
MahdiBM c5a404d
add new plugin to products
MahdiBM cfb128d
better debugging
MahdiBM b6e4ffe
Update plugin.swift
MahdiBM 7fbde61
fixes
MahdiBM d65e0bf
correct working dir
MahdiBM 45c8824
correct file-manipulation logic
MahdiBM 133a3c1
better file manipulation
MahdiBM 12fec26
generate empty files only for buildtool plugins
MahdiBM db96114
change directory name
MahdiBM 7fd39a2
perform cleanup for previous builds
MahdiBM fbd69d1
better cleanup
MahdiBM d6005dc
refinements
MahdiBM 02cda11
Update plugin.swift
MahdiBM 7f7b33a
fixes for same-name file creations by plugins
MahdiBM 11ee904
better configuration
MahdiBM 0198e6c
fix arguments
MahdiBM 7ada532
better cleanups
MahdiBM 5460188
better cleanups
MahdiBM 3cb098d
move plugins shared logic to shared files
MahdiBM 42c73f3
rename and fix 'invocation-kind' arg to 'invoked-from'
MahdiBM 253e17f
InvocationSource -> internal
MahdiBM 31365ed
better (or worse) InvocationSource handling
MahdiBM 617edfe
remove a lot of unneeded complexity
MahdiBM c381a0c
better message when running the generator
MahdiBM e2c085c
cleanup
MahdiBM ff25cba
fix passing bad arguments
MahdiBM ceaeb2d
even more removing unneeded complexity
MahdiBM 9887742
refinements
MahdiBM 8bd7363
Use existential any
MahdiBM ef1de07
Merge branch 'existential-any-compatibility' into generator-command-p…
MahdiBM e434021
move "any"s to the type names
MahdiBM bdcfd57
Revert "move "any"s to the type names"
MahdiBM 8032cc6
Merge branch 'main' into generator-command-plugin
MahdiBM 74c4e0a
Update Package.swift
MahdiBM d3567d9
Update Package.swift
MahdiBM 4a762b0
fix build
MahdiBM 0e009a0
command plugin by default run on all targets
MahdiBM 4f934b2
Merge branch 'main' into generator-command-plugin
MahdiBM 3b13bb4
Update Package.swift
MahdiBM 20bdc27
fixes
MahdiBM 9162042
more fixes
MahdiBM 94f110c
better error handling
MahdiBM b9337d2
better error reporting
MahdiBM b2cfb69
minor refinements
MahdiBM 3dd92f0
better errors
MahdiBM c14a4b9
better errors
MahdiBM 0b92074
better arguments parsing
MahdiBM 0d410a8
fixes
MahdiBM a92a4a0
better errors again
MahdiBM 5d14ae1
Update plugin.swift
MahdiBM ccdf3c9
Update plugin.swift
MahdiBM e4b38cb
Update plugin.swift
MahdiBM 914d5cf
Revert "Update plugin.swift"
MahdiBM 02998c1
Revert "Update plugin.swift"
MahdiBM 8faa974
Revert "Update plugin.swift"
MahdiBM 5f55d7f
Revert "better errors again"
MahdiBM a27efce
Revert "fixes"
MahdiBM 1f27d7d
Revert "better arguments parsing"
MahdiBM 17ee64c
always run on all targets
MahdiBM 39c0622
soundness
MahdiBM 07e3163
soundness
MahdiBM c72516c
soundness
MahdiBM 379abff
more soundness
MahdiBM 62dba75
repair/add comments
MahdiBM d9282d6
better FileError
MahdiBM f7a834c
more refinements
MahdiBM 691776a
soundness
MahdiBM cb70f29
FileError exclude unneeded info for conciseness
MahdiBM 48120d5
Update Plugins/PluginsShared/PluginError.swift
MahdiBM 125d5b5
apply some suggestions
MahdiBM 9c95116
Merge branch 'main' into generator-command-plugin
MahdiBM 5dbc8e5
Update PluginUtils.swift
MahdiBM fe01b88
get it working with passing only 1 target
MahdiBM 6fc3ff0
run on in-package dependencies too
MahdiBM cb4349d
fixes
MahdiBM cc26a94
more refinements
MahdiBM 8c441eb
Merge branch 'main' into generator-command-plugin
MahdiBM 0bc0d6c
more on-point errors
MahdiBM a97bc8e
better errors
MahdiBM 11ee766
more minor refinements
MahdiBM 75b534e
soundness?
MahdiBM fefdde3
more soundness
MahdiBM 80521ce
minor refinements
MahdiBM dd70138
Update Package.swift
MahdiBM 74efe1d
Update Package.swift
MahdiBM 1cffe16
Update Package.swift
MahdiBM 3962652
partially apply requested changes
MahdiBM 26fefd5
apply remaining requested changes
MahdiBM aa7a8a7
fix wrong variable
MahdiBM 653dc4a
minor improvement
MahdiBM b903f54
minor refinement
MahdiBM 0e7b1ee
soundness?
MahdiBM 4e37d6e
minor change
MahdiBM 8fb9775
apply logging suggestions
MahdiBM e9be1e7
Update plugin.swift
MahdiBM 29b6301
try ✅ in logs
MahdiBM d8e5a47
Update plugin.swift
MahdiBM 1b5286f
remove extra space
MahdiBM 7c9cee3
swift-format to the rescue of me from itself!
MahdiBM d4b7756
exclude directory
MahdiBM a2b0ab4
another try to exclude directory from headers-check script
MahdiBM 96398f4
headers script another try
MahdiBM a4f8584
fix the script itself (the check should still fail)
MahdiBM 4b4d0f8
final soundness fix hopefully?
MahdiBM a611ae2
Merge branch 'main' into generator-command-plugin
czechboy0 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../Plugins/PluginsShared |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../Plugins/PluginsShared |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
import PackagePlugin | ||
import Foundation | ||
|
||
@main | ||
struct SwiftOpenAPIGeneratorPlugin { | ||
func runCommand( | ||
targetWorkingDirectory: Path, | ||
tool: (String) throws -> PluginContext.Tool, | ||
sourceFiles: FileList, | ||
targetName: String | ||
) throws { | ||
let inputs = try PluginUtils.validateInputs( | ||
workingDirectory: targetWorkingDirectory, | ||
tool: tool, | ||
sourceFiles: sourceFiles, | ||
targetName: targetName, | ||
invocationSource: .CommandPlugin | ||
) | ||
|
||
let toolUrl = URL(fileURLWithPath: inputs.tool.path.string) | ||
let process = Process() | ||
process.executableURL = toolUrl | ||
process.arguments = inputs.arguments | ||
try process.run() | ||
} | ||
} | ||
|
||
extension SwiftOpenAPIGeneratorPlugin: CommandPlugin { | ||
func performCommand( | ||
context: PluginContext, | ||
arguments: [String] | ||
) async throws { | ||
guard arguments.count == 2, arguments[0] == "--target" else { | ||
throw PluginError.badArguments(arguments: arguments) | ||
} | ||
let targetName = arguments[1] | ||
let matchingTargets = try context.package.targets(named: [targetName]) | ||
// `matchingTargets.count` can't be 0 because | ||
// `targets(named:)` would throw an error for that. | ||
guard matchingTargets.count == 1 else { | ||
throw PluginError.tooManyTargetsMatchingTargetName(targetNames: matchingTargets.map(\.name)) | ||
} | ||
let target = matchingTargets[0] | ||
guard let swiftTarget = target as? SwiftSourceModuleTarget else { | ||
throw PluginError.incompatibleTarget(targetName: target.name) | ||
} | ||
return try runCommand( | ||
targetWorkingDirectory: target.directory, | ||
tool: context.tool, | ||
sourceFiles: swiftTarget.sourceFiles, | ||
targetName: target.name | ||
) | ||
} | ||
} | ||
|
||
#if canImport(XcodeProjectPlugin) | ||
import XcodeProjectPlugin | ||
|
||
extension SwiftOpenAPIGeneratorPlugin: XcodeCommandPlugin { | ||
func performCommand( | ||
context: XcodePluginContext, | ||
arguments: [String] | ||
) throws { | ||
guard arguments.count == 2, arguments[0] == "--target" else { | ||
throw PluginError.badArguments(arguments: arguments) | ||
} | ||
let targetName = arguments[1] | ||
guard let xcodeTarget = context.xcodeProject.targets.first( | ||
where: { $0.displayName == targetName } | ||
) else { | ||
throw PluginError.noTargetsMatchingTargetName(targetName: targetName) | ||
} | ||
guard let target = xcodeTarget as? SourceModuleTarget else { | ||
throw PluginError.incompatibleTarget(targetName: targetName) | ||
} | ||
return try runCommand( | ||
targetWorkingDirectory: target.directory, | ||
tool: context.tool, | ||
sourceFiles: xcodeTarget.inputFiles, | ||
targetName: xcodeTarget.displayName | ||
) | ||
} | ||
} | ||
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../Sources/swift-openapi-generator/InvocationSource.swift |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import PackagePlugin | ||
import Foundation | ||
|
||
enum PluginError: Swift.Error, CustomStringConvertible, LocalizedError { | ||
case incompatibleTarget(targetName: String) | ||
MahdiBM marked this conversation as resolved.
Show resolved
Hide resolved
|
||
case badArguments(arguments: [String]) | ||
// The description is only suitable for Xcode, as it's only thrown in Xcode plugins. | ||
case noTargetsMatchingTargetName(targetName: String) | ||
MahdiBM marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// The description is not suitable for Xcode, as it's not thrown in Xcode plugins. | ||
case tooManyTargetsMatchingTargetName(targetNames: [String]) | ||
case noConfigFound(targetName: String) | ||
case noDocumentFound(targetName: String) | ||
case multiConfigFound(targetName: String, files: [Path]) | ||
case multiDocumentFound(targetName: String, files: [Path]) | ||
MahdiBM marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
var description: String { | ||
switch self { | ||
case .incompatibleTarget(let targetName): | ||
return | ||
"Incompatible target called '\(targetName)'. Only Swift source targets can be used with the Swift OpenAPI generator plugin." | ||
case .badArguments(let arguments): | ||
return "Bad arguments provided: \(arguments). On Xcode, use Xcode's run plugin UI to choose a specific target. On CLI, pass a specific target's name to the command like so: '--target TARGET_NAME'" | ||
case .noTargetsMatchingTargetName(let targetName): | ||
return "No target called '\(targetName)' were found. Use Xcode's UI to choose a single specific target before triggering the command plugin." | ||
case .tooManyTargetsMatchingTargetName(let targetNames): | ||
return "Too many targets found matching the provided target name: '\(targetNames)'. Target name must be specific enough for the plugin to only find a single target." | ||
case .noConfigFound(let targetName): | ||
return | ||
"No config file found in the target named '\(targetName)'. Add a file called 'openapi-generator-config.yaml' or 'openapi-generator-config.yml' to the target's source directory. See documentation for details." | ||
case .noDocumentFound(let targetName): | ||
return | ||
"No OpenAPI document found in the target named '\(targetName)'. Add a file called 'openapi.yaml', 'openapi.yml' or 'openapi.json' (can also be a symlink) to the target's source directory. See documentation for details." | ||
case .multiConfigFound(let targetName, let files): | ||
return | ||
"Multiple config files found in the target named '\(targetName)', but exactly one is required. Found \(files.map(\.description).joined(separator: " "))." | ||
case .multiDocumentFound(let targetName, let files): | ||
return | ||
"Multiple OpenAPI documents found in the target named '\(targetName)', but exactly one is required. Found \(files.map(\.description).joined(separator: " "))." | ||
} | ||
} | ||
|
||
var errorDescription: String? { | ||
description | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import PackagePlugin | ||
|
||
enum PluginUtils { | ||
private static var supportedConfigFiles: Set<String> { Set(["yaml", "yml"].map { "openapi-generator-config." + $0 }) } | ||
private static var supportedDocFiles: Set<String> { Set(["yaml", "yml", "json"].map { "openapi." + $0 }) } | ||
|
||
struct ValidatedInputs { | ||
let doc: Path | ||
let config: Path | ||
let genSourcesDir: Path | ||
let arguments: [String] | ||
let tool: PluginContext.Tool | ||
} | ||
|
||
static func validateInputs( | ||
workingDirectory: Path, | ||
tool: (String) throws -> PluginContext.Tool, | ||
sourceFiles: FileList, | ||
targetName: String, | ||
invocationSource: InvocationSource | ||
) throws -> ValidatedInputs { | ||
let inputFiles = sourceFiles | ||
let matchedConfigs = inputFiles.filter { supportedConfigFiles.contains($0.path.lastComponent) }.map(\.path) | ||
guard matchedConfigs.count > 0 else { | ||
throw PluginError.noConfigFound(targetName: targetName) | ||
} | ||
guard matchedConfigs.count == 1 else { | ||
throw PluginError.multiConfigFound(targetName: targetName, files: matchedConfigs) | ||
} | ||
let config = matchedConfigs[0] | ||
|
||
let matchedDocs = inputFiles.filter { supportedDocFiles.contains($0.path.lastComponent) }.map(\.path) | ||
guard matchedDocs.count > 0 else { | ||
throw PluginError.noDocumentFound(targetName: targetName) | ||
} | ||
guard matchedDocs.count == 1 else { | ||
throw PluginError.multiDocumentFound(targetName: targetName, files: matchedDocs) | ||
} | ||
let doc = matchedDocs[0] | ||
let genSourcesDir = workingDirectory.appending("GeneratedSources") | ||
|
||
let arguments = [ | ||
"generate", "\(doc)", | ||
"--config", "\(config)", | ||
"--output-directory", "\(genSourcesDir)", | ||
"--invoked-from", "\(invocationSource.rawValue)" | ||
] | ||
|
||
let tool = try tool("swift-openapi-generator") | ||
|
||
return ValidatedInputs( | ||
doc: doc, | ||
config: config, | ||
genSourcesDir: genSourcesDir, | ||
arguments: arguments, | ||
tool: tool | ||
) | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.