Skip to content

Commit 69c4fc4

Browse files
Ashley Garlandbitjammer
authored andcommitted
Add optional -emit-symbol-graph output when emitting modules
rdar://71497047
1 parent 96397ec commit 69c4fc4

File tree

17 files changed

+114
-27
lines changed

17 files changed

+114
-27
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,7 @@ class alignas(1 << DeclAlignInBits) Decl {
866866
}
867867

868868
/// \returns the unparsed comment attached to this declaration.
869-
RawComment getRawComment(bool SerializedOK = false) const;
869+
RawComment getRawComment(bool SerializedOK = true) const;
870870

871871
Optional<StringRef> getGroupName() const;
872872

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ ERROR(error_mode_cannot_emit_interface,none,
123123
"this mode does not support emitting module interface files", ())
124124
ERROR(error_mode_cannot_emit_module_summary,none,
125125
"this mode does not support emitting module summary files", ())
126+
ERROR(error_mode_cannot_emit_symbol_graph,none,
127+
"this mode does not support emitting symbol graph files", ())
126128
ERROR(cannot_emit_ir_skipping_function_bodies,none,
127129
"the -experimental-skip-*-function-bodies* flags do not support "
128130
"emitting IR", ())

include/swift/Frontend/FrontendOptions.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,19 @@ class FrontendOptions {
373373

374374
/// Whether we're configured to track system intermodule dependencies.
375375
bool shouldTrackSystemDependencies() const;
376+
377+
/// Whether to emit symbol graphs for the output module.
378+
bool EmitSymbolGraph = false;
379+
380+
/// The directory to which we should emit a symbol graph JSON files.
381+
/// It is valid whenever there are any inputs.
382+
///
383+
/// These are JSON file that describes the public interface of a module for
384+
/// curating documentation, separated into files for each module this module
385+
/// extends.
386+
///
387+
/// \sa SymbolGraphASTWalker
388+
std::string SymbolGraphOutputDir;
376389

377390
private:
378391
static bool canActionEmitDependencies(ActionType);

include/swift/Option/Options.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,4 +1159,15 @@ def disable_autolinking_runtime_compatibility_dynamic_replacements
11591159
HelpText<"Do not use autolinking for the dynamic replacement runtime "
11601160
"compatibility library">;
11611161

1162+
def emit_symbol_graph: Flag<["-"], "emit-symbol-graph">,
1163+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
1164+
SupplementaryOutput, HelpHidden]>,
1165+
HelpText<"Emit a symbol graph">;
1166+
1167+
def emit_symbol_graph_dir : Separate<["-"], "emit-symbol-graph-dir">,
1168+
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
1169+
ArgumentIsPath, SupplementaryOutput, HelpHidden]>,
1170+
HelpText<"Emit a symbol graph to directory <dir>">,
1171+
MetaVarName<"<dir>">;
1172+
11621173
include "FrontendOptions.td"

