Skip to content

Commit 320410f

Browse files
Beta tag heuristic should use >= when comparing platform version information (#994)
* Consider symbols to be beta if their introduced version is greater than or equal to the current platform, if the current platform is beta. * SemanticVersion conforms to Comparable, and start migrating away from VersionTriplet and to SemanticVersion by changing two call sites. * Update CLI help message for --platform option * Remove unneeded import statement from VersionTripletTests.swift * Remove duplicate initializer for SemanticVersion * Update to-do comment in SemanticVersion.swift Co-authored-by: Sofía Rodríguez <[email protected]> * Remove unneeded binary file and whitespace change * Remove unneeded import statement --------- Co-authored-by: Sofía Rodríguez <[email protected]>
1 parent 081ad56 commit 320410f

File tree

7 files changed

+67
-18
lines changed

7 files changed

+67
-18
lines changed

Sources/SwiftDocC/Model/Rendering/DocumentationContentRenderer.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ public class DocumentationContentRenderer {
230230
}
231231

232232
// Verify that the current platform is in beta and the version number matches the introduced platform version.
233-
guard current.beta && SemanticVersion(introduced).isEqualToVersionTriplet(current.version) else {
233+
guard current.beta && SemanticVersion(introduced) >= SemanticVersion(versionTriplet: current.version) else {
234234
return false
235235
}
236236
}

Sources/SwiftDocC/Model/Rendering/RenderNodeTranslator.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -1762,7 +1762,8 @@ public struct RenderNodeTranslator: SemanticVisitor {
17621762
// Build a module availability version, defaulting the patch number to 0 if not provided (e.g. 10.15)
17631763
let moduleVersionTriplet = VersionTriplet(moduleVersion[0], moduleVersion[1], moduleVersion.count > 2 ? moduleVersion[2] : 0)
17641764

1765-
return moduleVersionTriplet == targetPlatformVersion.version
1765+
// Consider the module beta if its version is greater than or equal to the target platform
1766+
return moduleVersionTriplet >= targetPlatformVersion.version
17661767
}
17671768

17681769
/// The default availability for modules in a given bundle and module.

Sources/SwiftDocC/Model/Rendering/SemanticVersion.swift

+27-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
/// A semantic version.
1212
///
1313
/// A version that follows the [Semantic Versioning](https://semver.org) specification.
14-
public struct SemanticVersion: Codable, Equatable, CustomStringConvertible {
15-
14+
public struct SemanticVersion: Codable, Equatable, Comparable, CustomStringConvertible {
15+
1616
/// The major version number.
1717
///
1818
/// For example, the `1` in `1.2.3`
@@ -51,6 +51,31 @@ public struct SemanticVersion: Codable, Equatable, CustomStringConvertible {
5151
self.buildMetadata = try container.decodeIfPresent(String.self, forKey: .buildMetadata)
5252
}
5353

54+
// TODO: https://github.com/swiftlang/swift-docc/issues/970
55+
// Migrate all the code to use semantic versions, and not version triplets.
56+
/// Create a semantic version from a version triplet.
57+
init(versionTriplet: VersionTriplet) {
58+
self.major = versionTriplet.major
59+
self.minor = versionTriplet.minor
60+
self.patch = versionTriplet.patch
61+
}
62+
63+
/// Compare one semantic version with another.
64+
///
65+
/// - Parameters:
66+
/// - lhs: A version to compare.
67+
/// - rhs: Another version to compare.
68+
///
69+
/// - Returns: a Boolean value that indicates whether the first version is less than the second version.
70+
public static func < (lhs: SemanticVersion, rhs: SemanticVersion) -> Bool {
71+
if lhs.major != rhs.major { return lhs.major < rhs.major }
72+
if lhs.minor != rhs.minor { return lhs.minor < rhs.minor }
73+
if lhs.patch != rhs.patch { return lhs.patch < rhs.patch }
74+
// Note: don't compare the values of prerelease, even if it is
75+
// present in both semantic versions.
76+
return false // The version are equal
77+
}
78+
5479
public var description: String {
5580
var result = "\(major).\(minor).\(patch)"
5681
if let prerelease {

Sources/SwiftDocC/Model/Rendering/Symbol/AvailabilityRenderMetadataItem.swift

+3-12
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,6 @@ extension SemanticVersion {
5252
self.prerelease = semanticVersion.prerelease
5353
self.buildMetadata = semanticVersion.buildMetadata
5454
}
55-
56-
/// Compares a version triplet to a semantic version.
57-
/// - Parameter version: A version triplet to compare to this semantic version.
58-
/// - Returns: Returns whether the given triple represents the same version as the current version.
59-
func isEqualToVersionTriplet(_ version: VersionTriplet) -> Bool {
60-
return major == version.major &&
61-
minor == version.minor &&
62-
patch == version.patch
63-
}
6455
}
6556

6657
/// Availability information of a symbol on a specific platform.
@@ -154,11 +145,11 @@ public struct AvailabilityRenderItem: Codable, Hashable, Equatable {
154145
}
155146

156147
private static func isBeta(introduced: SemanticVersion?, current: PlatformVersion?) -> Bool {
157-
guard let introduced, let current, current.beta, introduced.isEqualToVersionTriplet(current.version) else {
148+
guard let introduced, let current, current.beta else {
158149
return false
159150
}
160-
161-
return true
151+
152+
return introduced >= SemanticVersion(versionTriplet: current.version)
162153
}
163154

164155
/// Creates a new item with the given platform name and version string.

Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/Convert.swift

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ extension Docc {
148148
help: ArgumentHelp("Specify information about the current release of a platform.", discussion: """
149149
Each platform's information is specified via separate "--platform" values using the following format: "name={platform name},version={semantic version}".
150150
Optionally, the platform information can include a 'beta={true|false}' component. If no beta information is provided, the platform is considered not in beta.
151+
If the platform is set to beta, any symbol introduced in a version equal to or greater than the specified semantic version will be marked as beta.
151152
""")
152153
)
153154
var platforms: [String] = []

Tests/SwiftDocCTests/Model/SemaToRenderNodeTests.swift

+12-1
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,17 @@ Document
19471947

19481948
// Beta platform matching the introduced version
19491949
context.externalMetadata.currentPlatforms = ["macOS": PlatformVersion(VersionTriplet(10, 15, 0), beta: true)]
1950+
1951+
do {
1952+
var translator = RenderNodeTranslator(context: context, bundle: bundle, identifier: reference)
1953+
let renderNode = translator.visitSymbol(symbol) as! RenderNode
1954+
1955+
// Verify platform beta was plumbed all the way to the render JSON
1956+
XCTAssertEqual(renderNode.metadata.platforms?.first?.isBeta, true)
1957+
}
1958+
1959+
// Beta platform earlier than the introduced version
1960+
context.externalMetadata.currentPlatforms = ["macOS": PlatformVersion(VersionTriplet(10, 14, 0), beta: true)]
19501961

19511962
do {
19521963
var translator = RenderNodeTranslator(context: context, bundle: bundle, identifier: reference)
@@ -1959,7 +1970,7 @@ Document
19591970
// Set only some platforms to beta & the exact version MyClass is being introduced at
19601971
context.externalMetadata.currentPlatforms = [
19611972
"macOS": PlatformVersion(VersionTriplet(10, 15, 0), beta: true),
1962-
"watchOS": PlatformVersion(VersionTriplet(3, 0, 0), beta: true),
1973+
"watchOS": PlatformVersion(VersionTriplet(9, 0, 0), beta: true),
19631974
"tvOS": PlatformVersion(VersionTriplet(1, 0, 0), beta: true),
19641975
]
19651976

Tests/SwiftDocCTests/Rendering/DefaultAvailabilityTests.swift

+21-1
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,32 @@ class DefaultAvailabilityTests: XCTestCase {
106106
try? FileManager.default.removeItem(at: url.appendingPathComponent("Info.plist"))
107107
try? FileManager.default.copyItem(at: self.infoPlistAvailabilityURL, to: url.appendingPathComponent("Info.plist"))
108108
}
109-
109+
110110
// Set a beta status for the docs (which would normally be set via command line argument)
111111
context.externalMetadata.currentPlatforms = [
112112
"macOS": PlatformVersion(VersionTriplet(10, 15, 1), beta: true),
113113
"Mac Catalyst": PlatformVersion(VersionTriplet(13, 5, 0), beta: true),
114114
]
115+
116+
// Test if the module availability is also "beta" for the "macOS" platform,
117+
// verify that the Mac Catalyst platform's name (including a space) is rendered correctly
118+
do {
119+
let identifier = ResolvedTopicReference(bundleIdentifier: "org.swift.docc.example", path: "/documentation/MyKit", fragment: nil, sourceLanguage: .swift)
120+
let node = try context.entity(with: identifier)
121+
var translator = RenderNodeTranslator(context: context, bundle: bundle, identifier: node.reference)
122+
let renderNode = translator.visit(node.semantic) as! RenderNode
123+
124+
XCTAssertEqual(renderNode.metadata.platforms?.map({ "\($0.name ?? "") \($0.introduced ?? "")\($0.isBeta == true ? "(beta)" : "")" }).sorted(), [
125+
"Mac Catalyst 13.5(beta)",
126+
"macOS 10.15.1(beta)",
127+
])
128+
}
129+
130+
// Repeat the assertions, but use an earlier platform version this time
131+
context.externalMetadata.currentPlatforms = [
132+
"macOS": PlatformVersion(VersionTriplet(10, 14, 1), beta: true),
133+
"Mac Catalyst": PlatformVersion(VersionTriplet(13, 5, 0), beta: true),
134+
]
115135

116136
// Test if the module availability is also "beta" for the "macOS" platform,
117137
// verify that the Mac Catalyst platform's name (including a space) is rendered correctly

0 commit comments

Comments
 (0)