From bc4cef885133e8120a152fa7e0737975117332bc Mon Sep 17 00:00:00 2001 From: "i.myakotin" <> Date: Mon, 28 Feb 2022 15:10:21 +0300 Subject: [PATCH 1/4] Parsing swift interface --- Sourcery/Configuration.swift | 46 +++++++++++++++++++-- Sourcery/Sourcery.swift | 4 ++ SourceryUtils/Sources/Path+Extensions.swift | 2 +- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/Sourcery/Configuration.swift b/Sourcery/Configuration.swift index c09325ec3..96f55578a 100644 --- a/Sourcery/Configuration.swift +++ b/Sourcery/Configuration.swift @@ -12,15 +12,52 @@ public struct Project { public let exclude: [Path] public struct Target { + + public struct XCFramework { + + public let path: Path + + public init(rawPath: String, relativePath: Path) throws { + let frameworkRelativePath = Path(rawPath, relativeTo: relativePath) + guard let framework = frameworkRelativePath.components.last else { + throw Configuration.Error.invalidXCFramework(message: "Framework path invalid. Expected String.") + } + let `extension` = Path(framework).`extension` + guard `extension` == "xcframework" else { + throw Configuration.Error.invalidXCFramework(message: "Framework path invalid. Expected path to xcframework file.") + } + let moduleName = Path(framework).lastComponentWithoutExtension + guard + let simulatorSlicePath = frameworkRelativePath.glob("*") + .first(where: { $0.lastComponent.contains("simulator") }) + else { + throw Configuration.Error.invalidXCFramework(message: "Framework path invalid. Expected to find simulator slice.") + } + let modulePath = simulatorSlicePath + Path("\(moduleName).framework/Modules/\(moduleName).swiftmodule/") + guard let interface = modulePath.glob("*.swiftinterface").first(where: { $0.lastComponent.contains("simulator") }) + else { + throw Configuration.Error.invalidXCFramework(message: "Framework path invalid. Expected to find .swiftinterface.") + } + self.path = interface + } + } + public let name: String public let module: String + public let xcframework: XCFramework? - public init(dict: [String: String]) throws { + public init(dict: [String: String], relativePath: Path) throws { guard let name = dict["name"] else { throw Configuration.Error.invalidSources(message: "Target name is not provided. Expected string.") } self.name = name self.module = dict["module"] ?? name + do { + self.xcframework = try dict["xcframework"].map { try .init(rawPath: $0, relativePath: relativePath) } + } catch let error as Configuration.Error { + Log.warning(error.description) + self.xcframework = nil + } } } @@ -31,9 +68,9 @@ public struct Project { let targetsArray: [Target] if let targets = dict["target"] as? [[String: String]] { - targetsArray = try targets.map({ try Target(dict: $0) }) + targetsArray = try targets.map({ try Target(dict: $0, relativePath: relativePath) }) } else if let target = dict["target"] as? [String: String] { - targetsArray = try [Target(dict: target)] + targetsArray = try [Target(dict: target, relativePath: relativePath)] } else { throw Configuration.Error.invalidSources(message: "'target' key is missing. Expected object or array of objects.") } @@ -209,6 +246,7 @@ public struct Configuration { public enum Error: Swift.Error, CustomStringConvertible { case invalidFormat(message: String) case invalidSources(message: String) + case invalidXCFramework(message: String) case invalidTemplates(message: String) case invalidOutput(message: String) case invalidCacheBasePath(message: String) @@ -220,6 +258,8 @@ public struct Configuration { return "Invalid config file format. \(message)" case .invalidSources(let message): return "Invalid sources. \(message)" + case .invalidXCFramework(let message): + return "Invalid xcframework. \(message)" case .invalidTemplates(let message): return "Invalid templates. \(message)" case .invalidOutput(let message): diff --git a/Sourcery/Sourcery.swift b/Sourcery/Sourcery.swift index 844e1ccc4..cb117e5e9 100644 --- a/Sourcery/Sourcery.swift +++ b/Sourcery/Sourcery.swift @@ -95,6 +95,10 @@ public class Sourcery { paths.append(file) modules.append(target.module) } + if let xcframework = target.xcframework { + paths.append(xcframework.path) + modules.append(target.module) + } } } result = try self.parse(from: paths, forceParse: forceParse, parseDocumentation: parseDocumentation, modules: modules, requiresFileParserCopy: hasSwiftTemplates) diff --git a/SourceryUtils/Sources/Path+Extensions.swift b/SourceryUtils/Sources/Path+Extensions.swift index ca3c9c661..48f22cf59 100644 --- a/SourceryUtils/Sources/Path+Extensions.swift +++ b/SourceryUtils/Sources/Path+Extensions.swift @@ -52,7 +52,7 @@ extension Path { } public var isSwiftSourceFile: Bool { - return !self.isDirectory && self.extension == "swift" + return !self.isDirectory && (self.extension == "swift" || self.extension == "swiftinterface") } public func hasExtension(as string: String) -> Bool { From fa66fbd507c8b16f4f5c09ee98e781c3747db83e Mon Sep 17 00:00:00 2001 From: "i.myakotin" <> Date: Mon, 28 Feb 2022 15:15:38 +0300 Subject: [PATCH 2/4] Naming --- Sourcery/Configuration.swift | 4 +++- Sourcery/Sourcery.swift | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Sourcery/Configuration.swift b/Sourcery/Configuration.swift index 96f55578a..024e8adc0 100644 --- a/Sourcery/Configuration.swift +++ b/Sourcery/Configuration.swift @@ -16,6 +16,7 @@ public struct Project { public struct XCFramework { public let path: Path + public let swiftInterfacePath: Path public init(rawPath: String, relativePath: Path) throws { let frameworkRelativePath = Path(rawPath, relativeTo: relativePath) @@ -38,7 +39,8 @@ public struct Project { else { throw Configuration.Error.invalidXCFramework(message: "Framework path invalid. Expected to find .swiftinterface.") } - self.path = interface + self.path = frameworkRelativePath + self.swiftInterfacePath = interface } } diff --git a/Sourcery/Sourcery.swift b/Sourcery/Sourcery.swift index cb117e5e9..13f2e4c9e 100644 --- a/Sourcery/Sourcery.swift +++ b/Sourcery/Sourcery.swift @@ -96,7 +96,7 @@ public class Sourcery { modules.append(target.module) } if let xcframework = target.xcframework { - paths.append(xcframework.path) + paths.append(xcframework.swiftInterfacePath) modules.append(target.module) } } From 419ca55a42dfbd31121f7fb8f9380fddb4cbfe2d Mon Sep 17 00:00:00 2001 From: "i.myakotin" <> Date: Thu, 3 Mar 2022 14:23:52 +0300 Subject: [PATCH 3/4] Supporting array for xcframework key --- Sourcery/Configuration.swift | 21 +++++++++++---------- Sourcery/Sourcery.swift | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Sourcery/Configuration.swift b/Sourcery/Configuration.swift index 024e8adc0..3c7e7752d 100644 --- a/Sourcery/Configuration.swift +++ b/Sourcery/Configuration.swift @@ -35,30 +35,31 @@ public struct Project { throw Configuration.Error.invalidXCFramework(message: "Framework path invalid. Expected to find simulator slice.") } let modulePath = simulatorSlicePath + Path("\(moduleName).framework/Modules/\(moduleName).swiftmodule/") - guard let interface = modulePath.glob("*.swiftinterface").first(where: { $0.lastComponent.contains("simulator") }) + guard let interfacePath = modulePath.glob("*.swiftinterface").first(where: { $0.lastComponent.contains("simulator") }) else { throw Configuration.Error.invalidXCFramework(message: "Framework path invalid. Expected to find .swiftinterface.") } self.path = frameworkRelativePath - self.swiftInterfacePath = interface + self.swiftInterfacePath = interfacePath } } public let name: String public let module: String - public let xcframework: XCFramework? + public let xcframeworks: [XCFramework] - public init(dict: [String: String], relativePath: Path) throws { - guard let name = dict["name"] else { + public init(dict: [String: Any], relativePath: Path) throws { + guard let name = dict["name"] as? String else { throw Configuration.Error.invalidSources(message: "Target name is not provided. Expected string.") } self.name = name - self.module = dict["module"] ?? name + self.module = (dict["module"] as? String) ?? name do { - self.xcframework = try dict["xcframework"].map { try .init(rawPath: $0, relativePath: relativePath) } + self.xcframeworks = try (dict["xcframeworks"] as? [String])? + .map { try XCFramework(rawPath: $0, relativePath: relativePath) } ?? [] } catch let error as Configuration.Error { Log.warning(error.description) - self.xcframework = nil + self.xcframeworks = [] } } } @@ -69,9 +70,9 @@ public struct Project { } let targetsArray: [Target] - if let targets = dict["target"] as? [[String: String]] { + if let targets = dict["target"] as? [[String: Any]] { targetsArray = try targets.map({ try Target(dict: $0, relativePath: relativePath) }) - } else if let target = dict["target"] as? [String: String] { + } else if let target = dict["target"] as? [String: Any] { targetsArray = try [Target(dict: target, relativePath: relativePath)] } else { throw Configuration.Error.invalidSources(message: "'target' key is missing. Expected object or array of objects.") diff --git a/Sourcery/Sourcery.swift b/Sourcery/Sourcery.swift index 13f2e4c9e..de5331b32 100644 --- a/Sourcery/Sourcery.swift +++ b/Sourcery/Sourcery.swift @@ -95,8 +95,8 @@ public class Sourcery { paths.append(file) modules.append(target.module) } - if let xcframework = target.xcframework { - paths.append(xcframework.swiftInterfacePath) + for framework in target.xcframeworks { + paths.append(framework.swiftInterfacePath) modules.append(target.module) } } From 78acaca604ddd1d917a28ee8ccd55007c86541c3 Mon Sep 17 00:00:00 2001 From: "i.myakotin" <> Date: Fri, 4 Mar 2022 09:03:04 +0300 Subject: [PATCH 4/4] Documentation --- CHANGELOG.md | 4 ++++ docs/usage.html | 5 ++++- guides/Usage.md | 5 ++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a075d322..5fedde373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Sourcery CHANGELOG +## Main +## New Features +- Adds `xcframework` key to `target` object in configuration file to enable processing of `swiftinterface` + ## 1.7.0 ## New Features diff --git a/docs/usage.html b/docs/usage.html index 7595d182f..8bcabc2e6 100644 --- a/docs/usage.html +++ b/docs/usage.html @@ -293,12 +293,15 @@

Sources

- <source file path> -

Or you can provide project which will be scanned and which source files will be processed. You can use several project or target objects to scan multiple targets from one project or to scan multiple projects.

+

Or you can provide project which will be scanned and which source files will be processed. You can use several project or target objects to scan multiple targets from one project or to scan multiple projects. You can provide paths to XCFramework files if your target has any and you want to process their swiftinterface files.

project:
   file: <path to xcodeproj file>
   target:
     name: <target name>
     module: <module name> //required if different from target name
+    xcframeworks:
+    - <path to xcframework file>
+    - <path to xcframework file>
 

Excluding sources or templates

diff --git a/guides/Usage.md b/guides/Usage.md index 25e02f452..66e01ad7c 100644 --- a/guides/Usage.md +++ b/guides/Usage.md @@ -87,7 +87,7 @@ sources: - ``` -Or you can provide project which will be scanned and which source files will be processed. You can use several `project` or `target` objects to scan multiple targets from one project or to scan multiple projects. +Or you can provide project which will be scanned and which source files will be processed. You can use several `project` or `target` objects to scan multiple targets from one project or to scan multiple projects. You can provide paths to XCFramework files if your target has any and you want to process their `swiftinterface` files. ```yaml project: @@ -95,6 +95,9 @@ project: target: name: module: //required if different from target name + xcframeworks: + - + - ``` #### Excluding sources or templates