Xcode 14.2 docc disambiguation completion not working

I am attempting to convert some framework documentation to DocC. From the tutorial, it looks like this should be the solution, but it's not working:

I made a very simply framework with the following type:

public struct Foo {
    public init(bar name: String) { }
    
    public init(foo name: String) { }
    public init(foo val: Int) { }
}

I have a corresponding DocC landing page:

# ``Test``

A test framework.

## Overview

Overview of the test framework.

## Topics

### Essentials

- ``Foo``
- ``Foo/init(bar:)``

The landing page shows up when I build documentation. So far so good. But when I try to add either of the other two init(foo:) initializers...

image

Looks like it's going to work! But, no...

image

The disambiguation suffix does not appear. Trying again by hitting escape...

image

Again, looks like it should work, but no suffix is added. Of course building the documentation at this point gives me a Topic reference 'Foo/init(foo:)' couldn't be resolved. No local documentation matches this reference. Which is pretty confusing because the error is resulting not from "no matches", but from multiple disambiguated matches.

Is this an Xcode bug? If so, is there a workaround?

I did discover a workaround, which is to build the documentation, then use the documentation browser to export a .doccarchive bundle, then go spelunking in the bundle:

Adding these suffixes to my markdown works:

image

Would still like to know whether anyone else can corroborate my Xcode issue.

1 Like

Yes, it looks like a bug that Xcode doesn't insert the necessary disambiguation when providing link completion.

IIRC bugs in Xcode are considered "off topic" for this forum but if you report a feedback (at https://feedbackassistant.apple.com) and post the feedback number in this thread I can make sure that it reaches the right people.

I'm not aware of a good workaround. The best I could think of would only improve the error message—making it easier to find the missing disambiguations—but Xcode still wouldn't add the necessary disambiguation when providing link completion and it would require a newer toolchain than what's included in Xcode 14.2.


We have been working on a new experimental link resolution implementation in Swift-DocC but that code is only available in the Swift 5.8 toolchain and later (the Development toolchain). With one of those toolchains (from Swift.org - Download Swift) you could opt-in to the new link resolver implementation by setting this user default:

defaults write -g DocCUseHierarchyBasedLinkResolver -boolean true

With that change the error message from building documentation would include information about the missing disambiguation:

Reference is ambiguous after '/ModuleName/Foo':
Append '-2tneo' to refer to 'init(foo: String)'.
Append '-8pp2j' to refer to 'init(foo: Int)'.

(Disambiguation hashes depend on the module name so the hashes in my local test (above) doesn't match the hashes from your original post)

5 Likes

I can say I run into the same issue just now and happily found your workaround here, will try it out now.

1 Like

I haven't had the chance to try out @ronnqvist new capabilities - but as a temporary workaround, I found half the battle was determining what the possible identifiers were. Fortunately, this can be relatively easily extracted, and I keep a script handy to do just that.

I include --emit-digest in the building of an archive (or set of HTML pages), and then dig around in the file linkable-entities.json within the archive.

cat docs/linkable-entities.json | jq '.[].referenceURL' -r

Dumps out all the identifiers that are possible - as well as links and pages that you could be referenced, that looks something like:

doc://com.github.heckj.CRDT/documentation/CRDT/List/values
doc://com.github.heckj.CRDT/documentation/CRDT/DeltaCRDT/mergingDelta(_:)
doc://com.github.heckj.CRDT/documentation/CRDT/GSet/init(actorId:clock:_:)

I then use a series of regular expressions to pull out what amounts to the identifiers from that set to generate a list of all available symbols:

For the set above, that transforms into something akin to:

- ``CRDT/List/values``
- ``CRDT/DeltaCRDT/mergingDelta(_:)``
- ``CRDT/GSet/init(actorId:clock:_:)``

This identifiers include the disambiguation hashes (even if my example doesn't show that immediately), which at least gives you a range of options to try.

For my part, I generate this giant list of symbols and dump them all together in a sorted list to make it a bit easier to start to sort and organize (curate in DocC speak) the symbols within documentation pages.

1 Like