Skip to content

Commit 725d749

Browse files
authored
Check symbols are deprecated on at least one platform before marking unconditionally deprecated (#712)
* Updates unconditional deprecation check Checks that a symbol must be deprecated on at least one platform for the symbol to be marked unconditionally deprecated; this prevents symbols that are only marked unavailable on all known platforms from being shown as unconditionally deprecated. * Adds a platform availability test and test bundle Adds a test checking that unavailability in the symbol graph overrides the default platform availability set in the Info.plist. rdar://112197357
1 parent feb4658 commit 725d749

File tree

5 files changed

+686
-1
lines changed

5 files changed

+686
-1
lines changed

Sources/SwiftDocC/Model/AvailabilityParser.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@ struct AvailabilityParser {
3939
}
4040

4141
// Check if the symbol is unconditionally deprecated
42-
return availability.availability
42+
let isUnconditionallyDeprecated = availability.availability
4343
.allSatisfy { $0.isUnconditionallyDeprecated || $0.isUnconditionallyUnavailable || $0.deprecatedVersion != nil }
44+
// If a symbol is unavailable on all known platforms, it should not be marked unconditionally deprecated.
45+
&& availability.availability.contains(where: { $0.isUnconditionallyDeprecated || $0.deprecatedVersion != nil })
46+
return isUnconditionallyDeprecated
4447
}
4548

4649
/// Determines a symbol's deprecation message that either applies to a given platform or that applies to all platforms.

Tests/SwiftDocCTests/Model/AvailabilityParserTests.swift

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,52 @@ class AvailabilityParserTests: XCTestCase {
154154
XCTAssertTrue(compiler.isDeprecated())
155155
XCTAssertEqual(compiler.deprecationMessage(), "deprecated")
156156
}
157+
158+
func testUnavailableIsNotDeprecated() throws {
159+
let json = """
160+
[
161+
{
162+
"domain": "tvOS",
163+
"isUnconditionallyUnavailable" : true
164+
}
165+
]
166+
"""
167+
let availability = try JSONDecoder().decode(Availability.self, from: json.data(using: .utf8)!)
168+
169+
/// Test all platforms
170+
let compiler = AvailabilityParser(availability)
171+
XCTAssertFalse(compiler.isDeprecated())
172+
}
173+
174+
func testAllPlatformsUnavailableOrDeprecatedIsMarkedDeprecated() throws {
175+
let json = """
176+
[
177+
{
178+
"domain": "tvOS",
179+
"isUnconditionallyUnavailable" : true
180+
},
181+
{
182+
"domain": "macOS",
183+
"message" : "deprecated",
184+
"deprecated": { "major": 10, "minor": 17 }
185+
},
186+
{
187+
"domain": "iOS",
188+
"message" : "deprecated",
189+
"deprecated": { "major": 10, "minor": 17 }
190+
},
191+
{
192+
"domain": "watchOS",
193+
"message" : "deprecated",
194+
"deprecated": { "major": 10, "minor": 17 }
195+
}
196+
]
197+
"""
198+
let availability = try JSONDecoder().decode(Availability.self, from: json.data(using: .utf8)!)
199+
200+
/// Test all platforms
201+
let compiler = AvailabilityParser(availability)
202+
XCTAssertTrue(compiler.isDeprecated())
203+
XCTAssertEqual(compiler.deprecationMessage(), "deprecated")
204+
}
157205
}

Tests/SwiftDocCTests/Rendering/PlatformAvailabilityTests.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,31 @@ class PlatformAvailabilityTests: XCTestCase {
132132
item.name == "My Package" && item.introduced == "2.0"
133133
}))
134134
}
135+
136+
// Test that the Info.plist default availability does not affect the deprecated/unavailable availabilities provided by the symbol graph.
137+
func testAvailabilityParserWithInfoPlistDefaultAvailability() throws {
138+
let (bundle, context) = try testBundleAndContext(named: "AvailabilityOverrideBundle")
139+
140+
let reference = ResolvedTopicReference(
141+
bundleIdentifier: bundle.identifier,
142+
path: "/documentation/MyKit/MyClass",
143+
sourceLanguage: .swift
144+
)
145+
let symbol = try XCTUnwrap(context.entity(with: reference).semantic as? Symbol)
146+
var translator = RenderNodeTranslator(
147+
context: context,
148+
bundle: bundle,
149+
identifier: reference,
150+
source: nil
151+
)
152+
let renderNode = try XCTUnwrap(translator.visitSymbol(symbol) as? RenderNode)
153+
let availability = try XCTUnwrap(renderNode.metadata.platformsVariants.defaultValue)
154+
XCTAssertEqual(availability.count, 4)
155+
availability.forEach { platform in
156+
XCTAssertTrue(platform.deprecated != nil)
157+
}
158+
XCTAssertFalse(availability.contains(where: { platform in
159+
platform.name == "tvOS"
160+
}))
161+
}
135162
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDisplayName</key>
6+
<string>AvailabilityBundle</string>
7+
<key>CFBundleIdentifier</key>
8+
<string>org.swift.docc.availability</string>
9+
<key>CFBundleVersion</key>
10+
<string>0.1.0</string>
11+
<key>CDAppleDefaultAvailability</key>
12+
<dict>
13+
<key>MyKit</key>
14+
<array>
15+
<dict>
16+
<key>name</key>
17+
<string>Mac Catalyst</string>
18+
<key>version</key>
19+
<string>13.0</string>
20+
</dict>
21+
<dict>
22+
<key>name</key>
23+
<string>iOS</string>
24+
<key>version</key>
25+
<string>13.0</string>
26+
</dict>
27+
<dict>
28+
<key>name</key>
29+
<string>tvOS</string>
30+
<key>version</key>
31+
<string>13.0</string>
32+
</dict>
33+
<dict>
34+
<key>name</key>
35+
<string>watchOS</string>
36+
<key>version</key>
37+
<string>6.0</string>
38+
</dict>
39+
<dict>
40+
<key>name</key>
41+
<string>macOS</string>
42+
<key>version</key>
43+
<string>10.15</string>
44+
</dict>
45+
</array>
46+
</dict>
47+
</dict>
48+
</plist>

0 commit comments

Comments
 (0)