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

Add support for variant overrides in Render JSON #11

Merged
merged 2 commits into from
Oct 21, 2021

Conversation

franklinsch
Copy link
Contributor

@franklinsch franklinsch commented Oct 18, 2021

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

Summary

Adds infrastructure groundwork for adding language-specific overrides in the Render JSON model. This is in support of handling symbols that are available in multiple languages (like Swift+Objective-C symbols). More details here: https://forums.swift.org/t/extending-swift-docc-render-json-to-support-multi-language-symbols/52881

This PR also adds support for specifying language variants for RenderMetadata.title and TopicRenderReference.title as an example for the new infrastructure.

Example usage

As an example on how to make a property support language-specific variants, let's look at the change for
RenderMetadata.title.

We create a sibling titleVariants property that holds the default title (e.g., the Swift title) of the symbol, and
update title to be a computed property that fetches/updates the default value of titleVariants.

-     public var title: String?
+     public var title: String? {
+         get { getVariantDefaultValue(keyPath: \.titleVariants) }
+         set { setVariantDefaultValue(newValue, keyPath: \.titleVariants) }
+     }
+
+     /// The variants of the title.
+     public var titleVariants: VariantCollection<String>?

We update the encoder method of RenderMetadata to encode the titleVariants instead of title, and
VariantCollection<_>'s Codable implementation will encode the default value at title. It also accumulates the
variants and the JSON pointers they apply to to a dictionary, and that dictionary gets written to the variantsOverride
property of the render node.

Then, to specify a variant for Objective-C documentation:

node.metadata.titleVariants = VariantCollection<String>(
   defaultValue: symbol.title, 
   objectiveCValue: "The Objective-C title"
)

Implementation overview

At a high-level, properties in Render JSON models that can hold different values for different languages are now represented by a VariantCollection<_> value. When a VariantCollection<_> value is encoded, two things happen:

  1. Its defaultValue gets encoded into the encoder's container
  2. Its variants are accumulated into the encoder's userInfo[.variantOverrides] property.

The RenderNode's Encodable implementation then grabs the encoder's userInfo[.variantOverrides]—which, at this point in the encoding process, contains the variants for all the variant collection values in the render node tree—and encodes the variants in the top-level variantOverrides property. Clients can get a JSONEncoder that's configured to accumulate variants information by using the RenderJSONEncoder.makeEncoder() API.

As a side-note, we updated the existing infrastructure to optimize the encoding of references objects across render node compilations to no longer cache encoded render references in the JSONEncoder's userInfo, but instead in a cache passed as a parameter to RenderNode.encodeToJSON(with:renderReferenceCache:). This is because the new infrastructure relies on using separate JSONEncoder instances for each render node compilation.

Performance impact

TestFramework-10.json
+-----------------------------------------------------------------------------------------------------+
| Metric                                   | Change     | Before               | After                |
+-----------------------------------------------------------------------------------------------------+
| Compiled output size (MB)                | no change  | 114.66               | 114.66               |
| Duration for 'bundle-registration' (sec) | -0.84%     | 7.74                 | 7.67                 |
| Duration for 'convert-action' (sec)      | -0.71%     | 9.81                 | 9.74                 |
| Peak memory footprint (MB)               | -1.92%     | 362.85               | 355.88               |
| Topic Anchor Checksum                    | no change  | c8f03d4e81da8e3b6d7f | c8f03d4e81da8e3b6d7f |
| Topic Graph Checksum                     | no change  | edce22bce4f8de475a5e | edce22bce4f8de475a5e |
+-----------------------------------------------------------------------------------------------------+

TestFramework-25.json
+-----------------------------------------------------------------------------------------------------+
| Metric                                   | Change     | Before               | After                |
+-----------------------------------------------------------------------------------------------------+
| Compiled output size (MB)                | no change  | 287.87               | 287.87               |
| Duration for 'bundle-registration' (sec) | +1.02%     | 19.27                | 19.47                |
| Duration for 'convert-action' (sec)      | +0.54%     | 24.64                | 24.78                |
| Peak memory footprint (MB)               | -1.94%     | 842.66               | 826.34               |
| Topic Anchor Checksum                    | no change  | 9a675b9ad6d69f8b7f0c | 9a675b9ad6d69f8b7f0c |
| Topic Graph Checksum                     | no change  | 665713509084b5131a37 | 665713509084b5131a37 |
+-----------------------------------------------------------------------------------------------------+

