Skip to content

Conversation

@anferbui
Copy link
Contributor

@anferbui anferbui commented Oct 30, 2025

Bug/issue #, if applicable: rdar://163018922

Summary

The navigation indexing code skips all further nodes after it has already indexed a node with a given identifier 1.

This can result in an odd interaction when there is an external link which is resolved to a path that the bundle serves itself (or more colloquially, a catalog has an external link to itself).

Since external entities are indexed before local entities, they were always be preferred over local entities, resulting in local entities mistakenly being dropped from the navigator altogether. The resulting navigator is incorrect and missing nodes, due to external entities not having hierarchy information. This issue was introduced when support for external links in the navigator was introduced.

This PR updates ConvertActionConverter to always index local entities first. If any external entities clash with local entities, they will be resolved as the local entity (including its hierarchy) in the navigator.

Dependencies

N/A

Testing

  • TODO: Fill out this section.

Checklist

Make sure you check off the following items. If they cannot be completed, provide a reason.

  • Added tests
  • Ran the ./bin/test script and it succeeded
  • [ ] Updated documentation if necessary N/A

@anferbui
Copy link
Contributor Author

Open question: Do we need any further logging / assertions / checking logic when we skip a node when building the navigator?

guard identifierToNode[normalizedIdentifier] == nil else {
return nil // skip as item exists already.
}

])
}

func testConflictingLocalAndExternalLinksInNavigatorIndex() async throws {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this shouldn't be possible (but I suspect that it's happening because of this code which misrepresents external nodes as local) and rather than enable it we should prevent it more explicitly with a user-facing diagnostic that informs the developer of the issue with a suggestion to replace the link with its local counterpart (which should be knowable if we have the local node as well)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were you thinking this checking would be done at the point of link resolution, or when building the navigator index?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm correct that its this code that causes this issue then I'd prefer that we check for this issue as close to that code as possible.

The navigation indexing code skips all further nodes after it has already indexed a node with a given identifier [1].

This can result in an odd interaction when there is an external link which is resolved to a path that the bundle serves itself (or more colloquially, a catalog has an external link to itself).

Since external entities are indexed before local entities, they were always be preferred over local entities, resulting in local entities mistakenly being dropped from the navigator altogether.
The resulting navigator is incorrect and missing nodes, due to external entities not having hierarchy information.
This issue was introduced when support for external links in the navigator was introduced.

This commit updates `ConvertActionConverter` to always index local entities first.
If any external entities clash with local entities, they will be resolved as the local entity (including its hierarchy) in the navigator.

Fixes rdar://163018922.

[1]: https://github.com/swiftlang/swift-docc/blob/b27288dd99b0e2715ed1a2d5720cd0f23118c030/Sources/SwiftDocC/Indexing/Navigator/NavigatorIndex.swift#L711-L713
[2]: swiftlang@65aaf92
@anferbui anferbui force-pushed the prefer-local-links-over-external-in-navigator branch from 46c0e3d to ee44242 Compare November 6, 2025 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants