-
Notifications
You must be signed in to change notification settings - Fork 129
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 all 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,105 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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, | ||
pluginSource: .command | ||
) | ||
|
||
let toolUrl = URL(fileURLWithPath: inputs.tool.path.string) | ||
let process = Process() | ||
process.executableURL = toolUrl | ||
process.arguments = inputs.arguments | ||
process.environment = [:] | ||
try process.run() | ||
MahdiBM marked this conversation as resolved.
Show resolved
Hide resolved
|
||
process.waitUntilExit() | ||
MahdiBM marked this conversation as resolved.
Show resolved
Hide resolved
|
||
guard process.terminationStatus == 0 else { | ||
throw PluginError.generatorFailure(targetName: targetName) | ||
} | ||
} | ||
} | ||
|
||
extension SwiftOpenAPIGeneratorPlugin: CommandPlugin { | ||
func performCommand( | ||
context: PluginContext, | ||
arguments: [String] | ||
) async throws { | ||
let targetNameArguments = arguments.filter({ $0 != "--target" }) | ||
let targets: [Target] | ||
if targetNameArguments.isEmpty { | ||
targets = context.package.targets | ||
} else { | ||
let matchingTargets = try context.package.targets(named: targetNameArguments) | ||
let packageTargets = Set(context.package.targets.map(\.id)) | ||
let withLocalDependencies = matchingTargets.flatMap { [$0] + $0.recursiveTargetDependencies } | ||
.filter { packageTargets.contains($0.id) } | ||
let enumeratedKeyValues = withLocalDependencies.map(\.id).enumerated() | ||
.map { (key: $0.element, value: $0.offset) } | ||
let indexLookupTable = Dictionary(enumeratedKeyValues, uniquingKeysWith: { l, _ in l }) | ||
let groupedByID = Dictionary(grouping: withLocalDependencies, by: \.id) | ||
let sortedUniqueTargets = groupedByID.map(\.value[0]) | ||
.sorted { indexLookupTable[$0.id, default: 0] < indexLookupTable[$1.id, default: 0] } | ||
targets = sortedUniqueTargets | ||
} | ||
|
||
guard !targets.isEmpty else { | ||
throw PluginError.noTargetsMatchingTargetNames(targetNameArguments) | ||
} | ||
|
||
var hadASuccessfulRun = false | ||
|
||
for target in targets { | ||
print("Considering target '\(target.name)':") | ||
guard let swiftTarget = target as? SwiftSourceModuleTarget else { | ||
print("- Not a swift source module. Can't generate OpenAPI code.") | ||
continue | ||
} | ||
do { | ||
print("- Trying OpenAPI code generation.") | ||
try runCommand( | ||
targetWorkingDirectory: target.directory, | ||
tool: context.tool, | ||
sourceFiles: swiftTarget.sourceFiles, | ||
targetName: target.name | ||
) | ||
print("- ✅ OpenAPI code generation for target '\(target.name)' successfully completed.") | ||
hadASuccessfulRun = true | ||
} catch let error as PluginError { | ||
if error.isMisconfigurationError { | ||
print("- OpenAPI code generation failed with error.") | ||
throw error | ||
} else { | ||
print("- Stopping because target isn't configured for OpenAPI code generation.") | ||
} | ||
} | ||
} | ||
|
||
guard hadASuccessfulRun else { | ||
throw PluginError.noTargetsWithExpectedFiles(targetNames: targets.map(\.name)) | ||
} | ||
} | ||
} |
File renamed without changes.
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,145 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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 | ||
|
||
enum PluginError: Swift.Error, CustomStringConvertible, LocalizedError { | ||
case incompatibleTarget(name: String) | ||
case generatorFailure(targetName: String) | ||
case noTargetsWithExpectedFiles(targetNames: [String]) | ||
case noTargetsMatchingTargetNames([String]) | ||
case fileErrors([FileError]) | ||
|
||
var description: String { | ||
switch self { | ||
case .incompatibleTarget(let name): | ||
return | ||
"Incompatible target called '\(name)'. Only Swift source targets can be used with the Swift OpenAPI Generator plugin." | ||
case .generatorFailure(let targetName): | ||
return "The generator failed to generate OpenAPI files for target '\(targetName)'." | ||
case .noTargetsWithExpectedFiles(let targetNames): | ||
let fileNames = FileError.Kind.allCases.map(\.name) | ||
.joined(separator: ", ", lastSeparator: " or ") | ||
let targetNames = targetNames.joined(separator: ", ", lastSeparator: " and ") | ||
return | ||
"Targets with names \(targetNames) don't contain any \(fileNames) files with expected names. See documentation for details." | ||
case .noTargetsMatchingTargetNames(let targetNames): | ||
let targetNames = targetNames.joined(separator: ", ", lastSeparator: " and ") | ||
return "Found no targets with names \(targetNames)." | ||
case .fileErrors(let fileErrors): | ||
return "Issues with required files: \(fileErrors.map(\.description).joined(separator: ", and"))." | ||
} | ||
} | ||
|
||
var errorDescription: String? { | ||
description | ||
} | ||
|
||
/// The error is definitely due to misconfiguration of a target. | ||
var isMisconfigurationError: Bool { | ||
switch self { | ||
case .incompatibleTarget: | ||
return false | ||
case .generatorFailure: | ||
return false | ||
case .noTargetsWithExpectedFiles: | ||
return false | ||
case .noTargetsMatchingTargetNames: | ||
return false | ||
case .fileErrors(let errors): | ||
return errors.isMisconfigurationError | ||
} | ||
} | ||
} | ||
|
||
struct FileError: Swift.Error, CustomStringConvertible, LocalizedError { | ||
|
||
/// The kind of the file. | ||
enum Kind: CaseIterable { | ||
/// Config file. | ||
case config | ||
/// OpenAPI document file. | ||
case document | ||
|
||
var name: String { | ||
switch self { | ||
case .config: | ||
return "config" | ||
case .document: | ||
return "OpenAPI document" | ||
} | ||
} | ||
} | ||
|
||
/// Encountered issue. | ||
enum Issue { | ||
/// File wasn't found. | ||
case noFilesFound | ||
/// More than 1 file found. | ||
case multipleFilesFound(files: [Path]) | ||
|
||
/// The error is definitely due to misconfiguration of a target. | ||
var isMisconfigurationError: Bool { | ||
switch self { | ||
case .noFilesFound: | ||
return false | ||
case .multipleFilesFound: | ||
return true | ||
} | ||
} | ||
} | ||
|
||
let targetName: String | ||
let fileKind: Kind | ||
let issue: Issue | ||
|
||
var description: String { | ||
switch fileKind { | ||
case .config: | ||
switch issue { | ||
case .noFilesFound: | ||
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 .multipleFilesFound(let files): | ||
return | ||
"Multiple config files found in the target named '\(targetName)', but exactly one is expected. Found \(files.map(\.description).joined(separator: " "))." | ||
} | ||
case .document: | ||
switch issue { | ||
case .noFilesFound: | ||
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 .multipleFilesFound(let files): | ||
return | ||
"Multiple OpenAPI documents found in the target named '\(targetName)', but exactly one is expected. Found \(files.map(\.description).joined(separator: " "))." | ||
} | ||
} | ||
} | ||
|
||
var errorDescription: String? { | ||
description | ||
} | ||
} | ||
|
||
private extension Array where Element == FileError { | ||
/// The error is definitely due to misconfiguration of a target. | ||
var isMisconfigurationError: Bool { | ||
// If errors for both files exist and none is a "Misconfiguration Error" then the | ||
// error can be related to a target that isn't supposed to be generator compatible at all. | ||
if count == FileError.Kind.allCases.count, self.allSatisfy({ !$0.issue.isMisconfigurationError }) { | ||
return false | ||
} | ||
return true | ||
} | ||
} |
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/PluginSource.swift |
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.