TestFramework-5.json
+-----------------------------------------------------------------------------------------------------+
| Metric                                   | Change     | Before               | After                |
+-----------------------------------------------------------------------------------------------------+
| Compiled output size (MB)                | no change  | 57.36                | 57.36                |
| Duration for 'bundle-registration' (sec) | -1.76%     | 3.87                 | 3.80                 |
| Duration for 'convert-action' (sec)      | -2.01%     | 4.93                 | 4.83                 |
| Peak memory footprint (MB)               | -4.55%     | 208.72               | 199.23               |
| Topic Anchor Checksum                    | no change  | 65d4ff3050cd1106a21b | 65d4ff3050cd1106a21b |
| Topic Graph Checksum                     | no change  | 0a64c740a2ed5a246836 | 0a64c740a2ed5a246836 |
+-----------------------------------------------------------------------------------------------------+

TestFramework-50.json
+-----------------------------------------------------------------------------------------------------+
| Metric                                   | Change     | Before               | After                |
+-----------------------------------------------------------------------------------------------------+
| Compiled output size (MB)                | no change  | 578.80               | 578.80               |
| Duration for 'bundle-registration' (sec) | -1.18%     | 39.59                | 39.12                |
| Duration for 'convert-action' (sec)      | -0.56%     | 50.87                | 50.58                |
| Peak memory footprint (MB)               | +2.40%     | 1561.69              | 1599.12              |
| Topic Anchor Checksum                    | no change  | 08d0a84bec913460905f | 08d0a84bec913460905f |
| Topic Graph Checksum                     | no change  | 74d25c4f1ee185ad5676 | 74d25c4f1ee185ad5676 |
+-----------------------------------------------------------------------------------------------------+

Dependencies

None.

Testing

These changes are non-breaking, so there should be no user-facing changes (including in Render JSON).

To test the the variantsOverrides functionality:

  1. Add an Objective-C value for node.metadata.titleVariants for example:
node.metadata.titleVariants = VariantCollection<String>(
   defaultValue: symbol.title, 
   objectiveCValue: "The Objective-C title for \(symbol.title)"
)
  1. Run a conversion and inspect the Render JSON for the symbol kind you've made a change to.

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

Adds infrastructure support for adding language-specific overrides in Render
JSON. Also, adds support specifying language variants for
`RenderMetadata.title` and `TopicRenderReference.title`.

rdar://82919099
@franklinsch
Copy link
Contributor Author

@swift-ci test

@franklinsch
Copy link
Contributor Author

franklinsch commented Oct 18, 2021

@swift-ci test

@franklinsch
Copy link
Contributor Author

@swift-ci test macOS

@mportiz08
Copy link
Contributor

@franklinsch should the Render JSON spec be updated with details about the new variantOverrides field as part of this PR?

@franklinsch
Copy link
Contributor Author

Great point @mportiz08, I filed https://bugs.swift.org/browse/SR-15354 to track this.

@franklinsch
Copy link
Contributor Author

@swift-ci test macOS

@franklinsch
Copy link
Contributor Author

@swift-ci test macOS

@franklinsch franklinsch merged commit d6bfe19 into swiftlang:main Oct 21, 2021
@franklinsch franklinsch deleted the render-json-variant-overrides branch October 21, 2021 09:38
franklinsch added a commit to franklinsch/swift-docc that referenced this pull request Oct 29, 2021
Update the render JSON spec for the changes introduced in swiftlang#11.

SR-15354
rdar://82919099
franklinsch added a commit to franklinsch/swift-docc that referenced this pull request Oct 29, 2021
Update the render JSON spec for the changes introduced in swiftlang#11.

SR-15354
rdar://83667105
franklinsch added a commit that referenced this pull request Nov 1, 2021
Update the render JSON spec for the changes introduced in #11.

SR-15354
rdar://83667105
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