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
This commit is contained in:
Ashley Garland
2020-02-06 17:26:15 -08:00
parent be68f864e0
commit 7190073a85
35 changed files with 254 additions and 61 deletions

View File

@@ -403,6 +403,8 @@ public:
SmallVectorImpl<GenericSignature> &genericSignatures)
override;
StringRef getTargetTriple() const;
static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::SerializedAST;
}

View File

@@ -20,8 +20,8 @@ class ModuleDecl;
namespace symbolgraphgen {
struct SymbolGraphOptions {
/// The path to output the symbol graph JSON.
StringRef OutputPath;
/// The directory to output the symbol graph JSON files.
StringRef OutputDir;
/// The target of the module.
llvm::Triple Target;

View File

@@ -823,6 +823,10 @@ public:
return ModuleInputBuffer->getBufferIdentifier();
}
StringRef getTargetTriple() const {
return TargetTriple;
}
/// AST-verify imported decls.
///
/// Has no effect in NDEBUG builds.

View File

@@ -1181,6 +1181,10 @@ StringRef SerializedASTFile::getFilename() const {
return File.getModuleFilename();
}
StringRef SerializedASTFile::getTargetTriple() const {
return File.getTargetTriple();
}
const clang::Module *SerializedASTFile::getUnderlyingClangModule() const {
if (auto *UnderlyingModule = File.getUnderlyingModule())
return UnderlyingModule->findUnderlyingClangModule();

View File

@@ -14,7 +14,7 @@
#define SWIFT_SYMBOLGRAPHGEN_FORMATVERSION_H
#define SWIFT_SYMBOLGRAPH_FORMAT_MAJOR 0
#define SWIFT_SYMBOLGRAPH_FORMAT_MINOR 2
#define SWIFT_SYMBOLGRAPH_FORMAT_MINOR 3
#define SWIFT_SYMBOLGRAPH_FORMAT_PATCH 0
#endif // SWIFT_SYMBOLGRAPHGEN_FORMATVERSION_H

View File

@@ -256,7 +256,11 @@ void Symbol::serializeSwiftExtensionMixin(llvm::json::OStream &OS) const {
if (const auto *Extension
= dyn_cast_or_null<ExtensionDecl>(VD->getInnermostDeclContext())) {
OS.attributeObject("swiftExtension", [&](){
OS.attribute("definedInModule", Graph.M.getNameStr());
if (const auto *ExtendedNominal = Extension->getExtendedNominal()) {
if (const auto *ExtendedModule = ExtendedNominal->getModuleContext()) {
OS.attribute("extendedModule", ExtendedModule->getNameStr());
}
}
auto Generics = Extension->getGenericSignature();
if (Generics && !Generics->getRequirements().empty()) {
OS.attributeArray("constraints", [&](){

View File

@@ -16,6 +16,8 @@
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/USRGeneration.h"
#include "swift/Basic/Version.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "DeclarationFragmentPrinter.h"
#include "FormatVersion.h"
@@ -25,10 +27,16 @@
using namespace swift;
using namespace symbolgraphgen;
SymbolGraph::SymbolGraph(ModuleDecl &M, llvm::Triple Target,
SymbolGraph::SymbolGraph(ModuleDecl &M,
Optional<ModuleDecl *> ExtendedModule,
llvm::Triple Target,
markup::MarkupContext &Ctx,
Optional<llvm::VersionTuple> ModuleVersion)
: M(M), Target(Target), Ctx(Ctx), ModuleVersion(ModuleVersion) {}
: M(M),
ExtendedModule(ExtendedModule),
Target(Target),
Ctx(Ctx),
ModuleVersion(ModuleVersion) {}
// MARK: - Utilities
@@ -98,7 +106,23 @@ PrintOptions SymbolGraph::getDeclarationFragmentsPrintOptions() const {
return Opts;
}
// MARK: - Relationships
// MARK: - Symbols (Nodes)
void SymbolGraph::recordNode(const ValueDecl *VD) {
Nodes.insert(VD);
// Record all of the possible relationships (edges) originating
// with this declaration.
recordMemberRelationship(VD);
recordConformanceRelationships(VD);
recordInheritanceRelationships(VD);
recordDefaultImplementationRelationships(VD);
recordOverrideRelationship(VD);
recordRequirementRelationships(VD);
recordOptionalRequirementRelationships(VD);
}
// MARK: - Relationships (Edges)
void SymbolGraph::recordEdge(const ValueDecl *Source,
const ValueDecl *Target,
@@ -237,7 +261,36 @@ void SymbolGraph::serialize(llvm::json::OStream &OS) {
OS.attributeObject("module", [&](){
OS.attribute("name", M.getNameStr());
AttributeRAII Platform("platform", OS);
auto *MainFile = M.getFiles().front();
switch (MainFile->getKind()) {
case FileUnitKind::Builtin:
llvm_unreachable("Unexpected module kind: Builtin");
case FileUnitKind::DWARFModule:
llvm_unreachable("Unexpected module kind: DWARFModule");
case FileUnitKind::Source:
llvm_unreachable("Unexpected module kind: Source");
break;
case FileUnitKind::SerializedAST: {
auto SerializedAST = cast<SerializedASTFile>(MainFile);
auto Target = llvm::Triple(SerializedAST->getTargetTriple());
symbolgraphgen::serialize(Target, OS);
break;
}
case FileUnitKind::ClangModule: {
auto ClangModule = cast<ClangModuleUnit>(MainFile);
if (const auto *Overlay = ClangModule->getOverlayModule()) {
auto &OverlayMainFile =
Overlay->getMainFile(FileUnitKind::SerializedAST);
auto SerializedAST = cast<SerializedASTFile>(OverlayMainFile);
auto Target = llvm::Triple(SerializedAST.getTargetTriple());
symbolgraphgen::serialize(Target, OS);
} else {
symbolgraphgen::serialize(Target, OS);
}
break;
}
}
});
if (ModuleVersion) {

View File

@@ -31,6 +31,11 @@ struct SymbolGraph {
*/
ModuleDecl &M;
/**
The module whose types were extended in `M`.
*/
Optional<ModuleDecl *> ExtendedModule;
/**
The module's target triple.
*/
@@ -60,7 +65,9 @@ struct SymbolGraph {
/// A cache of USRs for declarations.
llvm::DenseMap<const ValueDecl *, StringRef> USRCache;
SymbolGraph(ModuleDecl &M, llvm::Triple Target,
SymbolGraph(ModuleDecl &M,
Optional<ModuleDecl *> ExtendedModule,
llvm::Triple Target,
markup::MarkupContext &Ctx,
Optional<llvm::VersionTuple> ModuleVersion = None);
@@ -76,6 +83,13 @@ struct SymbolGraph {
/// Get the base print options for declaration fragments.
PrintOptions getDeclarationFragmentsPrintOptions() const;
// MARK: - Symbols (Nodes)
/**
Record a symbol as a node in the graph.
*/
void recordNode(const ValueDecl *VD);
// MARK: - Relationships (Edges)
/**

View File

@@ -13,6 +13,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
#include "SymbolGraphASTWalker.h"
@@ -24,7 +25,7 @@ SymbolGraphASTWalker::SymbolGraphASTWalker(ModuleDecl &M,
const SymbolGraphOptions &Options)
: Options(Options),
M(M),
Graph(M, Options.Target, Ctx) {}
Graph(M, None, Options.Target, Ctx) {}
/// Returns `true` if the symbol should be included as a node in the graph.
bool SymbolGraphASTWalker::shouldIncludeNode(const Decl *D) const {
@@ -86,6 +87,21 @@ bool SymbolGraphASTWalker::shouldIncludeNode(const Decl *D) const {
return ShouldInclude;
}
/// Get a "sub" symbol graph for the parent module of a type that the main module `M` is extending.
SymbolGraph &SymbolGraphASTWalker::getExtendedModuleSymbolGraph(ModuleDecl *M) {
auto Found = ExtendedModuleGraphs.find(M);
if (Found != ExtendedModuleGraphs.end()) {
return *Found->getSecond();
}
auto *Memory = Ctx.allocate(sizeof(SymbolGraph), alignof(SymbolGraph));
auto *SG = new (Memory) SymbolGraph(Graph.M,
Optional<ModuleDecl *>(M),
Options.Target,
Ctx);
ExtendedModuleGraphs.insert({M, SG});
return *SG;
}
bool SymbolGraphASTWalker::walkToDeclPre(Decl *D, CharSourceRange Range) {
switch (D->getKind()) {
@@ -111,17 +127,23 @@ bool SymbolGraphASTWalker::walkToDeclPre(Decl *D, CharSourceRange Range) {
}
auto *VD = cast<ValueDecl>(D);
Graph.Nodes.insert(VD);
// Record all of the possible relationships (edges) originating
// with this declaration.
Graph.recordMemberRelationship(VD);
Graph.recordConformanceRelationships(VD);
Graph.recordInheritanceRelationships(VD);
Graph.recordDefaultImplementationRelationships(VD);
Graph.recordOverrideRelationship(VD);
Graph.recordRequirementRelationships(VD);
Graph.recordOptionalRequirementRelationships(VD);
// If this symbol extends a type from another module, record it in that
// module's symbol graph, which will be emitted separately.
if (const auto *Extension
= dyn_cast_or_null<ExtensionDecl>(VD->getInnermostDeclContext())) {
if (const auto *ExtendedNominal = Extension->getExtendedNominal()) {
auto ExtendedModule = ExtendedNominal->getModuleContext();
if (ExtendedModule != &M) {
auto &SG = getExtendedModuleSymbolGraph(ExtendedModule);
SG.recordNode(VD);
return true;
}
}
}
// Otherwise, record this in the main module `M`'s symbol graph.
Graph.recordNode(VD);
return true;
}

View File

@@ -13,6 +13,8 @@
#ifndef SWIFT_SYMBOLGRAPHGEN_SYMBOLGRAPHASTWALKER_H
#define SWIFT_SYMBOLGRAPHGEN_SYMBOLGRAPHASTWALKER_H
#include "llvm/ADT/DenseMap.h"
#include "swift/AST/Module.h"
#include "swift/Basic/LLVM.h"
#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Markup/Markup.h"
@@ -48,16 +50,24 @@ struct SymbolGraphASTWalker : public SourceEntityWalker {
/// The symbol graph for a module.
SymbolGraph Graph;
// MARK: -
/// A map of modules whose types were extended by the main module of interest `M`.
llvm::DenseMap<ModuleDecl *, SymbolGraph *> ExtendedModuleGraphs;
// MARK: - Initialization
SymbolGraphASTWalker(ModuleDecl &M, const SymbolGraphOptions &Options);
virtual ~SymbolGraphASTWalker() {}
// MARK: -
// MARK: - Utilities
/// Returns `true` if the symbol should be included as a node in the graph.
bool shouldIncludeNode(const Decl *D) const;
/// Get a "sub" symbol graph for the parent module of a type that the main module `M` is extending.
SymbolGraph &getExtendedModuleSymbolGraph(ModuleDecl *M);
// MARK: - SourceEntityWalker
virtual bool walkToDeclPre(Decl *D, CharSourceRange Range);
};

View File

@@ -20,6 +20,35 @@
using namespace swift;
using namespace symbolgraphgen;
namespace {
int serializeSymbolGraph(SymbolGraph &SG,
const SymbolGraphOptions &Options) {
SmallString<256> FileName(SG.M.getNameStr());
if (SG.ExtendedModule.hasValue()) {
FileName.push_back('@');
FileName.append(SG.ExtendedModule.getValue()->getNameStr());
}
FileName.append(".symbols.json");
SmallString<1024> OutputPath(Options.OutputDir);
llvm::sys::path::append(OutputPath, FileName);
std::error_code Error;
llvm::raw_fd_ostream OS(OutputPath, Error, llvm::sys::fs::FA_Write);
if (Error) {
llvm::errs() << "Couldn't open output file '" << OutputPath
<< " for writing: "
<< Error.message() << "\n";
return EXIT_FAILURE;
}
llvm::json::OStream J(OS, Options.PrettyPrint ? 2 : 0);
SG.serialize(J);
return EXIT_SUCCESS;
}
} // end anonymous namespace
// MARK: - Main Entry Point
/// Emit a symbol graph JSON file for a `ModuleDecl`.
@@ -41,16 +70,13 @@ symbolgraphgen::emitSymbolGraphForModule(ModuleDecl *M,
<< "Found " << Walker.Graph.Nodes.size() << " symbols and "
<< Walker.Graph.Edges.size() << " relationships.\n";
std::error_code Error;
llvm::raw_fd_ostream OS(Options.OutputPath, Error, llvm::sys::fs::FA_Write);
if (Error) {
llvm::errs() << "Couldn't open output file for writing: "
<< Error.message() << "\n";
return EXIT_FAILURE;
int Success = EXIT_SUCCESS;
Success |= serializeSymbolGraph(Walker.Graph, Options);
for (auto Pair : Walker.ExtendedModuleGraphs) {
Success |= serializeSymbolGraph(*Pair.getSecond(), Options);
}
llvm::json::OStream J(OS, Options.PrettyPrint ? 2 : 0);
Walker.Graph.serialize(J);
return EXIT_SUCCESS;
return Success;
}

View File

@@ -0,0 +1,20 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name Extension -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name Extension -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/Extension@Swift.symbols.json
public extension String {
/// Return something.
var something: String {
return "something"
}
}
// CHECK: module
// CHECK-NEXT: "name": "Extension"
// CHECK: "precise": "s:SS9ExtensionE9somethingSSvp"
// CHECK: "kind": "memberOf"
// CHECK-NEXT: "source": "s:SS9ExtensionE9somethingSSvp"
// CHECK-NEXT: "target": "s:SS"

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name SymbolGraphModule -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name SymbolGraphModule -I %t -pretty-print -o %t/SymbolGraphModule.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name SymbolGraphModule -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/SymbolGraphModule.symbols.json
public struct S {

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name ConformsTo -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name ConformsTo -I %t -pretty-print -o %t/ConformsTo.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name ConformsTo -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/ConformsTo.symbols.json
public protocol P {

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name DefaultImplementationOf -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name DefaultImplementationOf -I %t -pretty-print -o %t/DefaultImplementationOf.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name DefaultImplementationOf -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/DefaultImplementationOf.symbols.json
public protocol P {

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name InheritsFrom -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name InheritsFrom -I %t -pretty-print -o %t/InheritsFrom.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name InheritsFrom -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/InheritsFrom.symbols.json
public class Base {}

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name MemberOf -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name MemberOf -I %t -pretty-print -o %t/MemberOf.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name MemberOf -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/MemberOf.symbols.json
public struct S {

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name Overrides -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name Overrides -I %t -pretty-print -o %t/Overrides.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name Overrides -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/Overrides.symbols.json
public class Base {

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name ConformsTo -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name ConformsTo -I %t -pretty-print -o %t/ConformsTo.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name ConformsTo -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/ConformsTo.symbols.json
public protocol P {

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name TargetFallback -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name TargetFallback -I %t -pretty-print -o %t/TargetFallback.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name TargetFallback -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/TargetFallback.symbols.json
public struct S: CustomStringConvertible {

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name IncludeInternal -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name IncludeInternal -I %t -pretty-print -o %t/IncludeInternal.symbols.json -minimum-access-level internal
// RUN: %target-swift-symbolgraph-extract -module-name IncludeInternal -I %t -pretty-print -output-dir %t -minimum-access-level internal
// RUN: %FileCheck %s --input-file %t/IncludeInternal.symbols.json
public struct ShouldAppear {

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name PublicDefault -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name PublicDefault -I %t -pretty-print -o %t/PublicDefault.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name PublicDefault -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/PublicDefault.symbols.json
public struct ShouldAppear {

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name AccessLevels -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name AccessLevels -I %t -pretty-print -o %t/AccessLevels.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name AccessLevels -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/AccessLevels.symbols.json
// CHECK: "accessLevel": "public"

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name DocComment -emit-module-path %t/DocComment.swiftmodule
// RUN: %target-swift-symbolgraph-extract -module-name DocComment -I %t -pretty-print -o %t/DocComment.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name DocComment -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/DocComment.symbols.json
// CHECK: "text": "Single line."

View File

@@ -0,0 +1,9 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name Identifier -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name Identifier -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/Identifier.symbols.json
public struct MyStruct {}
// CHECK: "precise": "s:10Identifier8MyStructV",
// CHECK-NEXT: "interfaceLanguage": "swift"

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name Kinds -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name Kinds -I %t -pretty-print -o %t/Kinds.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name Kinds -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/Kinds.symbols.json
// CHECK: "identifier": "swift.class"

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name Availability -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name Availability -I %t -pretty-print -o %t/Availability.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name Availability -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/Availability.symbols.json
@available(macOS, introduced: 10.9, deprecated: 10.10, obsoleted: 10.11, message: "Everyone makes mistakes", renamed: "S2")

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name UnconditionallyDeprecated -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name UnconditionallyDeprecated -I %t -pretty-print -o %t/UnconditionallyDeprecated.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name UnconditionallyDeprecated -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/UnconditionallyDeprecated.symbols.json
@available(*, deprecated)

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name UnconditionallyUnavailable -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name UnconditionallyUnavailable -I %t -pretty-print -o %t/UnconditionallyUnavailable.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name UnconditionallyUnavailable -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/UnconditionallyUnavailable.symbols.json
@available(*, unavailable)

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name DeclarationFragments -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name DeclarationFragments -I %t -pretty-print -o %t/DeclarationFragments.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name DeclarationFragments -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/DeclarationFragments.symbols.json
public func foo<S>(f: @escaping () -> (), x: Int = 2, s: S) {}

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name FunctionSignature -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name FunctionSignature -I %t -pretty-print -o %t/FunctionSignature.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name FunctionSignature -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/FunctionSignature.symbols.json
public func foo(_ noext: Int, ext int: Int) -> String {

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name Names -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name Names -I %t -pretty-print -o %t/Names.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name Names -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/Names.symbols.json
public struct MyStruct {}

View File

@@ -0,0 +1,19 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name PathComponents -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name PathComponents -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/PathComponents.symbols.json
public struct Outer {
public struct Inner {
public var x = 1
}
}
// CHECK: "precise": "s:14PathComponents5OuterV5InnerV1xSivp"
// CHECK-NEXT: "interfaceLanguage": "swift"
// CHECK-NEXT: },
// CHECK-NEXT: "pathComponents": [
// CHECK-NEXT: "Outer"
// CHECK-NEXT: "Inner"
// CHECK-NEXT: "x"
// CHECK-NEXT: ]

View File

@@ -1,7 +1,7 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name SkipsPublicUnderscore -emit-module -emit-module-path %t/
// RUN: %target-swift-symbolgraph-extract -module-name SkipsPublicUnderscore -I %t -pretty-print -o %t/SymbolGraphModule.symbols.json
// RUN: %FileCheck %s --input-file %t/SymbolGraphModule.symbols.json
// RUN: %target-swift-symbolgraph-extract -module-name SkipsPublicUnderscore -I %t -pretty-print -output-dir %t
// RUN: %FileCheck %s --input-file %t/SkipsPublicUnderscore.symbols.json
public struct _ShouldntAppear {
public var shouldntAppear: Int

View File

@@ -71,7 +71,7 @@ Xcc("Xcc", llvm::cl::desc("Pass the following command-line flag to Clang"),
llvm::cl::cat(Category));
static llvm::cl::opt<std::string>
OutputPath("o", llvm::cl::desc("Symbol Graph JSON Output Path (Required)"), llvm::cl::cat(Category));
OutputDir("output-dir", llvm::cl::desc("Symbol Graph JSON Output Directory (Required)"), llvm::cl::cat(Category));
} // end namespace options
static bool argumentsAreValid() {
@@ -86,8 +86,8 @@ static bool argumentsAreValid() {
Valid = false;
}
if (options::OutputPath.empty()) {
llvm::errs() << "Required -o argument is missing\n";
if (options::OutputDir.empty()) {
llvm::errs() << "Required -output-dir argument is missing\n";
Valid = false;
}
@@ -116,6 +116,12 @@ int swift_symbolgraph_extract_main(ArrayRef<const char *> Args, const char *Argv
return EXIT_FAILURE;
}
if (!llvm::sys::fs::is_directory(options::OutputDir)) {
llvm::errs() << "-output-dir argument '" << options::OutputDir
<< " does not exist or is not a directory\n";
return EXIT_FAILURE;
}
CompilerInvocation Invocation;
Invocation.setMainExecutablePath(
@@ -161,7 +167,7 @@ int swift_symbolgraph_extract_main(ArrayRef<const char *> Args, const char *Argv
}
symbolgraphgen::SymbolGraphOptions Options {
options::OutputPath,
options::OutputDir,
llvm::Triple(options::Target),
options::PrettyPrint,
AccessLevel::Public,