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
Create LinkDestinationSummary elements with multi-language variant content for symbols #60
Create LinkDestinationSummary elements with multi-language variant content for symbols #60
Conversation
…ntent for symbols rdar://86298116
@swift-ci please test |
@swift-ci please test |
1 similar comment
@swift-ci please test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Just left a few questions.
// Precompute the summarized elements information so that variants can compare their information against it and remove redundant duplicate information. | ||
|
||
// Multi-language symbols need to access the default content via the variant accessors (rdar://86580516) | ||
let kind = DocumentationNode.kind(forKind: (symbol.kindVariants[summaryTrait] ?? symbol.kindVariants[.fallback] ?? symbol.kind).identifier) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these chained ??
checks might be redundant.
The DocumentationDataVariants
subscript looks like this:
public subscript(trait: DocumentationDataVariantsTrait) -> Variant? {
get { values[trait] ?? defaultVariantValue }
set {
if trait == .fallback {
defaultVariantValue = newValue
} else {
values[trait] = newValue
}
}
}
So the .fallback
value is the defaultVariantValue
and we always fallback to the defaultVariantValue
if the given trait doesn't exist. So that should handle the ?? symbol.kindVariants[.fallback]
part inherently.
And the base symbol.kind
value is already a wrapper around the kindVariants
so I don't think we should be explicitly falling back to it.
We could do an explicit force unwrap of kindVariants.first!
which I think is what symbol.kind
is doing.
public var kind: SymbolGraph.Symbol.Kind { kindVariants.firstValue! }
In general I think we should probably try to avoid using the non-variant types on Symbol
since we should deprecate them soon and they're a little confusing.
Does that make sense or have I missed a case here?
let kind = DocumentationNode.kind(forKind: (symbol.kindVariants[summaryTrait] ?? symbol.kindVariants[.fallback] ?? symbol.kind).identifier) | |
let kind = DocumentationNode.kind(forKind: (symbol.kindVariants[summaryTrait] ?? symbol.kindVariants.first!).identifier) |
I don't love how we're having to force unwrap kindVariants.first
here, it seems like defaultVariantValue
should automatically fall back to the first variant and be non-optional if we want to guarantee that a variant collection always has a single value. Maybe @franklinsch wants to chime in here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I think this comment applies to several places in this function but I think we can isolate the discussion here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think force-unwrapping first
is correct. This value is never expected to be nil
in this case, because the kind
property always had a value before (non-optional)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the behavior is the same, I would prefer to call symbol.kind
(and symbol.title
, etc.) so that this code behaves consistently with how those properties are computed (in case that ever changes). That also helps avoid mistakes with force-unwrapping first
when the symbol convenience property is optional.
|
||
let abstractVariant: Abstract?? = symbol.abstractVariants[trait].map { renderSymbolAbstract($0) } | ||
|
||
func nilIfSame<Value: Equatable>(main: Value, variant: Value?) -> Value? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
func nilIfSame<Value: Equatable>(main: Value, variant: Value?) -> Value? { | |
func nilIfEqual<Value: Equatable>(main: Value, variant: Value?) -> Value? { |
XCTAssertEqual(summary.availableLanguages.sorted(by: \.id), [.objectiveC, .swift]) | ||
XCTAssertEqual(summary.platforms, renderNode.metadata.platforms) | ||
XCTAssertEqual(summary.usr, "c:objc(cs)Bar") | ||
// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stray open comment delimiter here
@@ -34,3 +34,24 @@ public enum VariantPatchOperation<Value: Codable> { | |||
} | |||
} | |||
} | |||
|
|||
extension VariantCollection.Variant where Value: RangeReplaceableCollection { | |||
/// Applies the variant's patch operations o a given value and returns the patched value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Applies the variant's patch operations o a given value and returns the patched value | |
/// Applies the variant's patch operations to a given value and returns the patched value. |
} | ||
return [LinkDestinationSummary(documentationNode: self, path: presentationURL.path, taskGroups: taskGroups, platforms: platforms, compiler: &compiler)] + landmarkSummaries | ||
return [LinkDestinationSummary(documentationNode: self, path: presentationURL.path, taskGroups: taskGroups, variantTaskGroups: variantTaskGroups, platforms: platforms, compiler: &compiler)] + landmarkSummaries |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: variantTaskGroups
-> taskGroupVariants
to align with the other variant APIs.
let taskGroups: [LinkDestinationSummary.TaskGroup] | ||
switch kind { | ||
case .tutorial, .tutorialArticle, .technology, .technologyOverview, .chapter, .volume, .onPageLandmark: | ||
taskGroups = [.init(title: nil, identifiers: context.children(of: reference).map { $0.reference.absoluteString })] | ||
default: | ||
taskGroups = renderNode.topicSections.map { group in .init(title: group.title, identifiers: group.identifiers) } | ||
for variant in renderNode.topicSectionsVariants.variants { | ||
variantTaskGroups[variant.traits] = variant.applyingPatchTo(renderNode.topicSections).map { group in .init(title: group.title, identifiers: group.identifiers) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of implementing applyingPatchTo
, which partly overlaps with JSONPatchApplier
's functionality, we can instead use the RenderNodeVariantOverridesApplier
API that applies the patch onto the entire render node. However, this will require first encoding the render node to JSON, which is probably undesirable for performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think that will have a performance impact. When linkable entities are emits, this code runs for every page and landmark that have topic section variants. In the worst case this could end up encoding all the pages.
// Precompute the summarized elements information so that variants can compare their information against it and remove redundant duplicate information. | ||
|
||
// Multi-language symbols need to access the default content via the variant accessors (rdar://86580516) | ||
let kind = DocumentationNode.kind(forKind: (symbol.kindVariants[summaryTrait] ?? symbol.kindVariants[.fallback] ?? symbol.kind).identifier) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think force-unwrapping first
is correct. This value is never expected to be nil
in this case, because the kind
property always had a value before (non-optional)
- Remove redundant retrieval of `.fallback` trait values - Rename inline helper function to `nilIfEqual` - Rename internal argument to `taskGroupVariants` for consistency - Fix typo in documentation comment
@swift-ci please test |
@swift-ci please test |
@swift-ci please test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks David!
@swift-ci please test |
Bug/issue #, if applicable: SR-15574 rdar://86298116
Summary
This change creates
LinkDestinationSummary
elements with multi-language variant content for symbols. Before this change only the main summary element was created without its variant content.Dependencies
n/a
Testing
Convert a multi-language documentation catalog and include the
--emit-digest
flag so that Swift-DocC will create the linkable-entities.json file.(For testing purposes it may be convenient to also set the
DOCC_JSON_PRETTYPRINT
environment toYES
to get output that's more easily inspectable.)The content of the linkable-entities.json file should include the variant content of each interface language for each symbol "entity". Each variant should contain only the information that's different in the variant compared to the summarized element.
Checklist
Make sure you check off the following items. If they cannot be completed, provide a reason.
./bin/test
script and it succeeded