Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use only canonical paths for symbol breadcrumbs #1081

Merged

Conversation

d-ronnqvist
Copy link
Contributor

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

Summary

This changes how DocC computes "breadcrumbs" for symbols to only use the canonical path and to use different paths for each language representation.
Before these changes, DocC would use the same "breadcrumbs" for each language representation, always based on the shortest path to the symbol, including curation. This meant, among other things, that:

  • C API with Swift refinements wouldn't reflect the symbol hierarchy on the Swift version of the page (because the path to the C top-level function was always shorter)
  • members that were organized outside of the canonical container location would no longer include a link to the container symbol on their page.

With these changes, symbol breadcrumbs ignore authored curation and only consider the canonical path for each language representation. For example:

Screenshot 2024-11-01 at 11 25 33

Articles and tutorial content continue to base their breadcrumbs on authored curation.

Dependencies

None.

Testing

  • Build and preview documentation for the "GeometricalShapes" test catalog

    swift run docc preview Tests/SwiftDocCTests/Test\ Bundles/GeometricalShapes.docc 
    
  • Click through the different pages and inspect the breadcrumbs for both language representations.

    • Note that center and radius are members in each language representation but that intersects(_:), isEmpty, etc. are top-level functions in C/Objective-C.
    • Note that init(center:radius:) only exist in Swift and that TLACircleMake only exist in C/Objective-C.
Screenshot 2024-11-01 at 11 39 49

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

Copy link
Contributor

@patshaughnessy patshaughnessy left a comment

Choose a reason for hiding this comment

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

Nice improvement! Just silly question about a few details.

/// - reference: The symbol reference to find the canonical path to.
/// - sourceLanguage: The source language representation of the symbol to fin the canonical path for.
/// - Returns: The canonical path to the given symbol reference, or `nil` if the reference isn't a symbol or if the symbol doesn't have a representation in the given source language.
func breadcrumbs(of reference: ResolvedTopicReference, in sourceLanguage: SourceLanguage) -> [ResolvedTopicReference]? {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe use a singular name for this since it only returns a single breadcrumb, not a list of breadcrumbs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I consider a path to be a list of breadcrumbs and a single breadcrumb to only be one path component.

I see that I used singular "breadcrumb" in the documentation comment. I'll update that documentation to say "breadcrumbs"

Copy link
Contributor Author

@d-ronnqvist d-ronnqvist Nov 8, 2024

Choose a reason for hiding this comment

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

I changed to plural "breadcrumbs" in the documentation comment in cc1e626

// To match the caller's expectations we remove the starting point and then flip the paths.
.dropFirst().reversed()
.compactMap {
$0.identifier.flatMap { resolvedReferenceMap[$0] }
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we assert on any nils? Or just remove them as you have done here? My guess is the PathHierarchy code is already well tested and has any asserts we would want.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, but I can add a comment that mentions why nil could be expected here.

The way that the ConvertService builds documentation for a single symbol may result in nodes in the hierarchy which doesn't correspond to any real symbols. The PathHierarchy internally refers to these as "sparse nodes". They only exist to construct a tree structure but links to them can't resolve. The ConvertService doesn't create any breadcrumbs, so handling nil here is possibly unnecessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a code comment in 8647adf

}

/// Returns the hierarchy under a given article.
/// - Parameter symbolReference: The reference to the article.
/// - Returns: The framework hierarchy that describes all paths where the article is curated.
mutating func visitArticle(_ symbolReference: ResolvedTopicReference) -> RenderHierarchy {
return visitSymbol(symbolReference)
mutating func visitArticle(_ symbolReference: ResolvedTopicReference) -> VariantCollection<RenderHierarchy?> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this function's parameter called symbolReference and not articleReference ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't change it but I suspect that it was an old copy-and-paste mistake. I can fix it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed in e63244e

],
expectedObjectiveCPaths: [
"doc://GeometricalShapes/documentation/GeometricalShapes",
"doc://GeometricalShapes/documentation/GeometricalShapes/Circle", // named TLACircle in Objective-C
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is the Objective-C breadcrumb the same as the Swift breadcrumb here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because the center property is a member of the TLACircle structure (see the comment above the assertion)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since the symbol exist for both Swift and Objective-C it only has a single reference (which uses the Swift path)

@d-ronnqvist
Copy link
Contributor Author

@swift-ci please test

@d-ronnqvist
Copy link
Contributor Author

@swift-ci please test

@d-ronnqvist d-ronnqvist merged commit 93a39a6 into swiftlang:main Nov 8, 2024
2 checks passed
@d-ronnqvist d-ronnqvist deleted the use-canonical-symbol-breadcrumbs branch November 8, 2024 14:49
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.

3 participants