include/swift/Serialization/SerializationOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ namespace swift {
3030
const char *OutputPath = nullptr;
3131
const char *DocOutputPath = nullptr;
3232
const char *SourceInfoOutputPath = nullptr;
33+
std::string SymbolGraphOutputDir;
3334

3435
StringRef GroupInfoPath;
3536
StringRef ImportedHeader;

lib/AST/Module.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ SourceFile::getBasicLocsForDecl(const Decl *D) const {
878878
BasicDeclLocs Result;
879879
Result.SourceFilePath = SM.getDisplayNameForLoc(D->getLoc());
880880

881-
for (const auto &SRC : D->getRawComment().Comments) {
881+
for (const auto &SRC : D->getRawComment(/*SerializedOK*/false).Comments) {
882882
Result.DocRanges.push_back(std::make_pair(
883883
LineColumn { SRC.StartLine, SRC.StartColumn },
884884
SRC.Range.getByteLength())

lib/Driver/ToolChains.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,11 @@ ToolChain::constructInvocation(const CompileJobAction &job,
556556
options::
557557
OPT_disable_autolinking_runtime_compatibility_dynamic_replacements);
558558

559+
if (context.OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
560+
context.Args.AddLastArg(Arguments, options::OPT_emit_symbol_graph);
561+
context.Args.AddLastArg(Arguments, options::OPT_emit_symbol_graph_dir);
562+
}
563+
559564
return II;
560565
}
561566

@@ -1039,6 +1044,9 @@ ToolChain::constructInvocation(const MergeModuleJobAction &job,
10391044
addOutputsOfType(Arguments, context.Output, context.Args, file_types::TY_TBD,
10401045
"-emit-tbd-path");
10411046

1047+
context.Args.AddLastArg(Arguments, options::OPT_emit_symbol_graph);
1048+
context.Args.AddLastArg(Arguments, options::OPT_emit_symbol_graph_dir);
1049+
10421050
context.Args.AddLastArg(Arguments, options::OPT_import_objc_header);
10431051

10441052
context.Args.AddLastArg(

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,12 @@ bool ArgsToFrontendOptionsConverter::convert(
234234
computeImplicitImportModuleNames(OPT_testable_import_module, /*isTestable=*/true);
235235
computeLLVMArgs();
236236

237+
Opts.EmitSymbolGraph |= Args.hasArg(OPT_emit_symbol_graph);
238+
239+
if (const Arg *A = Args.getLastArg(OPT_emit_symbol_graph_dir)) {
240+
Opts.SymbolGraphOutputDir = A->getValue();
241+
}
242+
237243
return false;
238244
}
239245

@@ -581,6 +587,11 @@ bool ArgsToFrontendOptionsConverter::checkUnusedSupplementaryOutputPaths()
581587
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_summary);
582588
return true;
583589
}
590+
if (!FrontendOptions::canActionEmitModule(Opts.RequestedAction) &&
591+
!Opts.SymbolGraphOutputDir.empty()) {
592+
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_symbol_graph);
593+
return true;
594+
}
584595
return false;
585596
}
586597

lib/Frontend/ArgsToFrontendOutputsConverter.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,8 @@ createFromTypeToPathMap(const TypeToPathMap *map) {
536536
paths.ModuleInterfaceOutputPath},
537537
{file_types::TY_SwiftModuleSummaryFile, paths.ModuleSummaryOutputPath},
538538
{file_types::TY_PrivateSwiftModuleInterfaceFile,
539-
paths.PrivateModuleInterfaceOutputPath}};
539+
paths.PrivateModuleInterfaceOutputPath},
540+
};
540541
for (const std::pair<file_types::ID, std::string &> &typeAndString :
541542
typesAndStrings) {
542543
auto const out = map->find(typeAndString.first);
@@ -559,7 +560,8 @@ SupplementaryOutputPathsComputer::readSupplementaryOutputFileMap() const {
559560
options::OPT_emit_private_module_interface_path,
560561
options::OPT_emit_module_source_info_path,
561562
options::OPT_emit_tbd_path,
562-
options::OPT_emit_ldadd_cfile_path)) {
563+
options::OPT_emit_ldadd_cfile_path,
564+
options::OPT_emit_symbol_graph_dir)) {
563565
Diags.diagnose(SourceLoc(),
564566
diag::error_cannot_have_supplementary_outputs,
565567
A->getSpelling(), "-supplementary-output-file-map");

lib/Frontend/CompilerInvocation.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,12 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
682682
Opts.AttachCommentsToDecls = true;
683683
}
684684

685+
// If we are emitting a symbol graph file, configure lexing and parsing to
686+
// remember comments.
687+
if (FrontendOpts.EmitSymbolGraph) {
688+
Opts.AttachCommentsToDecls = true;
689+
}
690+
685691
// If we're parsing SIL, access control doesn't make sense to enforce.
686692
if (Args.hasArg(OPT_parse_sil) ||
687693
FrontendOpts.InputsAndOutputs.shouldTreatAsSIL()) {

lib/Frontend/Frontend.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,19 @@ SerializationOptions CompilerInvocation::computeSerializationOptions(
154154
serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath;
155155
serializationOpts.ModuleLinkName = opts.ModuleLinkName;
156156
serializationOpts.ExtraClangOptions = getClangImporterOptions().ExtraArgs;
157+
158+
if (opts.EmitSymbolGraph) {
159+
if (!opts.SymbolGraphOutputDir.empty()) {
160+
serializationOpts.SymbolGraphOutputDir = opts.SymbolGraphOutputDir;
161+
} else {
162+
serializationOpts.SymbolGraphOutputDir = serializationOpts.OutputPath;
163+
}
164+
SmallString<256> OutputDir(serializationOpts.SymbolGraphOutputDir);
165+
llvm::sys::fs::make_absolute(OutputDir);
166+
llvm::sys::path::remove_filename(OutputDir);
167+
serializationOpts.SymbolGraphOutputDir = OutputDir.str().str();
168+
}
169+
157170
if (!getIRGenOptions().ForceLoadSymbolName.empty())
158171
serializationOpts.AutolinkForceLoad = true;
159172

lib/Serialization/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ add_swift_host_library(swiftSerialization STATIC
1616
)
1717
target_link_libraries(swiftSerialization PRIVATE
1818
swiftClangImporter
19-
swiftSIL)
19+
swiftSIL
20+
swiftSymbolGraphGen)
2021

lib/Serialization/Serialization.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
#include "swift/Serialization/SerializationOptions.h"
4949
#include "swift/Strings.h"
5050
#include "clang/AST/DeclTemplate.h"
51+
#include "swift/SymbolGraphGen/SymbolGraphOptions.h"
52+
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
5153
#include "llvm/ADT/SmallSet.h"
5254
#include "llvm/ADT/SmallString.h"
5355
#include "llvm/ADT/StringExtras.h"
@@ -5544,4 +5546,20 @@ void swift::serialize(ModuleOrSourceFile DC,
55445546
return false;
55455547
});
55465548
}
5549+
5550+
if (!options.SymbolGraphOutputDir.empty()) {
5551+
if (DC.is<ModuleDecl *>()) {
5552+
auto *M = DC.get<ModuleDecl*>();
5553+
FrontendStatsTracer tracer(getContext(DC).Stats,
5554+
"Serialization, symbolgraph");
5555+
symbolgraphgen::SymbolGraphOptions SGOpts {
5556+
options.SymbolGraphOutputDir,
5557+
M->getASTContext().LangOpts.Target,
5558+
/* PrettyPrint */false,
5559+
AccessLevel::Public,
5560+
/*EmitSynthesizedMembers*/true,
5561+
};
5562+
symbolgraphgen::emitSymbolGraphForModule(M, SGOpts);
5563+
}
5564+
}
55475565
}

