Skip to content

Commit

Permalink
Parsing .swiftinterface form xcframework (#1035)
Browse files Browse the repository at this point in the history
* Parsing swift interface

* Naming

* Supporting array for xcframework key

* Documentation

Co-authored-by: i.myakotin <>
  • Loading branch information
rehsals authored Mar 21, 2022
1 parent 75b1b26 commit 75e91b5
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
57 changes: 50 additions & 7 deletions Sourcery/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,55 @@ public struct Project {
public let exclude: [Path]

public struct Target {

public struct XCFramework {

public let path: Path
public let swiftInterfacePath: 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 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 = interfacePath
}
}

public let name: String
public let module: String
public let xcframeworks: [XCFramework]

public init(dict: [String: String]) 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.xcframeworks = try (dict["xcframeworks"] as? [String])?
.map { try XCFramework(rawPath: $0, relativePath: relativePath) } ?? []
} catch let error as Configuration.Error {
Log.warning(error.description)
self.xcframeworks = []
}
}
}

Expand All @@ -30,10 +70,10 @@ public struct Project {
}

let targetsArray: [Target]
if let targets = dict["target"] as? [[String: String]] {
targetsArray = try targets.map({ try Target(dict: $0) })
} else if let target = dict["target"] as? [String: String] {
targetsArray = try [Target(dict: target)]
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: Any] {
targetsArray = try [Target(dict: target, relativePath: relativePath)]
} else {
throw Configuration.Error.invalidSources(message: "'target' key is missing. Expected object or array of objects.")
}
Expand Down Expand Up @@ -209,6 +249,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)
Expand All @@ -220,6 +261,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):
Expand Down
4 changes: 4 additions & 0 deletions Sourcery/Sourcery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ public class Sourcery {
paths.append(file)
modules.append(target.module)
}
for framework in target.xcframeworks {
paths.append(framework.swiftInterfacePath)
modules.append(target.module)
}
}
}
result = try self.parse(from: paths, forceParse: forceParse, parseDocumentation: parseDocumentation, modules: modules, requiresFileParserCopy: hasSwiftTemplates)
Expand Down
2 changes: 1 addition & 1 deletion SourceryUtils/Sources/Path+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 4 additions & 1 deletion docs/usage.html
Original file line number Diff line number Diff line change
Expand Up @@ -293,12 +293,15 @@ <h4 id='sources' class='heading'>Sources</h4>
<span class="pi">-</span> <span class="s">&lt;source file path&gt;</span>
</code></pre>

<p>Or you can provide project which will be scanned and which source files will be processed. You can use several <code>project</code> or <code>target</code> objects to scan multiple targets from one project or to scan multiple projects.</p>
<p>Or you can provide project which will be scanned and which source files will be processed. You can use several <code>project</code> or <code>target</code> 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 <code>swiftinterface</code> files.</p>
<pre class="highlight yaml"><code><span class="na">project</span><span class="pi">:</span>
<span class="na">file</span><span class="pi">:</span> <span class="s">&lt;path to xcodeproj file&gt;</span>
<span class="na">target</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">&lt;target name&gt;</span>
<span class="na">module</span><span class="pi">:</span> <span class="s">&lt;module name&gt; //required if different from target name</span>
<span class="na">xcframeworks</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">&lt;path to xcframework file&gt;</span>
<span class="pi">-</span> <span class="s">&lt;path to xcframework file&gt;</span>
</code></pre>
<h4 id='excluding-sources-or-templates' class='heading'>Excluding sources or templates</h4>

Expand Down
5 changes: 4 additions & 1 deletion guides/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,17 @@ 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.

```yaml
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
Expand Down

0 comments on commit 75e91b5

Please sign in to comment.