From c925610cc52df7159a1bff3e12208e656faf40da Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Sat, 15 Mar 2025 18:26:15 +0000 Subject: [PATCH 1/6] fix: Attempt to work around PackageDescription.Path deprecation --- Plugins/MetaProtocolCodable/Plugin.swift | 26 ++++++------ .../MetaProtocolCodable/PluginContext.swift | 3 ++ .../SourceTarget/SwiftPackageTarget.swift | 40 +++++++++++++++---- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/Plugins/MetaProtocolCodable/Plugin.swift b/Plugins/MetaProtocolCodable/Plugin.swift index 2279b62b..ea1f95ac 100644 --- a/Plugins/MetaProtocolCodable/Plugin.swift +++ b/Plugins/MetaProtocolCodable/Plugin.swift @@ -50,32 +50,32 @@ struct MetaProtocolCodable: BuildToolPlugin { let (allTargets, imports) = config.scanInput(for: target, in: context) // Setup folder - let genFolder = context.pluginWorkDirectory.appending(["ProtocolGen"]) + let genFolder = context.pluginWorkDirectoryURL try FileManager.default.createDirectory( - atPath: genFolder.string, withIntermediateDirectories: true + at: genFolder, withIntermediateDirectories: true ) // Create source scan commands - var intermFiles: [Path] = [] + var intermFiles: [URL] = [] var buildCommands = allTargets.flatMap { target in return target.sourceFiles(withSuffix: "swift").map { file in let moduleName = target.moduleName - let fileName = file.path.stem + let fileName = file.url.lastPathComponent let genFileName = "\(moduleName)-\(fileName)-gen.json" - let genFile = genFolder.appending([genFileName]) + let genFile = genFolder.appending(path: genFileName) intermFiles.append(genFile) return Command.buildCommand( displayName: """ Parse source file "\(fileName)" in module "\(moduleName)" """, - executable: tool.path, + executable: tool.url, arguments: [ "parse", - file.path.string, + file.url.absoluteString, "--output", - genFile.string, + genFile.absoluteString, ], - inputFiles: [file.path], + inputFiles: [file.url], outputFiles: [genFile] ) } @@ -84,20 +84,20 @@ struct MetaProtocolCodable: BuildToolPlugin { // Create syntax generation command let moduleName = target.moduleName let genFileName = "\(moduleName)+ProtocolHelperCoders.swift" - let genPath = genFolder.appending(genFileName) - var genArgs = ["generate", "--output", genPath.string] + let genPath = genFolder.appending(path:genFileName) + var genArgs = ["generate", "--output", genPath.absoluteString] for `import` in imports { genArgs.append(contentsOf: ["--module", `import`]) } for file in intermFiles { - genArgs.append(file.string) + genArgs.append(file.absoluteString) } buildCommands.append( .buildCommand( displayName: """ Generate protocol decoding/encoding syntax for "\(moduleName)" """, - executable: tool.path, + executable: tool.url, arguments: genArgs, inputFiles: intermFiles, outputFiles: [genPath] diff --git a/Plugins/MetaProtocolCodable/PluginContext.swift b/Plugins/MetaProtocolCodable/PluginContext.swift index 27a8c14d..3f4f8ffe 100644 --- a/Plugins/MetaProtocolCodable/PluginContext.swift +++ b/Plugins/MetaProtocolCodable/PluginContext.swift @@ -1,4 +1,5 @@ import PackagePlugin +import Foundation /// Provides information about the package for which the plugin is invoked, /// as well as contextual information based on the plugin's stated intent @@ -24,6 +25,8 @@ protocol MetaProtocolCodablePluginContext { /// directories for cache files and other file system content that either /// it or the command will need. var pluginWorkDirectory: Path { get } + var pluginWorkDirectoryURL: URL { get } + /// The targets which are local to current context. /// /// These targets are included in the same package/project as this context. diff --git a/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift b/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift index 3258e459..30ede369 100644 --- a/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift +++ b/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift @@ -1,6 +1,14 @@ import Foundation import PackagePlugin +/// This is a workaround because PackageDescription.Target.directoryURL will not be available until version 6.1 +/// See: https://github.com/swiftlang/swift-package-manager/blob/735ddd97fa651729921315c8e46bd790429362cb/Sources/PackagePlugin/PackageModel.swift#L184-L186/// +/// The workaround defines a custom protocol that adds the missing property, and then introduces +/// a new initializer that accepts the actual target protocol and attempts to downcast. +protocol CompatSourceModuleTarget: SourceModuleTarget { + var directoryURL: URL { get } +} + /// Represents an SwiftPM target. /// /// Uses `SourceModuleTarget` to provide conformances. @@ -8,8 +16,27 @@ struct SwiftPackageTarget { /// The actual module for this target. /// /// The conformances provided uses this module. - let module: any SourceModuleTarget + let module: any CompatSourceModuleTarget + +} + +/// Workaround for 6.1 compatibility +extension ClangSourceModuleTarget: CompatSourceModuleTarget {} +extension SwiftSourceModuleTarget: CompatSourceModuleTarget {} + +extension SwiftPackageTarget { +init(module: M) where M: SourceModuleTarget { + switch module { + case let module as ClangSourceModuleTarget: + self.module = module + case let module as SwiftSourceModuleTarget: + self.module = module + default: + fatalError("Unsupported module type") + } +} } + extension SwiftPackageTarget: MetaProtocolCodableSourceTarget { /// The name of the module produced @@ -29,7 +56,7 @@ extension SwiftPackageTarget: MetaProtocolCodableSourceTarget { default: nil } - }.map { Self.init(module: $0) } + }.map { (target: any SourceModuleTarget) in Self.init(module: target) } } /// All the targets on which current target depends on. @@ -64,17 +91,16 @@ extension SwiftPackageTarget: MetaProtocolCodableSourceTarget { /// - Returns: The config file path. func configPath(named name: String) throws -> String? { let fileManager = FileManager.default - let directory = module.directory.string - let contents = try fileManager.contentsOfDirectory(atPath: directory) + let directory = module.directoryURL + let contents = try fileManager.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) let file = contents.first { file in - let path = Path(file) return name.lowercased() - == path.stem + == file.lastPathComponent .components(separatedBy: .alphanumerics.inverted) .joined(separator: "") .lowercased() } guard let file else { return nil } - return module.directory.appending([file]).string + return directory.appending(path: file.absoluteString).absoluteString } } From 3f937b48001a9cd8a8f8be4aec4ac3ea616ed2f3 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Sun, 6 Apr 2025 21:36:11 +0200 Subject: [PATCH 2/6] preserve backwards compatibility --- Plugins/MetaProtocolCodable/Plugin.swift | 6 ++- .../SourceTarget/SwiftPackageTarget.swift | 46 +++++++++---------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/Plugins/MetaProtocolCodable/Plugin.swift b/Plugins/MetaProtocolCodable/Plugin.swift index ea1f95ac..12c6565f 100644 --- a/Plugins/MetaProtocolCodable/Plugin.swift +++ b/Plugins/MetaProtocolCodable/Plugin.swift @@ -50,7 +50,7 @@ struct MetaProtocolCodable: BuildToolPlugin { let (allTargets, imports) = config.scanInput(for: target, in: context) // Setup folder - let genFolder = context.pluginWorkDirectoryURL + let genFolder = context.pluginWorkDirectoryURL.appending(path: "ProtocolGen") try FileManager.default.createDirectory( at: genFolder, withIntermediateDirectories: true ) @@ -60,7 +60,11 @@ struct MetaProtocolCodable: BuildToolPlugin { var buildCommands = allTargets.flatMap { target in return target.sourceFiles(withSuffix: "swift").map { file in let moduleName = target.moduleName + #if swift(<6) + let fileName = URL(string: file.path.string)! + #else let fileName = file.url.lastPathComponent + #endif let genFileName = "\(moduleName)-\(fileName)-gen.json" let genFile = genFolder.appending(path: genFileName) intermFiles.append(genFile) diff --git a/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift b/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift index 30ede369..a4c6cbab 100644 --- a/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift +++ b/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift @@ -1,14 +1,6 @@ import Foundation import PackagePlugin -/// This is a workaround because PackageDescription.Target.directoryURL will not be available until version 6.1 -/// See: https://github.com/swiftlang/swift-package-manager/blob/735ddd97fa651729921315c8e46bd790429362cb/Sources/PackagePlugin/PackageModel.swift#L184-L186/// -/// The workaround defines a custom protocol that adds the missing property, and then introduces -/// a new initializer that accepts the actual target protocol and attempts to downcast. -protocol CompatSourceModuleTarget: SourceModuleTarget { - var directoryURL: URL { get } -} - /// Represents an SwiftPM target. /// /// Uses `SourceModuleTarget` to provide conformances. @@ -16,27 +8,33 @@ struct SwiftPackageTarget { /// The actual module for this target. /// /// The conformances provided uses this module. - let module: any CompatSourceModuleTarget + let module: any SourceModuleTarget } -/// Workaround for 6.1 compatibility -extension ClangSourceModuleTarget: CompatSourceModuleTarget {} -extension SwiftSourceModuleTarget: CompatSourceModuleTarget {} - -extension SwiftPackageTarget { -init(module: M) where M: SourceModuleTarget { - switch module { - case let module as ClangSourceModuleTarget: - self.module = module - case let module as SwiftSourceModuleTarget: - self.module = module - default: - fatalError("Unsupported module type") +/// This is a workaround because PackageDescription.Target.directoryURL will not be available until version 6.1 +/// See: https://github.com/swiftlang/swift-package-manager/blob/735ddd97fa651729921315c8e46bd790429362cb/Sources/PackagePlugin/PackageModel.swift#L184-L186/// +#if swift(<6.1) +extension Target { + var directoryURL: URL { + #if swift(<6) + // No `directoryURL` but `Path` is not deprecated yet + return URL(string: directory.string)! +#else + // Concrete types have `directoryURL` + switch self { + case let target as ClangSourceModuleTarget: + return target.directoryURL + case let target as SwiftSourceModuleTarget: + return target.directoryURL + default: + fatalError("Unsupported target type") + } +#endif } } -} - +#endif + extension SwiftPackageTarget: MetaProtocolCodableSourceTarget { /// The name of the module produced From c68d0cf0d981ab1119211d7d0eda8d8040d16543 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Sun, 6 Apr 2025 21:47:15 +0200 Subject: [PATCH 3/6] cleanup --- Plugins/MetaProtocolCodable/Plugin.swift | 22 +++++++++++++------ .../SourceTarget/SwiftPackageTarget.swift | 5 ++--- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Plugins/MetaProtocolCodable/Plugin.swift b/Plugins/MetaProtocolCodable/Plugin.swift index 12c6565f..44198a30 100644 --- a/Plugins/MetaProtocolCodable/Plugin.swift +++ b/Plugins/MetaProtocolCodable/Plugin.swift @@ -46,6 +46,11 @@ struct MetaProtocolCodable: BuildToolPlugin { ) throws -> [Command] where Context: MetaProtocolCodablePluginContext { // Get config let tool = try context.tool(named: "ProtocolGen") +#if swift(<6) + let toolUrl = URL(string: tool.path.string)! +#else + let toolUrl = tool.url + #endif let config = try fetchConfig(for: target) let (allTargets, imports) = config.scanInput(for: target, in: context) @@ -61,25 +66,28 @@ struct MetaProtocolCodable: BuildToolPlugin { return target.sourceFiles(withSuffix: "swift").map { file in let moduleName = target.moduleName #if swift(<6) - let fileName = URL(string: file.path.string)! + let fileUrl = URL(string: file.path.string)! #else - let fileName = file.url.lastPathComponent + let fileUrl = file.url #endif + let fileName = fileUrl.deletingPathExtension().lastPathComponent let genFileName = "\(moduleName)-\(fileName)-gen.json" let genFile = genFolder.appending(path: genFileName) intermFiles.append(genFile) + + return Command.buildCommand( displayName: """ Parse source file "\(fileName)" in module "\(moduleName)" """, - executable: tool.url, + executable: toolUrl, arguments: [ "parse", - file.url.absoluteString, + fileUrl.absoluteString, "--output", genFile.absoluteString, ], - inputFiles: [file.url], + inputFiles: [fileUrl], outputFiles: [genFile] ) } @@ -88,7 +96,7 @@ struct MetaProtocolCodable: BuildToolPlugin { // Create syntax generation command let moduleName = target.moduleName let genFileName = "\(moduleName)+ProtocolHelperCoders.swift" - let genPath = genFolder.appending(path:genFileName) + let genPath = genFolder.appending(path: genFileName) var genArgs = ["generate", "--output", genPath.absoluteString] for `import` in imports { genArgs.append(contentsOf: ["--module", `import`]) @@ -101,7 +109,7 @@ struct MetaProtocolCodable: BuildToolPlugin { displayName: """ Generate protocol decoding/encoding syntax for "\(moduleName)" """, - executable: tool.url, + executable: toolUrl, arguments: genArgs, inputFiles: intermFiles, outputFiles: [genPath] diff --git a/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift b/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift index a4c6cbab..964a00cf 100644 --- a/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift +++ b/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift @@ -9,7 +9,6 @@ struct SwiftPackageTarget { /// /// The conformances provided uses this module. let module: any SourceModuleTarget - } /// This is a workaround because PackageDescription.Target.directoryURL will not be available until version 6.1 @@ -54,7 +53,7 @@ extension SwiftPackageTarget: MetaProtocolCodableSourceTarget { default: nil } - }.map { (target: any SourceModuleTarget) in Self.init(module: target) } + }.map { Self.init(module: $0) } } /// All the targets on which current target depends on. @@ -93,7 +92,7 @@ extension SwiftPackageTarget: MetaProtocolCodableSourceTarget { let contents = try fileManager.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) let file = contents.first { file in return name.lowercased() - == file.lastPathComponent + == file.deletingPathExtension().lastPathComponent .components(separatedBy: .alphanumerics.inverted) .joined(separator: "") .lowercased() From 240e0eeefb3cc03c22b3e93e8e9fcfdb9d3563db Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Sun, 6 Apr 2025 21:47:58 +0200 Subject: [PATCH 4/6] indentation --- Plugins/MetaProtocolCodable/Plugin.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/MetaProtocolCodable/Plugin.swift b/Plugins/MetaProtocolCodable/Plugin.swift index 44198a30..787cdf06 100644 --- a/Plugins/MetaProtocolCodable/Plugin.swift +++ b/Plugins/MetaProtocolCodable/Plugin.swift @@ -46,9 +46,9 @@ struct MetaProtocolCodable: BuildToolPlugin { ) throws -> [Command] where Context: MetaProtocolCodablePluginContext { // Get config let tool = try context.tool(named: "ProtocolGen") -#if swift(<6) + #if swift(<6) let toolUrl = URL(string: tool.path.string)! -#else + #else let toolUrl = tool.url #endif let config = try fetchConfig(for: target) From eaaed649c2fc8862660858cde6dd877077cadb2e Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Sun, 1 Jun 2025 16:18:30 +0200 Subject: [PATCH 5/6] fix: Unused return value warning --- Sources/ProtocolGen/Generate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/ProtocolGen/Generate.swift b/Sources/ProtocolGen/Generate.swift index a17b733b..d9c2474c 100644 --- a/Sources/ProtocolGen/Generate.swift +++ b/Sources/ProtocolGen/Generate.swift @@ -336,7 +336,7 @@ extension ProtocolGen { ) ).description let sourceData = sourceText.data(using: .utf8) - fileManager.createFile(atPath: output, contents: sourceData) + _ = fileManager.createFile(atPath: output, contents: sourceData) } } } From 14af8444404bfe1ebf56274b318a6a07f88c1441 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Sun, 1 Jun 2025 16:18:54 +0200 Subject: [PATCH 6/6] fix: Remove guard against Swift 6.1: directoryURL doesn't seem to have been added --- .../SourceTarget/SwiftPackageTarget.swift | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift b/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift index 964a00cf..ba9a2943 100644 --- a/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift +++ b/Plugins/MetaProtocolCodable/SourceTarget/SwiftPackageTarget.swift @@ -1,6 +1,7 @@ import Foundation import PackagePlugin + /// Represents an SwiftPM target. /// /// Uses `SourceModuleTarget` to provide conformances. @@ -12,9 +13,8 @@ struct SwiftPackageTarget { } /// This is a workaround because PackageDescription.Target.directoryURL will not be available until version 6.1 -/// See: https://github.com/swiftlang/swift-package-manager/blob/735ddd97fa651729921315c8e46bd790429362cb/Sources/PackagePlugin/PackageModel.swift#L184-L186/// -#if swift(<6.1) -extension Target { +/// See: https://github.com/swiftlang/swift-package-manager/blob/735ddd97fa651729921315c8e46bd790429362cb/Sources/PackagePlugin/PackageModel.swift#L184-L186 +extension PackagePlugin.Target { var directoryURL: URL { #if swift(<6) // No `directoryURL` but `Path` is not deprecated yet @@ -32,8 +32,6 @@ extension Target { #endif } } -#endif - extension SwiftPackageTarget: MetaProtocolCodableSourceTarget { /// The name of the module produced @@ -89,6 +87,7 @@ extension SwiftPackageTarget: MetaProtocolCodableSourceTarget { func configPath(named name: String) throws -> String? { let fileManager = FileManager.default let directory = module.directoryURL +// let directory = URL(string: module.directory.string)! let contents = try fileManager.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) let file = contents.first { file in return name.lowercased()