Skip to content

Commit 7c04206

Browse files
committed
enable snippets and code block references everywhere, not just in standalone documentation
1 parent f267598 commit 7c04206

File tree

2 files changed

+126
-94
lines changed

2 files changed

+126
-94
lines changed

Sources/SymbolGraphLinker/SSGC.Linker.Tables.swift

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import CodelinkResolution
22
import DoclinkResolution
3+
import MarkdownSemantics
34
import SourceDiagnostics
45

56
extension SSGC.Linker
@@ -26,6 +27,69 @@ extension SSGC.Linker
2627
}
2728
}
2829
extension SSGC.Linker.Tables
30+
{
31+
mutating
32+
func inline(resources:[String: SSGC.Resource],
33+
into sections:Markdown.SemanticSections,
34+
with parser:Markdown.SwiftLanguage?) throws
35+
{
36+
var last:[String?: SSGC.ResourceText] = [:]
37+
try sections.traverse
38+
{
39+
guard
40+
case let block as Markdown.BlockCodeReference = $0
41+
else
42+
{
43+
return
44+
}
45+
46+
guard
47+
let file:String = block.file
48+
else
49+
{
50+
self.diagnostics[block.source] = SSGC.ResourceError.fileRequired(
51+
argument: "file")
52+
return
53+
}
54+
guard
55+
let file:SSGC.Resource = resources[file]
56+
else
57+
{
58+
self.diagnostics[block.source] = SSGC.ResourceError.fileNotFound(file)
59+
return
60+
}
61+
62+
let code:SSGC.ResourceText = try file.text()
63+
defer
64+
{
65+
last[block.title] = code
66+
}
67+
68+
let base:SSGC.ResourceText?
69+
switch block.base
70+
{
71+
case .file(let file)?:
72+
if let file:SSGC.Resource = resources[file]
73+
{
74+
base = try file.text()
75+
break
76+
}
77+
78+
self.diagnostics[block.source] = SSGC.ResourceError.fileNotFound(file)
79+
base = nil
80+
81+
case .auto?:
82+
base = last[block.title]
83+
84+
case nil:
85+
base = nil
86+
}
87+
88+
block.inline(code: code, base: base, with: parser)
89+
}
90+
}
91+
}
92+
extension SSGC.Linker.Tables
2993
{
3094
@_spi(testable) public mutating
3195
func resolving<Success>(with scopes:SSGC.OutlineResolutionScopes,

Sources/SymbolGraphLinker/SSGC.Linker.swift

Lines changed: 62 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -539,9 +539,13 @@ extension SSGC.Linker
539539

540540
extension SSGC.Linker
541541
{
542+
/// Links declarations that have already been assigned addresses.
543+
///
544+
/// This throws an error if and only if a file system error occurs. This is fatal because
545+
/// there is already logic in the linker to handle the case where files are missing.
542546
public mutating
543547
func link(namespaces sources:[[SSGC.Namespace]],
544-
at destinations:[[SymbolGraph.Namespace]])
548+
at destinations:[[SymbolGraph.Namespace]]) throws
545549
{
546550
precondition(self.symbolizer.graph.cultures.count == destinations.count)
547551
precondition(self.symbolizer.graph.cultures.count == sources.count)
@@ -587,7 +591,7 @@ extension SSGC.Linker
587591
for (source, destination):
588592
(SSGC.Namespace, SymbolGraph.Namespace) in zip(sources[c], destinations[c])
589593
{
590-
self.link(decls: source.decls,
594+
try self.link(decls: source.decls,
591595
at: destination.range,
592596
of: culture,
593597
in: self.symbolizer.graph.namespaces[destination.index])
@@ -599,19 +603,19 @@ extension SSGC.Linker
599603
func link(decls:[SSGC.Decl],
600604
at addresses:ClosedRange<Int32>,
601605
of culture:Culture,
602-
in namespace:Symbol.Module)
606+
in namespace:Symbol.Module) throws
603607
{
604608
for (address, decl):(Int32, SSGC.Decl) in zip(addresses, decls)
605609
{
606-
self.link(decl: decl, at: address, of: culture, in: namespace)
610+
try self.link(decl: decl, at: address, of: culture, in: namespace)
607611
}
608612
}
609613

610614
private mutating
611615
func link(decl:SSGC.Decl,
612616
at address:Int32,
613617
of culture:Culture,
614-
in namespace:Symbol.Module)
618+
in namespace:Symbol.Module) throws
615619
{
616620
let signature:Signature<Int32> = decl.signature.map { self.symbolizer.intern($0) }
617621

@@ -683,6 +687,12 @@ extension SSGC.Linker
683687
let linked:(article:SymbolGraph.Article, topics:[SymbolGraph.Topic])?
684688
let rename:Int32?
685689

690+
if let sections:Markdown.SemanticSections = markdown?.parsed.details
691+
{
692+
try self.tables.inline(resources: culture.resources,
693+
into: sections,
694+
with: self.swiftParser)
695+
}
686696
if markdown != nil || renamed != nil
687697
{
688698
(linked, rename) = self.tables.resolving(with: .init(
@@ -723,9 +733,12 @@ extension SSGC.Linker
723733
}
724734
extension SSGC.Linker
725735
{
736+
/// Links extensions that have already been assigned addresses.
737+
///
738+
/// This throws an error if and only if a file system error occurs. This is fatal because
739+
/// there is already logic in the linker to handle the case where files are missing.
726740
public mutating
727-
func link(extensions:[SSGC.Extension],
728-
at addresses:[(Int32, Int)])
741+
func link(extensions:[SSGC.Extension], at addresses:[(Int32, Int)]) throws
729742
{
730743
for ((scalar, index), `extension`):((Int32, Int), SSGC.Extension) in zip(
731744
addresses,
@@ -737,10 +750,9 @@ extension SSGC.Linker
737750
// like DocC does. (Except DocC does this across all extensions with the
738751
// same extended type.)
739752
// https://github.com/apple/swift-docc/pull/369
740-
var longest:Int = 0
741-
753+
var location:SourceLocation<Symbol.File>? = nil
742754
var comment:SSGC.DocumentationComment? = nil
743-
var file:Symbol.File? = nil
755+
var longest:Int = 0
744756

745757
for block:SSGC.Extension.Block in `extension`.blocks
746758
{
@@ -752,107 +764,62 @@ extension SSGC.Linker
752764
let length:Int = current.text.count
753765
if (longest, comment?.text ?? "") < (length, current.text)
754766
{
755-
longest = length
767+
location = block.location
756768
comment = current
757-
file = block.location?.file
769+
longest = length
758770
}
759771
}
760772
}
761-
if let comment:SSGC.DocumentationComment
762-
{
763-
// Only intern the file path for the extension block with the longest comment
764-
let comment:Markdown.Source = .init(comment: comment,
765-
in: file.map { self.symbolizer.intern($0) })
766-
767-
let parsed:Markdown.SemanticDocument = comment.parse(
768-
markdownParser: self.doccommentParser,
769-
snippetsTable: self.snippets,
770-
diagnostics: &self.tables.diagnostics)
771773

772-
// Need to load these before mutating the symbol graph to avoid
773-
// overlapping access
774-
let imports:[Symbol.Module] = self.symbolizer.importAll
775-
;
776-
{
777-
let scopes:SSGC.OutlineResolutionScopes = .init(
778-
namespace: self.symbolizer.graph.namespaces[$0.namespace],
779-
culture: .init(
780-
resources: self.resources[$0.culture],
781-
imports: imports,
782-
module: self.symbolizer.graph.namespaces[$0.culture]),
783-
scope: [String].init(`extension`.path))
784-
785-
$0.article = self.tables.resolving(with: scopes)
786-
{
787-
$0.link(article: parsed, file: comment.origin?.file)
788-
}
789-
790-
} (&self.symbolizer.graph.decls.nodes[scalar].extensions[index])
791-
}
792-
}
793-
}
794-
}
795-
extension SSGC.Linker
796-
{
797-
private mutating
798-
func inline(resources:[String: SSGC.Resource],
799-
into sections:Markdown.SemanticSections) throws
800-
{
801-
var last:[String?: SSGC.ResourceText] = [:]
802-
try sections.traverse
803-
{
804774
guard
805-
case let block as Markdown.BlockCodeReference = $0
775+
let comment:SSGC.DocumentationComment
806776
else
807777
{
808-
return
778+
continue
809779
}
810780

811-
guard
812-
let file:String = block.file
813-
else
814-
{
815-
self.tables.diagnostics[block.source] = SSGC.ResourceError.fileRequired(
816-
argument: "file")
817-
return
818-
}
819-
guard
820-
let file:SSGC.Resource = resources[file]
821-
else
822-
{
823-
self.tables.diagnostics[block.source] = SSGC.ResourceError.fileNotFound(file)
824-
return
825-
}
781+
// Only intern the file path for the extension block with the longest comment
782+
let file:Int32? = location.map { self.symbolizer.intern($0.file) }
783+
let markdown:Markdown.Source = .init(comment: comment, in: file)
826784

827-
let code:SSGC.ResourceText = try file.text()
828-
defer
829-
{
830-
last[block.title] = code
831-
}
785+
// Need to load these before mutating the symbol graph to avoid
786+
// overlapping access
787+
let imports:[Symbol.Module] = self.symbolizer.importAll
788+
let parsed:Markdown.SemanticDocument = markdown.parse(
789+
markdownParser: self.doccommentParser,
790+
snippetsTable: self.snippets,
791+
diagnostics: &self.tables.diagnostics)
832792

833-
let base:SSGC.ResourceText?
834-
switch block.base
793+
try
835794
{
836-
case .file(let file)?:
837-
if let file:SSGC.Resource = resources[file]
838-
{
839-
base = try file.text()
840-
break
841-
}
795+
let culture:Culture = .init(resources: self.resources[$0.culture],
796+
imports: imports,
797+
module: self.symbolizer.graph.namespaces[$0.culture])
842798

843-
self.tables.diagnostics[block.source] = SSGC.ResourceError.fileNotFound(file)
844-
base = nil
799+
try self.tables.inline(resources: culture.resources,
800+
into: parsed.details,
801+
with: self.swiftParser)
845802

846-
case .auto?:
847-
base = last[block.title]
803+
let scopes:SSGC.OutlineResolutionScopes = .init(
804+
namespace: self.symbolizer.graph.namespaces[$0.namespace],
805+
culture: culture,
806+
scope: [String].init(`extension`.path))
848807

849-
case nil:
850-
base = nil
851-
}
808+
$0.article = self.tables.resolving(with: scopes)
809+
{
810+
$0.link(article: parsed, file: file)
811+
}
852812

853-
block.inline(code: code, base: base, with: self.swiftParser)
813+
} (&self.symbolizer.graph.decls.nodes[scalar].extensions[index])
854814
}
855815
}
816+
}
817+
extension SSGC.Linker
818+
{
819+
/// Links articles that have already been assigned addresses.
820+
///
821+
/// This throws an error if and only if a file system error occurs. This is fatal because
822+
/// there is already logic in the linker to handle the case where files are missing.
856823
public mutating
857824
func link(articles:[[SSGC.Article]]) throws
858825
{
@@ -864,11 +831,12 @@ extension SSGC.Linker
864831

865832
for article:SSGC.Article in articles[c]
866833
{
867-
try self.inline(resources: culture.resources, into: article.body.details)
834+
try self.tables.inline(resources: culture.resources,
835+
into: article.body.details,
836+
with: self.swiftParser)
868837

869838
self.tables.resolving(with: .init(culture: culture))
870839
{
871-
872840
let documentation:(SymbolGraph.Article, [SymbolGraph.Topic]) = $0.link(
873841
attached: article.body,
874842
file: article.file)

0 commit comments

Comments
 (0)