Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion Sources/SwiftDocC/Infrastructure/DocumentationContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1383,12 +1383,16 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {
referencesIndex.removeAll()
referencesIndex.reserveCapacity(knownIdentifiers.count)
for reference in knownIdentifiers {
referencesIndex[reference.absoluteString] = reference
registerReference(reference)
}

return (moduleReferences: Set(moduleReferences.values), urlHierarchy: symbolsURLHierarchy)
}
}

private func registerReference(_ resolvedReference: ResolvedTopicReference) {
referencesIndex[resolvedReference.absoluteString] = resolvedReference
}

private func shouldContinueRegistration() throws {
guard isRegistrationEnabled.sync({ $0 }) else {
Expand Down Expand Up @@ -2607,6 +2611,11 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate {

if case .success(let resolvedReference) = reference {
cacheReference(resolvedReference, withKey: ResolvedTopicReference.cacheIdentifier(unresolvedReference, fromSymbolLink: isCurrentlyResolvingSymbolLink, in: parent))

// Register the resolved reference in the context so that it can be looked up via its absolute
// path. We only do this for in-bundle content, and since we've just resolved an in-bundle link,
// we register the reference.
registerReference(resolvedReference)
return .success(resolvedReference)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,112 @@ class ConvertServiceTests: XCTestCase {
}
}

func testConvertTopLevelSymbolWithLinkResolving() throws {
let symbolGraphFile = Bundle.module.url(
forResource: "one-symbol-top-level",
withExtension: "symbols.json",
subdirectory: "Test Resources"
)!

let symbolGraph = try Data(contentsOf: symbolGraphFile)

let request = ConvertRequest(
bundleInfo: DocumentationBundle.Info(
displayName: "TestBundle",
identifier: "org.swift.example",
version: "1.0.0"
),
externalIDsToConvert: ["s:32MyKit3FooV"],
documentPathsToConvert: [],
symbolGraphs: [symbolGraph],
markupFiles: [],
miscResourceURLs: []
)

let server = DocumentationServer()

let mockLinkResolvingService = LinkResolvingService { message in
do {
let payload = try XCTUnwrap(message.payload)
let request = try JSONDecoder()
.decode(
ConvertRequestContextWrapper<OutOfProcessReferenceResolver.Request>.self,
from: payload
)

let errorResponse = DocumentationServer.Message(
type: "resolve-reference-response",
payload: try JSONEncoder().encode(
OutOfProcessReferenceResolver.Response
.errorMessage("Unable to resolve reference.")
)
)

switch request.payload {
case .topic(let url):
let resolvableBarURL = URL(
string: "doc://org.swift.example/documentation/MyKit/Foo/bar()"
)!

if url == resolvableBarURL {
let testSymbolInformationResponse = OutOfProcessReferenceResolver
.ResolvedInformation(
kind: .init(
name: "bar()",
id: "org.swift.docc.kind.method",
isSymbol: true
),
url: resolvableBarURL,
title: "bar()",
abstract: "",
language: .init(name: "Swift", id: "swift"),
availableLanguages: [],
platforms: [],
declarationFragments: nil
)

let payloadData = OutOfProcessReferenceResolver.Response
.resolvedInformation(testSymbolInformationResponse)

return DocumentationServer.Message(
type: "resolve-reference-response",
payload: try JSONEncoder().encode(payloadData)
)
} else {
return errorResponse
}
default:
return errorResponse
}
} catch {
XCTFail(error.localizedDescription)
return nil
}
}

server.register(service: mockLinkResolvingService)

try processAndAssert(request: request, linkResolvingServer: server) { message in
let renderNodes = try JSONDecoder().decode(
ConvertResponse.self,
from: XCTUnwrap(message.payload)
).renderNodes

XCTAssertEqual(renderNodes.count, 1)
let data = try XCTUnwrap(renderNodes.first)
let renderNode = try JSONDecoder().decode(RenderNode.self, from: data)

XCTAssertEqual(
Set(renderNode.references.keys),
[
"doc://org.swift.example/documentation/MyKit",
"doc://org.swift.example/documentation/MyKit/Foo",
"doc://org.swift.example/documentation/MyKit/Foo/bar()",
]
)
}
}

func testOrderOfLinkResolutionRequestsForDocLink() throws {
let symbolGraphFile = try XCTUnwrap(
Bundle.module.url(
Expand Down
213 changes: 213 additions & 0 deletions Tests/SwiftDocCTests/Test Resources/one-symbol-top-level.symbols.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
{
"metadata": {
"formatVersion": {
"major": 0,
"minor": 5,
"patch": 3
},
"generator": "Apple Swift version 5.7 (swiftlang-5.7.0.101.10 clang-1400.0.10.4.2)"
},
"module": {
"name": "MyKit",
"platform": {
"architecture": "x86_64",
"vendor": "apple",
"operatingSystem": {
"name": "macosx",
"minimumVersion": {
"major": 10,
"minor": 10,
"patch": 0
}
}
}
},
"symbols": [
{
"kind": {
"identifier": "swift.struct",
"displayName": "Structure"
},
"identifier": {
"precise": "s:32MyKit3FooV",
"interfaceLanguage": "swift"
},
"pathComponents": [
"Foo"
],
"names": {
"title": "Foo"
},
"docComment": {
"lines": [
{
"range": {
"start": {
"line": 0,
"character": 4
},
"end": {
"line": 0,
"character": 15
}
},
"text": "Foo"
},
{
"range": {
"start": {
"line": 1,
"character": 3
},
"end": {
"line": 1,
"character": 3
}
},
"text": ""
},
{
"range": {
"start": {
"line": 2,
"character": 4
},
"end": {
"line": 2,
"character": 39
}
},
"text": "All of these links should resolve:"
},
{
"range": {
"start": {
"line": 3,
"character": 3
},
"end": {
"line": 3,
"character": 3
}
},
"text": ""
},
{
"range": {
"start": {
"line": 4,
"character": 4
},
"end": {
"line": 4,
"character": 13
}
},
"text": "``bar()``"
},
{
"range": {
"start": {
"line": 5,
"character": 3
},
"end": {
"line": 5,
"character": 3
}
},
"text": ""
},
{
"range": {
"start": {
"line": 6,
"character": 4
},
"end": {
"line": 6,
"character": 17
}
},
"text": "``Foo/bar()``"
},
{
"range": {
"start": {
"line": 7,
"character": 3
},
"end": {
"line": 7,
"character": 3
}
},
"text": ""
},
{
"range": {
"start": {
"line": 8,
"character": 4
},
"end": {
"line": 8,
"character": 22
}
},
"text": "``Foo/otherBar()``"
},
{
"range": {
"start": {
"line": 9,
"character": 3
},
"end": {
"line": 9,
"character": 3
}
},
"text": ""
},
{
"range": {
"start": {
"line": 10,
"character": 4
},
"end": {
"line": 10,
"character": 50
}
},
"text": "``MyKit/Foo/bar()``"
}
]
},
"declarationFragments": [
{
"kind": "keyword",
"spelling": "struct"
},
{
"kind": "text",
"spelling": " "
},
{
"kind": "identifier",
"spelling": "Foo"
}
],
"accessLevel": "public",
"location": {
"uri": "file:///tmp/Downloads/MyKit/MyKit.swift",
"position": {
"line": 11,
"character": 14
}
}
}
],
"relationships": []
}