Skip to content

Commit 7190073

Browse files
committed
Serialize symbol graphs for extended modules separately
When a module extends a type from another module, serialize those symbols into separated files dedicated to those extended modules. This makes it easier to ingest and categorize those symbols under the extended module if desired. rdar://58941718
1 parent be68f86 commit 7190073

35 files changed

+254
-61
lines changed

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,8 @@ class SerializedASTFile final : public LoadedFile {
403403
SmallVectorImpl<GenericSignature> &genericSignatures)
404404
override;
405405

406+
StringRef getTargetTriple() const;
407+
406408
static bool classof(const FileUnit *file) {
407409
return file->getKind() == FileUnitKind::SerializedAST;
408410
}

include/swift/SymbolGraphGen/SymbolGraphGen.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class ModuleDecl;
2020
namespace symbolgraphgen {
2121

2222
struct SymbolGraphOptions {
23-
/// The path to output the symbol graph JSON.
24-
StringRef OutputPath;
23+
/// The directory to output the symbol graph JSON files.
24+
StringRef OutputDir;
2525

2626
/// The target of the module.
2727
llvm::Triple Target;

lib/Serialization/ModuleFile.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,10 @@ class ModuleFile
823823
return ModuleInputBuffer->getBufferIdentifier();
824824
}
825825

826+
StringRef getTargetTriple() const {
827+
return TargetTriple;
828+
}
829+
826830
/// AST-verify imported decls.
827831
///
828832
/// Has no effect in NDEBUG builds.

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,10 @@ StringRef SerializedASTFile::getFilename() const {
11811181
return File.getModuleFilename();
11821182
}
11831183

1184+
StringRef SerializedASTFile::getTargetTriple() const {
1185+
return File.getTargetTriple();
1186+
}
1187+
11841188
const clang::Module *SerializedASTFile::getUnderlyingClangModule() const {
11851189
if (auto *UnderlyingModule = File.getUnderlyingModule())
11861190
return UnderlyingModule->findUnderlyingClangModule();

lib/SymbolGraphGen/FormatVersion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#define SWIFT_SYMBOLGRAPHGEN_FORMATVERSION_H
1515

1616
#define SWIFT_SYMBOLGRAPH_FORMAT_MAJOR 0
17-
#define SWIFT_SYMBOLGRAPH_FORMAT_MINOR 2
17+
#define SWIFT_SYMBOLGRAPH_FORMAT_MINOR 3
1818
#define SWIFT_SYMBOLGRAPH_FORMAT_PATCH 0
1919

2020
#endif // SWIFT_SYMBOLGRAPHGEN_FORMATVERSION_H

lib/SymbolGraphGen/Symbol.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,11 @@ void Symbol::serializeSwiftExtensionMixin(llvm::json::OStream &OS) const {
256256
if (const auto *Extension
257257
= dyn_cast_or_null<ExtensionDecl>(VD->getInnermostDeclContext())) {
258258
OS.attributeObject("swiftExtension", [&](){
259-
OS.attribute("definedInModule", Graph.M.getNameStr());
259+
if (const auto *ExtendedNominal = Extension->getExtendedNominal()) {
260+
if (const auto *ExtendedModule = ExtendedNominal->getModuleContext()) {
261+
OS.attribute("extendedModule", ExtendedModule->getNameStr());
262+
}
263+
}
260264
auto Generics = Extension->getGenericSignature();
261265
if (Generics && !Generics->getRequirements().empty()) {
262266
OS.attributeArray("constraints", [&](){

lib/SymbolGraphGen/SymbolGraph.cpp

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "swift/AST/ProtocolConformance.h"
1717
#include "swift/AST/USRGeneration.h"
1818
#include "swift/Basic/Version.h"
19+
#include "swift/ClangImporter/ClangModule.h"
20+
#include "swift/Serialization/SerializedModuleLoader.h"
1921

2022
#include "DeclarationFragmentPrinter.h"
2123
#include "FormatVersion.h"
@@ -25,10 +27,16 @@
2527
using namespace swift;
2628
using namespace symbolgraphgen;
2729

28-
SymbolGraph::SymbolGraph(ModuleDecl &M, llvm::Triple Target,
30+
SymbolGraph::SymbolGraph(ModuleDecl &M,
31+
Optional<ModuleDecl *> ExtendedModule,
32+
llvm::Triple Target,
2933
markup::MarkupContext &Ctx,
3034
Optional<llvm::VersionTuple> ModuleVersion)
31-
: M(M), Target(Target), Ctx(Ctx), ModuleVersion(ModuleVersion) {}
35+
: M(M),
36+
ExtendedModule(ExtendedModule),
37+
Target(Target),
38+
Ctx(Ctx),
39+
ModuleVersion(ModuleVersion) {}
3240

3341
// MARK: - Utilities
3442

@@ -98,11 +106,27 @@ PrintOptions SymbolGraph::getDeclarationFragmentsPrintOptions() const {
98106
return Opts;
99107
}
100108

101-
// MARK: - Relationships
109+
// MARK: - Symbols (Nodes)
110+
111+
void SymbolGraph::recordNode(const ValueDecl *VD) {
112+
Nodes.insert(VD);
113+
114+
// Record all of the possible relationships (edges) originating
115+
// with this declaration.
116+
recordMemberRelationship(VD);
117+
recordConformanceRelationships(VD);
118+
recordInheritanceRelationships(VD);
119+
recordDefaultImplementationRelationships(VD);
120+
recordOverrideRelationship(VD);
121+
recordRequirementRelationships(VD);
122+
recordOptionalRequirementRelationships(VD);
123+
}
124+
125+
// MARK: - Relationships (Edges)
102126

103127
void SymbolGraph::recordEdge(const ValueDecl *Source,
104-
const ValueDecl *Target,
105-
RelationshipKind Kind) {
128+
const ValueDecl *Target,
129+
RelationshipKind Kind) {
106130
if (Target->isPrivateStdlibDecl(
107131
/*treatNonBuiltinProtocolsAsPublic = */false)) {
108132
return;
@@ -237,7 +261,36 @@ void SymbolGraph::serialize(llvm::json::OStream &OS) {
237261
OS.attributeObject("module", [&](){
238262
OS.attribute("name", M.getNameStr());
239263
AttributeRAII Platform("platform", OS);
240-
symbolgraphgen::serialize(Target, OS);
264+
265+
auto *MainFile = M.getFiles().front();
266+
switch (MainFile->getKind()) {
267+
case FileUnitKind::Builtin:
268+
llvm_unreachable("Unexpected module kind: Builtin");
269+
case FileUnitKind::DWARFModule:
270+
llvm_unreachable("Unexpected module kind: DWARFModule");
271+
case FileUnitKind::Source:
272+
llvm_unreachable("Unexpected module kind: Source");
273+
break;
274+
case FileUnitKind::SerializedAST: {
275+
auto SerializedAST = cast<SerializedASTFile>(MainFile);
276+
auto Target = llvm::Triple(SerializedAST->getTargetTriple());
277+
symbolgraphgen::serialize(Target, OS);
278+
break;
279+
}
280+
case FileUnitKind::ClangModule: {
281+
auto ClangModule = cast<ClangModuleUnit>(MainFile);
282+
if (const auto *Overlay = ClangModule->getOverlayModule()) {
283+
auto &OverlayMainFile =
284+
Overlay->getMainFile(FileUnitKind::SerializedAST);
285+
auto SerializedAST = cast<SerializedASTFile>(OverlayMainFile);
286+
auto Target = llvm::Triple(SerializedAST.getTargetTriple());
287+
symbolgraphgen::serialize(Target, OS);
288+
} else {
289+
symbolgraphgen::serialize(Target, OS);
290+
}
291+
break;
292+
}
293+
}
241294
});
242295

243296
if (ModuleVersion) {

lib/SymbolGraphGen/SymbolGraph.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ struct SymbolGraph {
3131
*/
3232
ModuleDecl &M;
3333

34+
/**
35+
The module whose types were extended in `M`.
36+
*/
37+
Optional<ModuleDecl *> ExtendedModule;
38+
3439
/**
3540
The module's target triple.
3641
*/
@@ -60,7 +65,9 @@ struct SymbolGraph {
6065
/// A cache of USRs for declarations.
6166
llvm::DenseMap<const ValueDecl *, StringRef> USRCache;
6267

63-
SymbolGraph(ModuleDecl &M, llvm::Triple Target,
68+
SymbolGraph(ModuleDecl &M,
69+
Optional<ModuleDecl *> ExtendedModule,
70+
llvm::Triple Target,
6471
markup::MarkupContext &Ctx,
6572
Optional<llvm::VersionTuple> ModuleVersion = None);
6673

@@ -76,6 +83,13 @@ struct SymbolGraph {
7683
/// Get the base print options for declaration fragments.
7784
PrintOptions getDeclarationFragmentsPrintOptions() const;
7885

86+
// MARK: - Symbols (Nodes)
87+
88+
/**
89+
Record a symbol as a node in the graph.
90+
*/
91+
void recordNode(const ValueDecl *VD);
92+
7993
// MARK: - Relationships (Edges)
8094

8195
/**

lib/SymbolGraphGen/SymbolGraphASTWalker.cpp

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/ADT/StringSwitch.h"
1414
#include "swift/AST/Decl.h"
1515
#include "swift/AST/Module.h"
16+
#include "swift/Serialization/SerializedModuleLoader.h"
1617
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
1718

1819
#include "SymbolGraphASTWalker.h"
@@ -24,7 +25,7 @@ SymbolGraphASTWalker::SymbolGraphASTWalker(ModuleDecl &M,
2425
const SymbolGraphOptions &Options)
2526
: Options(Options),
2627
M(M),
27-
Graph(M, Options.Target, Ctx) {}
28+
Graph(M, None, Options.Target, Ctx) {}
2829

2930
/// Returns `true` if the symbol should be included as a node in the graph.
3031
bool SymbolGraphASTWalker::shouldIncludeNode(const Decl *D) const {
@@ -86,6 +87,21 @@ bool SymbolGraphASTWalker::shouldIncludeNode(const Decl *D) const {
8687
return ShouldInclude;
8788
}
8889

90+
/// Get a "sub" symbol graph for the parent module of a type that the main module `M` is extending.
91+
SymbolGraph &SymbolGraphASTWalker::getExtendedModuleSymbolGraph(ModuleDecl *M) {
92+
auto Found = ExtendedModuleGraphs.find(M);
93+
if (Found != ExtendedModuleGraphs.end()) {
94+
return *Found->getSecond();
95+
}
96+
auto *Memory = Ctx.allocate(sizeof(SymbolGraph), alignof(SymbolGraph));
97+
auto *SG = new (Memory) SymbolGraph(Graph.M,
98+
Optional<ModuleDecl *>(M),
99+
Options.Target,
100+
Ctx);
101+
ExtendedModuleGraphs.insert({M, SG});
102+
return *SG;
103+
}
104+
89105
bool SymbolGraphASTWalker::walkToDeclPre(Decl *D, CharSourceRange Range) {
90106

91107
switch (D->getKind()) {
@@ -111,17 +127,23 @@ bool SymbolGraphASTWalker::walkToDeclPre(Decl *D, CharSourceRange Range) {
111127
}
112128

113129
auto *VD = cast<ValueDecl>(D);
114-
Graph.Nodes.insert(VD);
115-
116-
// Record all of the possible relationships (edges) originating
117-
// with this declaration.
118-
Graph.recordMemberRelationship(VD);
119-
Graph.recordConformanceRelationships(VD);
120-
Graph.recordInheritanceRelationships(VD);
121-
Graph.recordDefaultImplementationRelationships(VD);
122-
Graph.recordOverrideRelationship(VD);
123-
Graph.recordRequirementRelationships(VD);
124-
Graph.recordOptionalRequirementRelationships(VD);
125-
130+
131+
// If this symbol extends a type from another module, record it in that
132+
// module's symbol graph, which will be emitted separately.
133+
if (const auto *Extension
134+
= dyn_cast_or_null<ExtensionDecl>(VD->getInnermostDeclContext())) {
135+
if (const auto *ExtendedNominal = Extension->getExtendedNominal()) {
136+
auto ExtendedModule = ExtendedNominal->getModuleContext();
137+
if (ExtendedModule != &M) {
138+
auto &SG = getExtendedModuleSymbolGraph(ExtendedModule);
139+
SG.recordNode(VD);
140+
return true;
141+
}
142+
}
143+
}
144+
145+
// Otherwise, record this in the main module `M`'s symbol graph.
146+
Graph.recordNode(VD);
147+
126148
return true;
127149
}

lib/SymbolGraphGen/SymbolGraphASTWalker.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#ifndef SWIFT_SYMBOLGRAPHGEN_SYMBOLGRAPHASTWALKER_H
1414
#define SWIFT_SYMBOLGRAPHGEN_SYMBOLGRAPHASTWALKER_H
1515

16+
#include "llvm/ADT/DenseMap.h"
17+
#include "swift/AST/Module.h"
1618
#include "swift/Basic/LLVM.h"
1719
#include "swift/IDE/SourceEntityWalker.h"
1820
#include "swift/Markup/Markup.h"
@@ -48,16 +50,24 @@ struct SymbolGraphASTWalker : public SourceEntityWalker {
4850
/// The symbol graph for a module.
4951
SymbolGraph Graph;
5052

51-
// MARK: -
53+
/// A map of modules whose types were extended by the main module of interest `M`.
54+
llvm::DenseMap<ModuleDecl *, SymbolGraph *> ExtendedModuleGraphs;
55+
56+
// MARK: - Initialization
5257

5358
SymbolGraphASTWalker(ModuleDecl &M, const SymbolGraphOptions &Options);
5459
virtual ~SymbolGraphASTWalker() {}
5560

56-
// MARK: -
61+
// MARK: - Utilities
5762

5863
/// Returns `true` if the symbol should be included as a node in the graph.
5964
bool shouldIncludeNode(const Decl *D) const;
6065

66+
/// Get a "sub" symbol graph for the parent module of a type that the main module `M` is extending.
67+
SymbolGraph &getExtendedModuleSymbolGraph(ModuleDecl *M);
68+
69+
// MARK: - SourceEntityWalker
70+
6171
virtual bool walkToDeclPre(Decl *D, CharSourceRange Range);
6272
};
6373

0 commit comments

Comments
 (0)