Skip to content

Commit 1b8e7ca

Browse files
committed
Add full (symbol) name to LinkDestinationSummary
The only use-case for storing the full declaration fragments in `LinkDestinationSummary` rather than the shortened declaration fragments intended for display, is to derive the full name of the symbol in diagnostics [1] [2]. We have a number of tests [3] which verify that the diagnostic emitted when a symbol is referenced locally is the same as when the symbol is referenced externally. However, we want to stop storing the full declaration fragments in favour of the shortened ones because: - the full fragments are never displayed when referenced externally, as they are too long - the full fragments take up additionally storage space, and encoding/decoding time, to only be used to derive the full name of the symbol This commit updates the logic such that, we pre-derive the full name of the symbol from its declaration fragments, and then store that as part of `LinkDestinationSummary`, so that in a subsequent commit we can stop storing the full declaration fragments and store only the shortened ones instead. The diagnostic logic has also been updated to use the new field rather than the full declaration fragments. [1]: https://github.com/swiftlang/swift-docc/blob/1b4a1850dd2785a8ebabded139ae0af3551bb029/Sources/SwiftDocC/Infrastructure/Link%20Resolution/ExternalPathHierarchyResolver.swift#L61-L63 [2]: https://github.com/swiftlang/swift-docc/blob/1b4a1850dd2785a8ebabded139ae0af3551bb029/Sources/SwiftDocC/Infrastructure/Link%20Resolution/PathHierarchy%2BError.swift#L115-L117 [3]: https://github.com/swiftlang/swift-docc/blob/9413c599817abc9dd4f8feeed57a998b19a05a6f/Tests/SwiftDocCTests/Infrastructure/ExternalPathHierarchyResolverTests.swift#L907-L918
1 parent d720379 commit 1b8e7ca

File tree

4 files changed

+57
-16
lines changed

4 files changed

+57
-16
lines changed

Sources/SwiftDocC/Infrastructure/Link Resolution/ExternalPathHierarchyResolver.swift

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,13 @@ final class ExternalPathHierarchyResolver {
5858
return collidingNode.name
5959
}
6060
if let symbolID = collidingNode.symbol?.identifier {
61-
if symbolID.interfaceLanguage == summary.language.id, let fragments = summary.declarationFragments {
62-
return fragments.plainTextDeclaration()
61+
if symbolID.interfaceLanguage == summary.language.id, let fullName = summary.fullName {
62+
return fullName
6363
}
6464
if let variant = summary.variants.first(where: { $0.traits.contains(.interfaceLanguage(symbolID.interfaceLanguage)) }),
65-
let fragments = variant.declarationFragments ?? summary.declarationFragments
65+
let fullName = variant.fullName ?? summary.fullName
6666
{
67-
return fragments.plainTextDeclaration()
67+
return fullName
6868
}
6969
}
7070
return summary.title
@@ -153,12 +153,6 @@ final class ExternalPathHierarchyResolver {
153153
}
154154
}
155155

156-
private extension Sequence<DeclarationRenderSection.Token> {
157-
func plainTextDeclaration() -> String {
158-
return self.map(\.text).joined().split(whereSeparator: { $0.isWhitespace || $0.isNewline }).joined(separator: " ")
159-
}
160-
}
161-
162156
// MARK: ExternalEntity
163157

