Skip to content

Commit cfcd96f

Browse files
mgrebenetsMax Grebenets
andauthored
(#1257) Combined module link issue - public extension of dependent module causes resolution failure (#1327)
* (#1257) Combined module link issue - public extension of dependent module causes resolution failure * Apply suggestions from code review * Address feedback comments - Cleanup unrelated assertions - Use readable names for IDs - Cleanup unused IDs - Make sure the tests clearly show that relative paths resolve and absolute paths thoe 'no module' error - Use ExtendedModule name --------- Co-authored-by: Max Grebenets <mgrebenets@apple.com>
1 parent 0b356e8 commit cfcd96f

File tree

2 files changed

+88
-2
lines changed

2 files changed

+88
-2
lines changed

Sources/SwiftDocC/Infrastructure/Link Resolution/PathHierarchy+Find.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ extension PathHierarchy {
8484
if let moduleMatch = modules.first(where: { $0.matches(firstComponent) }) {
8585
return try searchForNode(descendingFrom: moduleMatch, pathComponents: remaining.dropFirst(), onlyFindSymbols: onlyFindSymbols, rawPathForError: rawPath)
8686
}
87-
if modules.count == 1 {
87+
// For absolute links, only use the single-module fallback if the first component doesn't match
88+
// any module name
89+
if modules.count == 1 && !isAbsolute {
8890
do {
8991
return try searchForNode(descendingFrom: modules.first!, pathComponents: remaining, onlyFindSymbols: onlyFindSymbols, rawPathForError: rawPath)
9092
} catch {

Tests/SwiftDocCTests/Infrastructure/PathHierarchyTests.swift

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3198,7 +3198,91 @@ class PathHierarchyTests: XCTestCase {
31983198
try assertFindsPath("/MainModule/TopLevelProtocol/extensionMember(_:)", in: tree, asSymbolID: "extensionMember1")
31993199
try assertFindsPath("/MainModule/TopLevelProtocol/InnerStruct/extensionMember(_:)", in: tree, asSymbolID: "extensionMember2")
32003200
}
3201-
3201+
3202+
func testAbsoluteLinksToOtherModuleWithExtensions() async throws {
3203+
enableFeatureFlag(\.isExperimentalLinkHierarchySerializationEnabled)
3204+
3205+
let extendedTypeID = "extended-type-id"
3206+
let extensionID = "extension-id"
3207+
let extensionMethodID = "extension-method-id"
3208+
3209+
let extensionMixin = SymbolGraph.Symbol.Swift.Extension(
3210+
extendedModule: "ExtendedModule",
3211+
typeKind: .struct,
3212+
constraints: []
3213+
)
3214+
3215+
let catalog = Folder(name: "TestCatalog.docc", content: [
3216+
JSONFile(name: "MainModule.symbols.json", content: makeSymbolGraph(moduleName: "MainModule", symbols: [])),
3217+
JSONFile(name: "MainModule@ExtendedModule.symbols.json", content: makeSymbolGraph(
3218+
moduleName: "MainModule",
3219+
symbols: [
3220+
makeSymbol(
3221+
id: extensionID,
3222+
kind: .extension,
3223+
pathComponents: ["ExtendedType"],
3224+
otherMixins: [extensionMixin]
3225+
),
3226+
makeSymbol(
3227+
id: extensionMethodID,
3228+
kind: .method,
3229+
pathComponents: ["ExtendedType", "extensionMethod()"],
3230+
otherMixins: [extensionMixin]
3231+
)
3232+
],
3233+
relationships: [
3234+
.init(
3235+
source: extensionMethodID,
3236+
target: extensionID,
3237+
kind: .memberOf,
3238+
targetFallback: "ExtendedModule.ExtendedType"
3239+
),
3240+
.init(
3241+
source: extensionID,
3242+
target: extendedTypeID,
3243+
kind: .extensionTo,
3244+
targetFallback: "ExtendedModule.ExtendedType"
3245+
)
3246+
]
3247+
))
3248+
])
3249+
3250+
let (_, context) = try await loadBundle(catalog: catalog)
3251+
let tree = context.linkResolver.localResolver.pathHierarchy
3252+
3253+
try assertFindsPath(
3254+
"/MainModule/ExtendedModule/ExtendedType/extensionMethod()",
3255+
in: tree,
3256+
asSymbolID: extensionMethodID
3257+
)
3258+
3259+
try assertFindsPath(
3260+
"ExtendedModule/ExtendedType",
3261+
in: tree,
3262+
asSymbolID: extensionID
3263+
)
3264+
try assertFindsPath(
3265+
"ExtendedModule/ExtendedType/extensionMethod()",
3266+
in: tree,
3267+
asSymbolID: extensionMethodID
3268+
)
3269+
3270+
// Verify that a link that resolves relative to the module
3271+
// fails to resolve as an absolute link, with a moduleNotFound error.
3272+
try assertPathRaisesErrorMessage(
3273+
"/ExtendedModule/ExtendedType",
3274+
in: tree,
3275+
context: context,
3276+
expectedErrorMessage: "No module named 'ExtendedModule'"
3277+
)
3278+
try assertPathRaisesErrorMessage(
3279+
"/ExtendedModule/ExtendedType/extensionMethod()",
3280+
in: tree,
3281+
context: context,
3282+
expectedErrorMessage: "No module named 'ExtendedModule'"
3283+
)
3284+
}
3285+
32023286
func testMissingRequiredMemberOfSymbolGraphRelationshipInOneLanguageAcrossManyPlatforms() async throws {
32033287
// We make a best-effort attempt to create a valid path hierarchy, even if the symbol graph inputs are not valid.
32043288

0 commit comments

Comments
 (0)