lib/SymbolGraphGen/SymbolGraph.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -533,11 +533,9 @@ void SymbolGraph::serialize(llvm::json::OStream &OS) {
533533
case FileUnitKind::Synthesized:
534534
llvm_unreachable("Unexpected module kind: Synthesized");
535535
break;
536-
case FileUnitKind::Source: {
537-
auto Target = MainFile->getASTContext().LangOpts.Target;
538-
symbolgraphgen::serialize(Target, OS);
536+
case FileUnitKind::Source:
537+
symbolgraphgen::serialize(M.getASTContext().LangOpts.Target, OS);
539538
break;
540-
}
541539
case FileUnitKind::SerializedAST: {
542540
auto SerializedAST = cast<SerializedASTFile>(MainFile);
543541
auto Target = llvm::Triple(SerializedAST->getTargetTriple());

lib/SymbolGraphGen/SymbolGraphGen.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
#include "llvm/Support/JSON.h"
1414
#include "llvm/Support/Path.h"
15+
#include "swift/AST/ASTContext.h"
16+
#include "swift/AST/FileSystem.h"
1517
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
1618

1719
#include "SymbolGraphASTWalker.h"
@@ -49,18 +51,11 @@ int serializeSymbolGraph(SymbolGraph &SG,
4951
SmallString<1024> OutputPath(Options.OutputDir);
5052
llvm::sys::path::append(OutputPath, FileName);
5153

52-
std::error_code Error;
53-
llvm::raw_fd_ostream OS(OutputPath, Error, llvm::sys::fs::FA_Write);
54-
if (Error) {
55-
llvm::errs() << "Couldn't open output file '" << OutputPath
56-
<< " for writing: "
57-
<< Error.message() << "\n";
58-
return EXIT_FAILURE;
59-
}
60-
61-
llvm::json::OStream J(OS, Options.PrettyPrint ? 2 : 0);
62-
SG.serialize(J);
63-
return EXIT_SUCCESS;
54+
return withOutputFile(SG.M.getASTContext().Diags, OutputPath, [&](raw_ostream &OS) {
55+
llvm::json::OStream J(OS, Options.PrettyPrint ? 2 : 0);
56+
SG.serialize(J);
57+
return false;
58+
});
6459
}
6560

6661
} // end anonymous namespace

test/Serialization/comments-hidden.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ private class PrivateClass {
9292
// TESTING: InternalClass Documentation
9393
// TESTING: Internal Function Documentation
9494

95-
// SOURCE-LOC: comments-hidden.swift:37:15: Func/PublicClass.__UnderscoredPublic RawComment=none BriefComment=none DocCommentAsXML=none
96-
// SOURCE-LOC: comments-hidden.swift:39:10: Constructor/PublicClass.init RawComment=none BriefComment=none DocCommentAsXML=none
97-
// SOURCE-LOC: comments-hidden.swift:41:10: Subscript/PublicClass.subscript RawComment=none BriefComment=none DocCommentAsXML=none
98-
// SOURCE-LOC: comments-hidden.swift:43:10: Constructor/PublicClass.init RawComment=none BriefComment=none DocCommentAsXML=none
99-
// SOURCE-LOC: comments-hidden.swift:45:10: Subscript/PublicClass.subscript RawComment=none BriefComment=none DocCommentAsXML=none
100-
// SOURCE-LOC: comments-hidden.swift:52:15: Func/-= RawComment=none BriefComment=none DocCommentAsXML=none
95+
// SOURCE-LOC: comments-hidden.swift:37:15: Func/PublicClass.__UnderscoredPublic
96+
// SOURCE-LOC: comments-hidden.swift:39:10: Constructor/PublicClass.init
97+
// SOURCE-LOC: comments-hidden.swift:41:10: Subscript/PublicClass.subscript
98+
// SOURCE-LOC: comments-hidden.swift:43:10: Constructor/PublicClass.init
99+
// SOURCE-LOC: comments-hidden.swift:45:10: Subscript/PublicClass.subscript
100+
// SOURCE-LOC: comments-hidden.swift:52:15: Func/-=
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift %s -module-name EmitWhileBuilding -emit-module -emit-module-path %t/ -emit-symbol-graph -emit-symbol-graph-dir %t/
3+
// RUN: %FileCheck %s --input-file %t/EmitWhileBuilding.symbols.json
4+
5+
/// Does a foo.
6+
public func foo() {}
7+
8+
// CHECK: "precise":"s:17EmitWhileBuilding3fooyyF"

0 commit comments

Comments
 (0)