164158
extension LinkDestinationSummary {

Sources/SwiftDocC/LinkTargets/LinkDestinationSummary.swift

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ public struct LinkDestinationSummary: Codable, Equatable {
135135
/// The unique, precise identifier for this symbol that you use to reference it across different systems, or `nil` if the summarized element isn't a symbol.
136136
public let usr: String?
137137

138+
/// The full name of this symbol, derived from its full declaration fragments, or `nil` if the summarized element isn't a symbol.
139+
public let fullName: String?
140+
138141
/// The rendered fragments of a symbol's declaration.
139142
public typealias DeclarationFragments = [DeclarationRenderSection.Token]
140143
/// The fragments for this symbol's declaration, or `nil` if the summarized element isn't a symbol.
@@ -193,6 +196,11 @@ public struct LinkDestinationSummary: Codable, Equatable {
193196
/// If the summarized element has a precise symbol identifier but the variant doesn't, this property will be `Optional.some(nil)`.
194197
public let usr: VariantValue<String?>
195198

199+
/// The full name of this symbol, derived from its full declaration fragments, or `nil` if the precise symbol identifier is the same as the summarized element.
200+
///
201+
/// If the summarized element has a full name but the variant doesn't, this property will be `Optional.some(nil)`.
202+
public let fullName: VariantValue<String?>
203+
196204
/// The declaration of the variant or `nil` if the declaration is the same as the summarized element.
197205
///
198206
/// If the summarized element has a declaration but the variant doesn't, this property will be `Optional.some(nil)`.
@@ -215,6 +223,7 @@ public struct LinkDestinationSummary: Codable, Equatable {
215223
/// - abstract: The abstract of the variant or `nil` if the abstract is the same as the summarized element.
216224
/// - taskGroups: The taskGroups of the variant or `nil` if the taskGroups is the same as the summarized element.
217225
/// - usr: The precise symbol identifier of the variant or `nil` if the precise symbol identifier is the same as the summarized element.
226+
/// - fullName: The full name of this symbol, derived from its full declaration fragments, or `nil` if the precise symbol identifier is the same as the summarized element.
218227
/// - declarationFragments: The declaration of the variant or `nil` if the declaration is the same as the summarized element.
219228
public init(
220229
traits: [RenderNode.Variant.Trait],
@@ -225,6 +234,7 @@ public struct LinkDestinationSummary: Codable, Equatable {
225234
abstract: VariantValue<LinkDestinationSummary.Abstract?> = nil,
226235
taskGroups: VariantValue<[LinkDestinationSummary.TaskGroup]?> = nil,
227236
usr: VariantValue<String?> = nil,
237+
fullName: VariantValue<String?> = nil,
228238
declarationFragments: VariantValue<LinkDestinationSummary.DeclarationFragments?> = nil
229239
) {
230240
self.traits = traits
@@ -235,10 +245,11 @@ public struct LinkDestinationSummary: Codable, Equatable {
235245
self.abstract = abstract
236246
self.taskGroups = taskGroups
237247
self.usr = usr
248+
self.fullName = fullName
238249
self.declarationFragments = declarationFragments
239250
}
240251

241-
@available(*, deprecated, renamed: "init(traits:kind:language:relativePresentationURL:title:abstract:taskGroups:usr:declarationFragments:)", message: "Use `init(traits:kind:language:relativePresentationURL:title:abstract:taskGroups:usr:declarationFragments:)` instead. `TopicRenderReference` doesn't support variant specific topic images. This property will be removed after 6.3 is released")
252+
@available(*, deprecated, renamed: "init(traits:kind:language:relativePresentationURL:title:abstract:taskGroups:usr:fullName:declarationFragments:)", message: "Use `init(traits:kind:language:relativePresentationURL:title:abstract:taskGroups:usr:fullName:declarationFragments:)` instead. `TopicRenderReference` doesn't support variant specific topic images. This property will be removed after 6.3 is released")
242253
public init(
243254
traits: [RenderNode.Variant.Trait],
244255
kind: VariantValue<DocumentationNode.Kind> = nil,
@@ -248,6 +259,7 @@ public struct LinkDestinationSummary: Codable, Equatable {
248259
abstract: VariantValue<LinkDestinationSummary.Abstract?> = nil,
249260
taskGroups: VariantValue<[LinkDestinationSummary.TaskGroup]?> = nil,
250261
usr: VariantValue<String?> = nil,
262+
fullName: VariantValue<String?> = nil,
251263
declarationFragments: VariantValue<LinkDestinationSummary.DeclarationFragments?> = nil,
252264
topicImages: VariantValue<[TopicImage]?> = nil
253265
) {
@@ -260,6 +272,7 @@ public struct LinkDestinationSummary: Codable, Equatable {
260272
abstract: abstract,
261273
taskGroups: taskGroups,
262274
usr: usr,
275+
fullName: fullName,
263276
declarationFragments: declarationFragments
264277
)
265278
}
@@ -281,6 +294,7 @@ public struct LinkDestinationSummary: Codable, Equatable {
281294
/// - platforms: Information about the platforms for which the summarized element is available.
282295
/// - taskGroups: The reference URLs of the summarized element's children, grouped by their task groups.
283296
/// - usr: The unique, precise identifier for this symbol that you use to reference it across different systems, or `nil` if the summarized element isn't a symbol.
297+
/// - fullName: The full name of this symbol, derived from its full declaration fragments, or `nil` if the summarized element isn't a symbol.
284298
/// - declarationFragments: The fragments for this symbol's declaration, or `nil` if the summarized element isn't a symbol.
285299
/// - redirects: Any previous URLs for this element, or `nil` if this element has no previous URLs.
286300
/// - topicImages: Images that are used to represent the summarized element, or `nil` if this element has no topic images.
@@ -296,6 +310,7 @@ public struct LinkDestinationSummary: Codable, Equatable {
296310
platforms: [LinkDestinationSummary.PlatformAvailability]? = nil,
297311
taskGroups: [LinkDestinationSummary.TaskGroup]? = nil,
298312
usr: String? = nil,
313+
fullName: String? = nil,
299314
declarationFragments: LinkDestinationSummary.DeclarationFragments? = nil,
300315
redirects: [URL]? = nil,
301316
topicImages: [TopicImage]? = nil,
@@ -312,6 +327,7 @@ public struct LinkDestinationSummary: Codable, Equatable {
312327
self.platforms = platforms
313328
self.taskGroups = taskGroups
314329
self.usr = usr
330+
self.fullName = fullName
315331
self.declarationFragments = declarationFragments
316332
self.redirects = redirects
317333
self.topicImages = topicImages
@@ -466,6 +482,7 @@ extension LinkDestinationSummary {
466482

467483
let abstract = renderSymbolAbstract(symbol.abstractVariants[summaryTrait] ?? symbol.abstract)
468484
let usr = symbol.externalIDVariants[summaryTrait] ?? symbol.externalID
485+
let fullName = symbol.fullName(for: summaryTrait)
469486
let declaration = (symbol.declarationVariants[summaryTrait] ?? symbol.declaration).renderDeclarationTokens()
470487
let language = documentationNode.sourceLanguage
471488

@@ -483,6 +500,7 @@ extension LinkDestinationSummary {
483500
return main == variant ? nil : variant
484501
}
485502

503+
let fullNameVariant = symbol.fullName(for: trait)
486504
let variantTraits = [RenderNode.Variant.Trait.interfaceLanguage(interfaceLanguage)]
487505
return Variant(
488506
traits: variantTraits,
@@ -493,6 +511,7 @@ extension LinkDestinationSummary {
493511
abstract: nilIfEqual(main: abstract, variant: abstractVariant),
494512
taskGroups: nilIfEqual(main: taskGroups, variant: taskGroupVariants[variantTraits]),
495513
usr: nil, // The symbol variant uses the same USR
514+
fullName: nilIfEqual(main: fullName, variant: fullNameVariant),
496515
declarationFragments: nilIfEqual(main: declaration, variant: declarationVariant)
497516
)
498517
}
@@ -512,6 +531,7 @@ extension LinkDestinationSummary {
512531
platforms: platforms,
513532
taskGroups: taskGroups,
514533
usr: usr,
534+
fullName: fullName,
515535
declarationFragments: declaration,
516536
redirects: redirects,
517537
topicImages: topicImages.nilIfEmpty,
@@ -594,7 +614,7 @@ extension LinkDestinationSummary {
594614
// Add Codable methods—which include an initializer—in an extension so that it doesn't override the member-wise initializer.
595615
extension LinkDestinationSummary {
596616
enum CodingKeys: String, CodingKey {
597-
case kind, referenceURL, title, abstract, language, taskGroups, usr, availableLanguages, platforms, redirects, topicImages, references, variants
617+
case kind, referenceURL, title, abstract, language, taskGroups, usr, availableLanguages, platforms, redirects, topicImages, references, variants, fullName
598618
case relativePresentationURL = "path"
599619
case declarationFragments = "fragments"
600620
}
@@ -626,6 +646,7 @@ extension LinkDestinationSummary {
626646
try container.encodeIfPresent(platforms, forKey: .platforms)
627647
try container.encodeIfPresent(taskGroups, forKey: .taskGroups)
628648
try container.encodeIfPresent(usr, forKey: .usr)
649+
try container.encodeIfPresent(fullName, forKey: .fullName)
629650
try container.encodeIfPresent(declarationFragments, forKey: .declarationFragments)
630651
try container.encodeIfPresent(redirects, forKey: .redirects)
631652
try container.encodeIfPresent(topicImages, forKey: .topicImages)
@@ -682,6 +703,7 @@ extension LinkDestinationSummary {
682703
platforms = try container.decodeIfPresent([AvailabilityRenderItem].self, forKey: .platforms)
683704
taskGroups = try container.decodeIfPresent([TaskGroup].self, forKey: .taskGroups)
684705
usr = try container.decodeIfPresent(String.self, forKey: .usr)
706+
fullName = try container.decodeIfPresent(String.self, forKey: .fullName)
685707
declarationFragments = try container.decodeIfPresent(DeclarationFragments.self, forKey: .declarationFragments)
686708
redirects = try container.decodeIfPresent([URL].self, forKey: .redirects)
687709
topicImages = try container.decodeIfPresent([TopicImage].self, forKey: .topicImages)
@@ -695,7 +717,7 @@ extension LinkDestinationSummary {
695717

696718
extension LinkDestinationSummary.Variant {
697719
enum CodingKeys: String, CodingKey {
698-
case traits, kind, title, abstract, language, usr, taskGroups
720+
case traits, kind, title, abstract, language, usr, taskGroups, fullName
699721
case relativePresentationURL = "path"
700722
case declarationFragments = "fragments"
701723
}
@@ -721,6 +743,7 @@ extension LinkDestinationSummary.Variant {
721743
}
722744
}
723745
try container.encodeIfPresent(usr, forKey: .usr)
746+
try container.encodeIfPresent(fullName, forKey: .fullName)
724747
try container.encodeIfPresent(declarationFragments, forKey: .declarationFragments)
725748
try container.encodeIfPresent(taskGroups, forKey: .taskGroups)
726749
}
@@ -762,6 +785,7 @@ extension LinkDestinationSummary.Variant {
762785
title = try container.decodeIfPresent(String.self, forKey: .title)
763786
abstract = try container.decodeIfPresent(LinkDestinationSummary.Abstract?.self, forKey: .abstract)
764787
usr = try container.decodeIfPresent(String?.self, forKey: .usr)
788+
fullName = try container.decodeIfPresent(String?.self, forKey: .fullName)
765789
declarationFragments = try container.decodeIfPresent(LinkDestinationSummary.DeclarationFragments?.self, forKey: .declarationFragments)
766790
taskGroups = try container.decodeIfPresent([LinkDestinationSummary.TaskGroup]?.self, forKey: .taskGroups)
767791
}
@@ -871,3 +895,16 @@ private extension Collection {
871895
isEmpty ? nil : self
872896
}
873897
}
898+
899+
private extension Sequence<DeclarationRenderSection.Token> {
900+
func plainTextDeclaration() -> String {
901+
return self.map(\.text).joined().split(whereSeparator: { $0.isWhitespace || $0.isNewline }).joined(separator: " ")
902+
}
903+
}
904+
905+
private extension Symbol {
906+
func fullName(for trait: DocumentationDataVariantsTrait) -> String? {
907+
let fullDeclaration = (self.declarationVariants[trait] ?? self.declaration).renderDeclarationTokens()
908+
return fullDeclaration?.plainTextDeclaration()
909+
}
910+
}

0 commit comments

Comments
 (0)