Skip to content

Commit 6ec7920

Browse files
goergisnAlex Guretzki
and
Alex Guretzki
authored
Modularize Package.swift (#27)
* Moving files around * Better modularization * Removing unused code * More modularization * fixing Package.swift file * some fixes * Renaming * Renaming * Renaming * More renaming * Restructuring * Adding swift-docc plugin --------- Co-authored-by: Alex Guretzki <alexander.guretzki@adyen.com>
1 parent 8a6bd75 commit 6ec7920

File tree

92 files changed

+778
-518
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+778
-518
lines changed

Package.resolved

+18
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,24 @@
99
"version" : "1.5.0"
1010
}
1111
},
12+
{
13+
"identity" : "swift-docc-plugin",
14+
"kind" : "remoteSourceControl",
15+
"location" : "https://github.com/apple/swift-docc-plugin",
16+
"state" : {
17+
"revision" : "85e4bb4e1cd62cec64a4b8e769dcefdf0c5b9d64",
18+
"version" : "1.4.3"
19+
}
20+
},
21+
{
22+
"identity" : "swift-docc-symbolkit",
23+
"kind" : "remoteSourceControl",
24+
"location" : "https://github.com/swiftlang/swift-docc-symbolkit",
25+
"state" : {
26+
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
27+
"version" : "1.0.0"
28+
}
29+
},
1230
{
1331
"identity" : "swift-syntax",
1432
"kind" : "remoteSourceControl",

Package.swift

+84-5
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,102 @@ let package = Package(
88
platforms: [
99
.macOS(.v13)
1010
],
11+
products: [
12+
.executable(
13+
name: "public-api-diff",
14+
targets: ["public-api-diff"]
15+
),
16+
.library(
17+
name: "SwiftInterfaceDiff",
18+
targets: [
19+
"PADSwiftInterfaceDiff",
20+
"PADOutputGenerator"
21+
]
22+
),
23+
.library(
24+
name: "PublicApiDiff",
25+
targets: [
26+
"PADProjectBuilder",
27+
"PADSwiftInterfaceDiff",
28+
"PADOutputGenerator"
29+
]
30+
)
31+
],
1132
dependencies: [
1233
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"),
1334
.package(url: "https://github.com/swiftlang/swift-syntax", from: "600.0.0"),
14-
.package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.54.6")
35+
.package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.54.6"),
36+
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0")
1537
],
1638
targets: [
17-
// Targets are the basic building blocks of a package, defining a module or a test suite.
18-
// Targets can depend on other targets in this package and products from dependencies.
39+
40+
// MARK: - Executable Targets
41+
1942
.executableTarget(
2043
name: "public-api-diff",
2144
dependencies: [
22-
.product(name: "ArgumentParser", package: "swift-argument-parser"),
45+
"PADProjectBuilder",
46+
"PADSwiftInterfaceDiff",
47+
"PADOutputGenerator",
48+
.product(name: "ArgumentParser", package: "swift-argument-parser")
49+
],
50+
path: "Sources/ExecutableTargets/CommandLineTool"
51+
),
52+
53+
// MARK: - Public Modules
54+
55+
.target(
56+
name: "PADSwiftInterfaceDiff",
57+
dependencies: [
58+
"PADCore",
59+
"FileHandlingModule",
60+
"PADLogging",
2361
.product(name: "SwiftSyntax", package: "swift-syntax"),
2462
.product(name: "SwiftParser", package: "swift-syntax"),
2563
],
26-
path: "Sources"
64+
path: "Sources/PublicModules/PADSwiftInterfaceDiff"
65+
),
66+
.target(
67+
name: "PADProjectBuilder",
68+
dependencies: [
69+
"PADCore",
70+
"FileHandlingModule",
71+
"PADLogging",
72+
"ShellModule"
73+
],
74+
path: "Sources/PublicModules/PADProjectBuilder"
75+
),
76+
.target(
77+
name: "PADOutputGenerator",
78+
dependencies: ["PADCore"],
79+
path: "Sources/PublicModules/PADOutputGenerator"
80+
),
81+
82+
// MARK: - Shared/Public
83+
84+
.target(
85+
name: "PADCore",
86+
path: "Sources/Shared/Public/PADCore"
87+
),
88+
.target(
89+
name: "PADLogging",
90+
dependencies: ["FileHandlingModule"],
91+
path: "Sources/Shared/Public/PADLogging"
92+
),
93+
94+
// MARK: - Shared/Package
95+
96+
.target(
97+
name: "FileHandlingModule",
98+
path: "Sources/Shared/Package/FileHandlingModule"
99+
),
100+
.target(
101+
name: "ShellModule",
102+
path: "Sources/Shared/Package/ShellModule"
27103
),
104+
105+
// MARK: - Test Targets
106+
28107
.testTarget(
29108
name: "UnitTests",
30109
dependencies: [

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ The `ChangeConsolidator` takes 2 independent changes (`addition` & `removal`) an
4747

4848
### OutputGenerator
4949

50-
Receives a dictionary of `[{SCOPE_NAME}: [Change]]` and processes them into a human readable format.
50+
Receives a dictionary of `[{SCOPE_NAME}: [PADChange]]` and processes them into a human readable format.
5151

5252
# Alternatives
5353
- `xcrun swift-api-digester -dump-sdk` & `xcrun swift-api-digester -diagnose-sdk`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
//
2+
// Copyright (c) 2024 Adyen N.V.
3+
//
4+
// This file is open source and available under the MIT license. See the LICENSE file for more info.
5+
//
6+
7+
import ArgumentParser
8+
import Foundation
9+
10+
import PADCore
11+
import PADLogging
12+
13+
import PADSwiftInterfaceDiff
14+
import PADProjectBuilder
15+
import PADOutputGenerator
16+
17+
@main
18+
struct PublicApiDiff: AsyncParsableCommand {
19+
20+
@Option(help: "Specify the updated version to compare to")
21+
public var new: String
22+
23+
@Option(help: "Specify the old version to compare to")
24+
public var old: String
25+
26+
@Option(help: "Where to output the result (File path)")
27+
public var output: String?
28+
29+
@Option(help: "Where to output the logs (File path)")
30+
public var logOutput: String?
31+
32+
@Option(help: "Which scheme to build (Needed when comparing 2 swift frameworks)")
33+
public var scheme: String?
34+
35+
public func run() async throws {
36+
37+
let logLevel: PADLogLevel = .debug
38+
let projectType: PADProjectType = { // Only needed when we have to produce the .swiftinterface files
39+
if let scheme { return .xcodeProject(scheme: scheme) }
40+
return .swiftPackage
41+
}()
42+
let swiftInterfaceType: PADSwiftInterfaceType = .public // Only needed when we have to produce the .swiftinterface files
43+
44+
let logger = Self.logger(with: logLevel, logOutputFilePath: logOutput)
45+
46+
do {
47+
var warnings = [String]()
48+
var changes = [String: [PADChange]]()
49+
50+
// MARK: - Producing .swiftinterface files
51+
52+
let oldSource: PADProjectSource = try .from(old)
53+
let newSource: PADProjectSource = try .from(new)
54+
55+
let oldVersionName = oldSource.description
56+
let newVersionName = newSource.description
57+
58+
let projectBuilder = PADProjectBuilder(
59+
projectType: projectType,
60+
swiftInterfaceType: swiftInterfaceType,
61+
logger: logger
62+
)
63+
64+
let projectBuilderResult = try await projectBuilder.build(
65+
oldSource: oldSource,
66+
newSource: newSource
67+
)
68+
69+
warnings += projectBuilderResult.warnings
70+
if !projectBuilderResult.packageFileChanges.isEmpty {
71+
changes["Package.swift"] = projectBuilderResult.packageFileChanges
72+
}
73+
74+
// MARK: - Analyze .swiftinterface files
75+
76+
let pipeline = PADSwiftInterfaceDiff(logger: logger)
77+
78+
let pipelineOutput = try await pipeline.run(
79+
with: projectBuilderResult.swiftInterfaceFiles
80+
)
81+
82+
// Merging pipeline output into existing changes - making sure we're not overriding any keys
83+
pipelineOutput.forEach { key, value in
84+
var keyToUse = key
85+
if changes[key] != nil {
86+
keyToUse = "\(key) (\(UUID().uuidString))"
87+
}
88+
changes[keyToUse] = value
89+
}
90+
91+
// MARK: - Generate Output
92+
93+
let outputGenerator: any PADOutputGenerating = PADMarkdownOutputGenerator()
94+
95+
let generatedOutput = try outputGenerator.generate(
96+
from: changes,
97+
allTargets: projectBuilderResult.swiftInterfaceFiles.map(\.name).sorted(),
98+
oldVersionName: oldVersionName,
99+
newVersionName: newVersionName,
100+
warnings: warnings
101+
)
102+
103+
if let output {
104+
try FileManager.default.write(generatedOutput, to: output)
105+
} else {
106+
// We're not using a logger here as we always want to have it printed if no output was specified
107+
print(generatedOutput)
108+
}
109+
110+
logger.log("✅ Success", from: "Main")
111+
} catch {
112+
logger.log("💥 \(error.localizedDescription)", from: "Main")
113+
}
114+
}
115+
}
116+
117+
private extension PublicApiDiff {
118+
119+
static func logger(
120+
with logLevel: PADLogLevel,
121+
logOutputFilePath: String?
122+
) -> any PADLogging {
123+
var loggers = [any PADLogging]()
124+
if let logOutputFilePath {
125+
loggers += [PADLogFileLogger(outputFilePath: logOutputFilePath)]
126+
}
127+
loggers += [PADSystemLogger().withLogLevel(logLevel)]
128+
129+
return PADLoggingGroup(with: loggers)
130+
}
131+
}

Sources/Helpers/Logging/LoggingGroup.swift

-18
This file was deleted.

Sources/Helpers/Models/Constants.swift

-12
This file was deleted.

Sources/Helpers/SwiftInterfaceType.swift

-25
This file was deleted.

Sources/Pipeline/Pipeline+Protocols.swift

-62
This file was deleted.

0 commit comments

Comments
 (0)