mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #73080 from daniel-grumberg/export-import-sgf-extract
[SymbolGraphGen] Correctly handle exported imports in swift-symbolgraph-extract
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
#define SWIFT_MODULE_H
|
#define SWIFT_MODULE_H
|
||||||
|
|
||||||
#include "swift/AST/AccessNotes.h"
|
#include "swift/AST/AccessNotes.h"
|
||||||
|
#include "swift/AST/AttrKind.h"
|
||||||
#include "swift/AST/Decl.h"
|
#include "swift/AST/Decl.h"
|
||||||
#include "swift/AST/DeclContext.h"
|
#include "swift/AST/DeclContext.h"
|
||||||
#include "swift/AST/Identifier.h"
|
#include "swift/AST/Identifier.h"
|
||||||
@@ -551,7 +552,7 @@ public:
|
|||||||
ModuleDecl *getUnderlyingModuleIfOverlay() const;
|
ModuleDecl *getUnderlyingModuleIfOverlay() const;
|
||||||
|
|
||||||
/// Returns true if this module is the Clang overlay of \p other.
|
/// Returns true if this module is the Clang overlay of \p other.
|
||||||
bool isClangOverlayOf(ModuleDecl *other);
|
bool isClangOverlayOf(ModuleDecl *other) const;
|
||||||
|
|
||||||
/// Returns true if this module is the same module or either module is a clang
|
/// Returns true if this module is the same module or either module is a clang
|
||||||
/// overlay of the other.
|
/// overlay of the other.
|
||||||
@@ -1094,6 +1095,24 @@ public:
|
|||||||
/// for that.
|
/// for that.
|
||||||
void getDisplayDecls(SmallVectorImpl<Decl*> &results, bool recursive = false) const;
|
void getDisplayDecls(SmallVectorImpl<Decl*> &results, bool recursive = false) const;
|
||||||
|
|
||||||
|
struct ImportCollector {
|
||||||
|
SmallPtrSet<const ModuleDecl *, 4> imports;
|
||||||
|
llvm::SmallDenseMap<const ModuleDecl *, SmallPtrSet<Decl *, 4>, 4>
|
||||||
|
qualifiedImports;
|
||||||
|
AccessLevel minimumDocVisibility = AccessLevel::Private;
|
||||||
|
llvm::function_ref<bool(const ModuleDecl *)> importFilter = nullptr;
|
||||||
|
|
||||||
|
void collect(const ImportedModule &importedModule);
|
||||||
|
|
||||||
|
ImportCollector() = default;
|
||||||
|
ImportCollector(AccessLevel minimumDocVisibility)
|
||||||
|
: minimumDocVisibility(minimumDocVisibility) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
getDisplayDeclsRecursivelyAndImports(SmallVectorImpl<Decl *> &results,
|
||||||
|
ImportCollector &importCollector) const;
|
||||||
|
|
||||||
using LinkLibraryCallback = llvm::function_ref<void(LinkLibrary)>;
|
using LinkLibraryCallback = llvm::function_ref<void(LinkLibrary)>;
|
||||||
|
|
||||||
/// Generate the list of libraries needed to link this module, based on its
|
/// Generate the list of libraries needed to link this module, based on its
|
||||||
@@ -1273,12 +1292,6 @@ inline SourceLoc extractNearestSourceLoc(const ModuleDecl *mod) {
|
|||||||
return extractNearestSourceLoc(static_cast<const Decl *>(mod));
|
return extractNearestSourceLoc(static_cast<const Decl *>(mod));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collects modules that this module imports via `@_exported import`.
|
|
||||||
void collectParsedExportedImports(const ModuleDecl *M,
|
|
||||||
SmallPtrSetImpl<ModuleDecl *> &Imports,
|
|
||||||
llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> &QualifiedImports,
|
|
||||||
llvm::function_ref<bool(AttributedImport<ImportedModule>)> includeImport = nullptr);
|
|
||||||
|
|
||||||
/// If the import that would make the given declaration visibile is absent,
|
/// If the import that would make the given declaration visibile is absent,
|
||||||
/// emit a diagnostic and a fix-it suggesting adding the missing import.
|
/// emit a diagnostic and a fix-it suggesting adding the missing import.
|
||||||
bool diagnoseMissingImportForMember(const ValueDecl *decl,
|
bool diagnoseMissingImportForMember(const ValueDecl *decl,
|
||||||
|
|||||||
@@ -1573,6 +1573,10 @@ def output_dir : Separate<["-"], "output-dir">,
|
|||||||
HelpText<"Output directory">,
|
HelpText<"Output directory">,
|
||||||
MetaVarName<"<dir>">;
|
MetaVarName<"<dir>">;
|
||||||
|
|
||||||
|
def experimental_allowed_reexported_modules: CommaJoined<["-"], "experimental-allowed-reexported-modules=">,
|
||||||
|
Flags<[NoDriverOption, SwiftSymbolGraphExtractOption]>,
|
||||||
|
HelpText<"Allow reexporting symbols from the provided modules if they are themselves exported from the main module. This is a comma separated list of module names.">;
|
||||||
|
|
||||||
def skip_synthesized_members: Flag<[ "-" ], "skip-synthesized-members">,
|
def skip_synthesized_members: Flag<[ "-" ], "skip-synthesized-members">,
|
||||||
Flags<[NoDriverOption, SwiftSymbolGraphExtractOption]>,
|
Flags<[NoDriverOption, SwiftSymbolGraphExtractOption]>,
|
||||||
HelpText<"Skip members inherited through classes or default implementations">;
|
HelpText<"Skip members inherited through classes or default implementations">;
|
||||||
|
|||||||
@@ -162,6 +162,15 @@ namespace swift {
|
|||||||
void
|
void
|
||||||
getTopLevelDeclsForDisplay(ModuleDecl *M, SmallVectorImpl<Decl*> &Results, bool Recursive = false);
|
getTopLevelDeclsForDisplay(ModuleDecl *M, SmallVectorImpl<Decl*> &Results, bool Recursive = false);
|
||||||
|
|
||||||
|
/// Get all of the top-level declarations that should be printed as part of
|
||||||
|
/// this module. This may force synthesis of top-level declarations that
|
||||||
|
/// \p getDisplayDeclsForModule would only return if previous
|
||||||
|
/// work happened to have synthesized them.
|
||||||
|
void getTopLevelDeclsForDisplay(
|
||||||
|
ModuleDecl *M, SmallVectorImpl<Decl *> &Results,
|
||||||
|
llvm::function_ref<void(ModuleDecl *, SmallVectorImpl<Decl *> &)>
|
||||||
|
getDisplayDeclsForModule);
|
||||||
|
|
||||||
struct ExtensionInfo {
|
struct ExtensionInfo {
|
||||||
// The extension with the declarations to apply.
|
// The extension with the declarations to apply.
|
||||||
ExtensionDecl *Ext;
|
ExtensionDecl *Ext;
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/TargetParser/Triple.h"
|
#include "llvm/TargetParser/Triple.h"
|
||||||
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
|
||||||
#include "swift/AST/AttrKind.h"
|
#include "swift/AST/AttrKind.h"
|
||||||
|
|
||||||
#ifndef SWIFT_SYMBOLGRAPHGEN_SYMBOLGRAPHOPTIONS_H
|
#ifndef SWIFT_SYMBOLGRAPHGEN_SYMBOLGRAPHOPTIONS_H
|
||||||
@@ -63,6 +65,10 @@ struct SymbolGraphOptions {
|
|||||||
/// but SourceKit should be able to load the information when pulling symbol
|
/// but SourceKit should be able to load the information when pulling symbol
|
||||||
/// information for individual queries.
|
/// information for individual queries.
|
||||||
bool PrintPrivateStdlibSymbols = false;
|
bool PrintPrivateStdlibSymbols = false;
|
||||||
|
|
||||||
|
/// If this has a value specifies an explicit allow list of reexported module
|
||||||
|
/// names that should be included symbol graph.
|
||||||
|
std::optional<llvm::ArrayRef<StringRef>> AllowedReexportedModules = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace symbolgraphgen
|
} // end namespace symbolgraphgen
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "swift/AST/ExistentialLayout.h"
|
#include "swift/AST/ExistentialLayout.h"
|
||||||
#include "swift/AST/FileUnit.h"
|
#include "swift/AST/FileUnit.h"
|
||||||
#include "swift/AST/GenericEnvironment.h"
|
#include "swift/AST/GenericEnvironment.h"
|
||||||
|
#include "swift/AST/Import.h"
|
||||||
#include "swift/AST/ImportCache.h"
|
#include "swift/AST/ImportCache.h"
|
||||||
#include "swift/AST/LazyResolver.h"
|
#include "swift/AST/LazyResolver.h"
|
||||||
#include "swift/AST/LinkLibrary.h"
|
#include "swift/AST/LinkLibrary.h"
|
||||||
@@ -39,6 +40,7 @@
|
|||||||
#include "swift/AST/ProtocolConformance.h"
|
#include "swift/AST/ProtocolConformance.h"
|
||||||
#include "swift/AST/SourceFile.h"
|
#include "swift/AST/SourceFile.h"
|
||||||
#include "swift/AST/SynthesizedFileUnit.h"
|
#include "swift/AST/SynthesizedFileUnit.h"
|
||||||
|
#include "swift/AST/Type.h"
|
||||||
#include "swift/AST/TypeCheckRequests.h"
|
#include "swift/AST/TypeCheckRequests.h"
|
||||||
#include "swift/Basic/Compiler.h"
|
#include "swift/Basic/Compiler.h"
|
||||||
#include "swift/Basic/SourceManager.h"
|
#include "swift/Basic/SourceManager.h"
|
||||||
@@ -1288,42 +1290,6 @@ bool ModuleDecl::shouldCollectDisplayDecls() const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swift::collectParsedExportedImports(const ModuleDecl *M,
|
|
||||||
SmallPtrSetImpl<ModuleDecl *> &Imports,
|
|
||||||
llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> &QualifiedImports,
|
|
||||||
llvm::function_ref<bool(AttributedImport<ImportedModule>)> includeImport) {
|
|
||||||
for (const FileUnit *file : M->getFiles()) {
|
|
||||||
if (const SourceFile *source = dyn_cast<SourceFile>(file)) {
|
|
||||||
if (source->hasImports()) {
|
|
||||||
for (auto import : source->getImports()) {
|
|
||||||
if (import.options.contains(ImportFlags::Exported) &&
|
|
||||||
(!includeImport || includeImport(import)) &&
|
|
||||||
import.module.importedModule->shouldCollectDisplayDecls()) {
|
|
||||||
auto *TheModule = import.module.importedModule;
|
|
||||||
|
|
||||||
if (import.module.getAccessPath().size() > 0) {
|
|
||||||
if (QualifiedImports.find(TheModule) == QualifiedImports.end()) {
|
|
||||||
QualifiedImports.try_emplace(TheModule);
|
|
||||||
}
|
|
||||||
auto collectDecls = [&](ValueDecl *VD,
|
|
||||||
DeclVisibilityKind reason) {
|
|
||||||
if (reason == DeclVisibilityKind::VisibleAtTopLevel)
|
|
||||||
QualifiedImports[TheModule].insert(VD);
|
|
||||||
};
|
|
||||||
auto consumer = makeDeclConsumer(std::move(collectDecls));
|
|
||||||
TheModule->lookupVisibleDecls(
|
|
||||||
import.module.getAccessPath(), consumer,
|
|
||||||
NLKind::UnqualifiedLookup);
|
|
||||||
} else if (!Imports.contains(TheModule)) {
|
|
||||||
Imports.insert(TheModule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModuleDecl::getLocalTypeDecls(SmallVectorImpl<TypeDecl*> &Results) const {
|
void ModuleDecl::getLocalTypeDecls(SmallVectorImpl<TypeDecl*> &Results) const {
|
||||||
FORWARD(getLocalTypeDecls, (Results));
|
FORWARD(getLocalTypeDecls, (Results));
|
||||||
}
|
}
|
||||||
@@ -1544,41 +1510,102 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const {
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results, bool Recursive) const {
|
void ModuleDecl::ImportCollector::collect(
|
||||||
if (Recursive && isParsedModule(this)) {
|
const ImportedModule &importedModule) {
|
||||||
SmallPtrSet<ModuleDecl *, 4> Modules;
|
auto *module = importedModule.importedModule;
|
||||||
llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> QualifiedImports;
|
|
||||||
collectParsedExportedImports(this, Modules, QualifiedImports);
|
|
||||||
for (const auto &QI : QualifiedImports) {
|
|
||||||
auto Module = QI.getFirst();
|
|
||||||
if (Modules.contains(Module)) continue;
|
|
||||||
|
|
||||||
auto &Decls = QI.getSecond();
|
if (!module->shouldCollectDisplayDecls())
|
||||||
Results.append(Decls.begin(), Decls.end());
|
return;
|
||||||
}
|
|
||||||
for (const ModuleDecl *import : Modules) {
|
if (importFilter && !importFilter(module))
|
||||||
import->getDisplayDecls(Results, Recursive);
|
return;
|
||||||
|
|
||||||
|
if (importedModule.getAccessPath().size() > 0) {
|
||||||
|
auto collectDecls = [&](ValueDecl *VD, DeclVisibilityKind reason) {
|
||||||
|
if (reason == DeclVisibilityKind::VisibleAtTopLevel)
|
||||||
|
this->qualifiedImports[module].insert(VD);
|
||||||
|
};
|
||||||
|
auto consumer = makeDeclConsumer(std::move(collectDecls));
|
||||||
|
module->lookupVisibleDecls(importedModule.getAccessPath(), consumer,
|
||||||
|
NLKind::UnqualifiedLookup);
|
||||||
|
} else {
|
||||||
|
imports.insert(module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
collectExportedImports(const ModuleDecl *module,
|
||||||
|
ModuleDecl::ImportCollector &importCollector) {
|
||||||
|
for (const FileUnit *file : module->getFiles()) {
|
||||||
|
if (const SourceFile *source = dyn_cast<SourceFile>(file)) {
|
||||||
|
if (source->hasImports()) {
|
||||||
|
for (const auto &import : source->getImports()) {
|
||||||
|
if (import.options.contains(ImportFlags::Exported) &&
|
||||||
|
import.docVisibility.value_or(AccessLevel::Public) >=
|
||||||
|
importCollector.minimumDocVisibility) {
|
||||||
|
importCollector.collect(import.module);
|
||||||
|
collectExportedImports(import.module.importedModule,
|
||||||
|
importCollector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SmallVector<ImportedModule, 8> exportedImports;
|
||||||
|
file->getImportedModules(exportedImports,
|
||||||
|
ModuleDecl::ImportFilterKind::Exported);
|
||||||
|
for (const auto &im : exportedImports) {
|
||||||
|
// Skip collecting the underlying clang module as we already have the relevant import.
|
||||||
|
if (module->isClangOverlayOf(im.importedModule))
|
||||||
|
continue;
|
||||||
|
importCollector.collect(im);
|
||||||
|
collectExportedImports(im.importedModule, importCollector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results, bool Recursive) const {
|
||||||
|
if (Recursive) {
|
||||||
|
ImportCollector importCollector;
|
||||||
|
this->getDisplayDeclsRecursivelyAndImports(Results, importCollector);
|
||||||
|
} else {
|
||||||
// FIXME: Should this do extra access control filtering?
|
// FIXME: Should this do extra access control filtering?
|
||||||
FORWARD(getDisplayDecls, (Results));
|
FORWARD(getDisplayDecls, (Results));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleDecl::getDisplayDeclsRecursivelyAndImports(
|
||||||
|
SmallVectorImpl<Decl *> &results, ImportCollector &importCollector) const {
|
||||||
|
this->getDisplayDecls(results, /*Recursive=*/false);
|
||||||
|
|
||||||
|
// Look up imports recursively.
|
||||||
|
collectExportedImports(this, importCollector);
|
||||||
|
for (const auto &QI : importCollector.qualifiedImports) {
|
||||||
|
auto Module = QI.getFirst();
|
||||||
|
if (importCollector.imports.contains(Module))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto &Decls = QI.getSecond();
|
||||||
|
results.append(Decls.begin(), Decls.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ModuleDecl *import : importCollector.imports)
|
||||||
|
import->getDisplayDecls(results);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (Recursive) {
|
|
||||||
llvm::DenseSet<Decl *> visited;
|
llvm::DenseSet<Decl *> visited;
|
||||||
for (auto *D : Results) {
|
for (auto *D : results) {
|
||||||
// decls synthesized from implicit clang decls may appear multiple times;
|
// decls synthesized from implicit clang decls may appear multiple times;
|
||||||
// e.g. if multiple modules with underlying clang modules are re-exported.
|
// e.g. if multiple modules with underlying clang modules are re-exported.
|
||||||
// including duplicates of these is harmless, so skip them when counting
|
// including duplicates of these is harmless, so skip them when counting
|
||||||
// this assertion
|
// this assertion
|
||||||
if (const auto *CD = D->getClangDecl()) {
|
if (const auto *CD = D->getClangDecl()) {
|
||||||
if (CD->isImplicit()) continue;
|
if (CD->isImplicit())
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto inserted = visited.insert(D).second;
|
auto inserted = visited.insert(D).second;
|
||||||
assert(inserted && "there should be no duplicate decls");
|
assert(inserted && "there should be no duplicate decls");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2394,7 +2421,7 @@ ModuleDecl::getDeclaringModuleAndBystander() {
|
|||||||
return *(declaringModuleAndBystander = {nullptr, Identifier()});
|
return *(declaringModuleAndBystander = {nullptr, Identifier()});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModuleDecl::isClangOverlayOf(ModuleDecl *potentialUnderlying) {
|
bool ModuleDecl::isClangOverlayOf(ModuleDecl *potentialUnderlying) const {
|
||||||
return getUnderlyingModuleIfOverlay() == potentialUnderlying;
|
return getUnderlyingModuleIfOverlay() == potentialUnderlying;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,6 +163,13 @@ int swift_symbolgraph_extract_main(ArrayRef<const char *> Args,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SmallVector<StringRef, 4> AllowedRexports;
|
||||||
|
if (auto *A =
|
||||||
|
ParsedArgs.getLastArg(OPT_experimental_allowed_reexported_modules)) {
|
||||||
|
for (const auto *val : A->getValues())
|
||||||
|
AllowedRexports.emplace_back(val);
|
||||||
|
}
|
||||||
|
|
||||||
symbolgraphgen::SymbolGraphOptions Options;
|
symbolgraphgen::SymbolGraphOptions Options;
|
||||||
Options.OutputDir = OutputDir;
|
Options.OutputDir = OutputDir;
|
||||||
Options.Target = Target;
|
Options.Target = Target;
|
||||||
@@ -175,6 +182,7 @@ int swift_symbolgraph_extract_main(ArrayRef<const char *> Args,
|
|||||||
Options.EmitExtensionBlockSymbols =
|
Options.EmitExtensionBlockSymbols =
|
||||||
ParsedArgs.hasFlag(OPT_emit_extension_block_symbols,
|
ParsedArgs.hasFlag(OPT_emit_extension_block_symbols,
|
||||||
OPT_omit_extension_block_symbols, /*default=*/false);
|
OPT_omit_extension_block_symbols, /*default=*/false);
|
||||||
|
Options.AllowedReexportedModules = AllowedRexports;
|
||||||
|
|
||||||
if (auto *A = ParsedArgs.getLastArg(OPT_minimum_access_level)) {
|
if (auto *A = ParsedArgs.getLastArg(OPT_minimum_access_level)) {
|
||||||
Options.MinimumAccessLevel =
|
Options.MinimumAccessLevel =
|
||||||
|
|||||||
@@ -10,9 +10,10 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "swift/Sema/IDETypeChecking.h"
|
||||||
|
#include "swift/AST/ASTContext.h"
|
||||||
#include "swift/AST/ASTDemangler.h"
|
#include "swift/AST/ASTDemangler.h"
|
||||||
#include "swift/AST/ASTPrinter.h"
|
#include "swift/AST/ASTPrinter.h"
|
||||||
#include "swift/AST/ASTContext.h"
|
|
||||||
#include "swift/AST/Attr.h"
|
#include "swift/AST/Attr.h"
|
||||||
#include "swift/AST/Decl.h"
|
#include "swift/AST/Decl.h"
|
||||||
#include "swift/AST/Expr.h"
|
#include "swift/AST/Expr.h"
|
||||||
@@ -25,20 +26,30 @@
|
|||||||
#include "swift/AST/Requirement.h"
|
#include "swift/AST/Requirement.h"
|
||||||
#include "swift/AST/SourceFile.h"
|
#include "swift/AST/SourceFile.h"
|
||||||
#include "swift/AST/Types.h"
|
#include "swift/AST/Types.h"
|
||||||
#include "swift/Sema/IDETypeChecking.h"
|
|
||||||
#include "swift/Sema/IDETypeCheckingRequests.h"
|
|
||||||
#include "swift/IDE/SourceEntityWalker.h"
|
|
||||||
#include "swift/IDE/IDERequests.h"
|
#include "swift/IDE/IDERequests.h"
|
||||||
|
#include "swift/IDE/SourceEntityWalker.h"
|
||||||
#include "swift/Parse/Lexer.h"
|
#include "swift/Parse/Lexer.h"
|
||||||
|
#include "swift/Sema/IDETypeCheckingRequests.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
|
||||||
using namespace swift;
|
using namespace swift;
|
||||||
|
|
||||||
void
|
void swift::getTopLevelDeclsForDisplay(ModuleDecl *M,
|
||||||
swift::getTopLevelDeclsForDisplay(ModuleDecl *M,
|
|
||||||
SmallVectorImpl<Decl *> &Results,
|
SmallVectorImpl<Decl *> &Results,
|
||||||
bool Recursive) {
|
bool Recursive) {
|
||||||
auto startingSize = Results.size();
|
auto getDisplayDeclsForModule =
|
||||||
|
[Recursive](ModuleDecl *M, SmallVectorImpl<Decl *> &Results) {
|
||||||
M->getDisplayDecls(Results, Recursive);
|
M->getDisplayDecls(Results, Recursive);
|
||||||
|
};
|
||||||
|
getTopLevelDeclsForDisplay(M, Results, std::move(getDisplayDeclsForModule));
|
||||||
|
}
|
||||||
|
|
||||||
|
void swift::getTopLevelDeclsForDisplay(
|
||||||
|
ModuleDecl *M, SmallVectorImpl<Decl *> &Results,
|
||||||
|
llvm::function_ref<void(ModuleDecl *, SmallVectorImpl<Decl *> &)>
|
||||||
|
getDisplayDeclsForModule) {
|
||||||
|
auto startingSize = Results.size();
|
||||||
|
getDisplayDeclsForModule(M, Results);
|
||||||
|
|
||||||
// Force Sendable on all public types, which might synthesize some extensions.
|
// Force Sendable on all public types, which might synthesize some extensions.
|
||||||
// FIXME: We can remove this if @_nonSendable stops creating extensions.
|
// FIXME: We can remove this if @_nonSendable stops creating extensions.
|
||||||
@@ -48,8 +59,8 @@ swift::getTopLevelDeclsForDisplay(ModuleDecl *M,
|
|||||||
// Restrict this logic to public and package types. Non-public types
|
// Restrict this logic to public and package types. Non-public types
|
||||||
// may refer to implementation details and fail at deserialization.
|
// may refer to implementation details and fail at deserialization.
|
||||||
auto accessScope = NTD->getFormalAccessScope();
|
auto accessScope = NTD->getFormalAccessScope();
|
||||||
if (!M->isMainModule() &&
|
if (!M->isMainModule() && !accessScope.isPublic() &&
|
||||||
!accessScope.isPublic() && !accessScope.isPackage())
|
!accessScope.isPackage())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto proto = M->getASTContext().getProtocol(KnownProtocolKind::Sendable);
|
auto proto = M->getASTContext().getProtocol(KnownProtocolKind::Sendable);
|
||||||
@@ -61,7 +72,7 @@ swift::getTopLevelDeclsForDisplay(ModuleDecl *M,
|
|||||||
// Remove what we fetched and fetch again, possibly now with additional
|
// Remove what we fetched and fetch again, possibly now with additional
|
||||||
// extensions.
|
// extensions.
|
||||||
Results.resize(startingSize);
|
Results.resize(startingSize);
|
||||||
M->getDisplayDecls(Results, Recursive);
|
getDisplayDeclsForModule(M, Results);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool shouldPrintAsFavorable(const Decl *D, const PrintOptions &Options) {
|
static bool shouldPrintAsFavorable(const Decl *D, const PrintOptions &Options) {
|
||||||
|
|||||||
@@ -43,9 +43,14 @@ bool areModulesEqual(const ModuleDecl *lhs, const ModuleDecl *rhs, bool isClangE
|
|||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
SymbolGraphASTWalker::SymbolGraphASTWalker(ModuleDecl &M,
|
||||||
|
const SymbolGraphOptions &Options)
|
||||||
|
: Options(Options), M(M), MainGraph(*this, M, std::nullopt, Ctx) {}
|
||||||
|
|
||||||
SymbolGraphASTWalker::SymbolGraphASTWalker(
|
SymbolGraphASTWalker::SymbolGraphASTWalker(
|
||||||
ModuleDecl &M, const SmallPtrSet<ModuleDecl *, 4> ExportedImportedModules,
|
ModuleDecl &M,
|
||||||
const llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4>
|
const SmallPtrSet<const ModuleDecl *, 4> ExportedImportedModules,
|
||||||
|
const llvm::SmallDenseMap<const ModuleDecl *, SmallPtrSet<Decl *, 4>, 4>
|
||||||
QualifiedExportedImports,
|
QualifiedExportedImports,
|
||||||
const SymbolGraphOptions &Options)
|
const SymbolGraphOptions &Options)
|
||||||
: Options(Options), M(M), ExportedImportedModules(ExportedImportedModules),
|
: Options(Options), M(M), ExportedImportedModules(ExportedImportedModules),
|
||||||
|
|||||||
@@ -48,9 +48,10 @@ struct SymbolGraphASTWalker : public SourceEntityWalker {
|
|||||||
const ModuleDecl &M;
|
const ModuleDecl &M;
|
||||||
|
|
||||||
// FIXME: these should be tracked per-graph, rather than at the top level
|
// FIXME: these should be tracked per-graph, rather than at the top level
|
||||||
const SmallPtrSet<ModuleDecl *, 4> ExportedImportedModules;
|
const SmallPtrSet<const ModuleDecl *, 4> ExportedImportedModules;
|
||||||
|
|
||||||
const llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> QualifiedExportedImports;
|
const llvm::SmallDenseMap<const ModuleDecl *, SmallPtrSet<Decl *, 4>, 4>
|
||||||
|
QualifiedExportedImports;
|
||||||
|
|
||||||
/// The symbol graph for the main module of interest.
|
/// The symbol graph for the main module of interest.
|
||||||
SymbolGraph MainGraph;
|
SymbolGraph MainGraph;
|
||||||
@@ -60,10 +61,14 @@ struct SymbolGraphASTWalker : public SourceEntityWalker {
|
|||||||
|
|
||||||
// MARK: - Initialization
|
// MARK: - Initialization
|
||||||
|
|
||||||
SymbolGraphASTWalker(ModuleDecl &M,
|
SymbolGraphASTWalker(
|
||||||
const SmallPtrSet<ModuleDecl *, 4> ExportedImportedModules,
|
ModuleDecl &M,
|
||||||
const llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> QualifiedExportedImports,
|
const SmallPtrSet<const ModuleDecl *, 4> ExportedImportedModules,
|
||||||
|
const llvm::SmallDenseMap<const ModuleDecl *, SmallPtrSet<Decl *, 4>, 4>
|
||||||
|
QualifiedExportedImports,
|
||||||
const SymbolGraphOptions &Options);
|
const SymbolGraphOptions &Options);
|
||||||
|
|
||||||
|
SymbolGraphASTWalker(ModuleDecl &M, const SymbolGraphOptions &Options);
|
||||||
virtual ~SymbolGraphASTWalker() {}
|
virtual ~SymbolGraphASTWalker() {}
|
||||||
|
|
||||||
// MARK: - Utilities
|
// MARK: - Utilities
|
||||||
|
|||||||
@@ -10,12 +10,16 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Support/JSON.h"
|
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
|
||||||
#include "llvm/Support/Path.h"
|
|
||||||
#include "swift/AST/ASTContext.h"
|
#include "swift/AST/ASTContext.h"
|
||||||
#include "swift/AST/FileSystem.h"
|
#include "swift/AST/FileSystem.h"
|
||||||
|
#include "swift/AST/Import.h"
|
||||||
|
#include "swift/AST/Module.h"
|
||||||
|
#include "swift/AST/NameLookup.h"
|
||||||
#include "swift/Sema/IDETypeChecking.h"
|
#include "swift/Sema/IDETypeChecking.h"
|
||||||
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include "llvm/Support/JSON.h"
|
||||||
|
#include "llvm/Support/Path.h"
|
||||||
|
|
||||||
#include "SymbolGraphASTWalker.h"
|
#include "SymbolGraphASTWalker.h"
|
||||||
|
|
||||||
@@ -54,25 +58,36 @@ int serializeSymbolGraph(SymbolGraph &SG,
|
|||||||
// MARK: - Main Entry Point
|
// MARK: - Main Entry Point
|
||||||
|
|
||||||
/// Emit a symbol graph JSON file for a `ModuleDecl`.
|
/// Emit a symbol graph JSON file for a `ModuleDecl`.
|
||||||
int
|
int symbolgraphgen::emitSymbolGraphForModule(
|
||||||
symbolgraphgen::emitSymbolGraphForModule(ModuleDecl *M,
|
ModuleDecl *M, const SymbolGraphOptions &Options) {
|
||||||
const SymbolGraphOptions &Options) {
|
ModuleDecl::ImportCollector importCollector(Options.MinimumAccessLevel);
|
||||||
SmallVector<Decl *, 64> ModuleDecls;
|
|
||||||
swift::getTopLevelDeclsForDisplay(M, ModuleDecls, /*recursive*/true);
|
|
||||||
|
|
||||||
SmallPtrSet<ModuleDecl *, 4> ExportedImportedModules;
|
auto importFilter = [&Options](const ModuleDecl *module) {
|
||||||
llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> QualifiedImports;
|
if (!module)
|
||||||
auto shouldIncludeImport = [&](AttributedImport<ImportedModule> import) {
|
return false;
|
||||||
auto docVisibility = import.docVisibility.value_or(AccessLevel::Public);
|
|
||||||
return docVisibility >= Options.MinimumAccessLevel;
|
for (const auto &allowedModuleName : *Options.AllowedReexportedModules)
|
||||||
|
if (allowedModuleName == module->getNameStr())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
swift::collectParsedExportedImports(M, ExportedImportedModules, QualifiedImports, shouldIncludeImport);
|
|
||||||
|
if (Options.AllowedReexportedModules.has_value())
|
||||||
|
importCollector.importFilter = std::move(importFilter);
|
||||||
|
|
||||||
|
SmallVector<Decl *, 64> ModuleDecls;
|
||||||
|
swift::getTopLevelDeclsForDisplay(
|
||||||
|
M, ModuleDecls, [&importCollector](ModuleDecl *M, SmallVectorImpl<Decl *> &results) {
|
||||||
|
M->getDisplayDeclsRecursivelyAndImports(results, importCollector);
|
||||||
|
});
|
||||||
|
|
||||||
if (Options.PrintMessages)
|
if (Options.PrintMessages)
|
||||||
llvm::errs() << ModuleDecls.size()
|
llvm::errs() << ModuleDecls.size()
|
||||||
<< " top-level declarations in this module.\n";
|
<< " top-level declarations in this module.\n";
|
||||||
|
|
||||||
SymbolGraphASTWalker Walker(*M, ExportedImportedModules, QualifiedImports, Options);
|
SymbolGraphASTWalker Walker(*M, importCollector.imports,
|
||||||
|
importCollector.qualifiedImports, Options);
|
||||||
|
|
||||||
for (auto *Decl : ModuleDecls) {
|
for (auto *Decl : ModuleDecls) {
|
||||||
Walker.walk(Decl);
|
Walker.walk(Decl);
|
||||||
@@ -109,8 +124,7 @@ printSymbolGraphForDecl(const ValueDecl *D, Type BaseTy,
|
|||||||
|
|
||||||
llvm::json::OStream JOS(OS, Options.PrettyPrint ? 2 : 0);
|
llvm::json::OStream JOS(OS, Options.PrettyPrint ? 2 : 0);
|
||||||
ModuleDecl *MD = D->getModuleContext();
|
ModuleDecl *MD = D->getModuleContext();
|
||||||
llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> QualifiedImports;
|
SymbolGraphASTWalker Walker(*MD, Options);
|
||||||
SymbolGraphASTWalker Walker(*MD, {}, QualifiedImports, Options);
|
|
||||||
markup::MarkupContext MarkupCtx;
|
markup::MarkupContext MarkupCtx;
|
||||||
SymbolGraph Graph(Walker, *MD, std::nullopt, MarkupCtx, std::nullopt,
|
SymbolGraph Graph(Walker, *MD, std::nullopt, MarkupCtx, std::nullopt,
|
||||||
/*IsForSingleNode=*/true);
|
/*IsForSingleNode=*/true);
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
// RUN: %empty-directory(%t)
|
// RUN: %empty-directory(%t)
|
||||||
|
// RUN: %empty-directory(%t/module-generated)
|
||||||
// RUN: cp -r %S/Inputs/ExportedImport/ObjcProperty.framework %t
|
// RUN: cp -r %S/Inputs/ExportedImport/ObjcProperty.framework %t
|
||||||
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop -emit-module -o %t/ObjcProperty.framework/Modules/ObjcProperty.swiftmodule/%target-swiftmodule-name -import-underlying-module -F %t -module-name ObjcProperty %S/Inputs/ExportedImport/A.swift
|
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop -emit-module -o %t/ObjcProperty.framework/Modules/ObjcProperty.swiftmodule/%target-swiftmodule-name -import-underlying-module -F %t -module-name ObjcProperty %S/Inputs/ExportedImport/A.swift
|
||||||
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop -emit-module -o %t/ExportedImport.swiftmodule -F %t -module-name ExportedImport %s -emit-symbol-graph -emit-symbol-graph-dir %t
|
// RUN: %target-swift-frontend -emit-module -o %t/ExportedImport.swiftmodule -F %t -module-name ExportedImport %s -emit-symbol-graph -emit-symbol-graph-dir %t
|
||||||
// RUN: %FileCheck %s --input-file %t/ExportedImport.symbols.json
|
// RUN: %FileCheck %s --input-file %t/ExportedImport.symbols.json
|
||||||
|
// RUN: %target-swift-symbolgraph-extract -sdk %clang-importer-sdk -module-name ExportedImport -I %t \
|
||||||
|
// RUN: -output-dir %t/module-generated/ -experimental-allowed-reexported-modules=ObjcProperty
|
||||||
|
// RUN: %FileCheck %s --input-file %t/module-generated/ExportedImport.symbols.json
|
||||||
|
|
||||||
// REQUIRES: objc_interop
|
// REQUIRES: objc_interop
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,8 @@
|
|||||||
// INTERNAL-DAG: "precise":"s:1A11SymbolFromAV"
|
// INTERNAL-DAG: "precise":"s:1A11SymbolFromAV"
|
||||||
// INTERNAL-DAG: "precise":"s:1B9StructOneV"
|
// INTERNAL-DAG: "precise":"s:1B9StructOneV"
|
||||||
|
|
||||||
// FIXME: Symbols from `@_exported import` do not get emitted when using swift-symbolgraph-extract
|
// FIXME: Functionality doesn't currently work swift-symbolgraph-extract as documentation visibility attribute isn't
|
||||||
// This is tracked by https://github.com/apple/swift-docc/issues/179.
|
// exposed in the module interface
|
||||||
|
|
||||||
// FILES-NOT: DocAttrExportedImport@A.symbols.json
|
// FILES-NOT: DocAttrExportedImport@A.symbols.json
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
// RUN: %empty-directory(%t)
|
// RUN: %empty-directory(%t)
|
||||||
|
// RUN: %empty-directory(%t/module-generated)
|
||||||
// RUN: %target-swift-frontend %S/Inputs/DuplicateExportedImport/A.swift -module-name A -emit-module -emit-module-path %t/A.swiftmodule
|
// RUN: %target-swift-frontend %S/Inputs/DuplicateExportedImport/A.swift -module-name A -emit-module -emit-module-path %t/A.swiftmodule
|
||||||
// RUN: %target-swift-frontend %s -module-name DuplicateExportedImport -emit-module -emit-module-path /dev/null -I %t -emit-symbol-graph -emit-symbol-graph-dir %t/
|
// RUN: %target-swift-frontend %s -module-name DuplicateExportedImport -emit-module -emit-module-path \
|
||||||
|
// RUN: %t/DuplicateExportedImport.swiftmodule -I %t -emit-symbol-graph -emit-symbol-graph-dir %t/
|
||||||
// RUN: %FileCheck %s --input-file %t/DuplicateExportedImport.symbols.json
|
// RUN: %FileCheck %s --input-file %t/DuplicateExportedImport.symbols.json
|
||||||
|
// RUN: %target-swift-symbolgraph-extract -module-name DuplicateExportedImport -I %t -output-dir %t/module-generated/ \
|
||||||
|
// RUN: -experimental-allowed-reexported-modules=A
|
||||||
|
// RUN: %FileCheck %s --input-file %t/module-generated/DuplicateExportedImport.symbols.json
|
||||||
|
|
||||||
// REQUIRES: asserts
|
// REQUIRES: asserts
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
// RUN: %empty-directory(%t)
|
// RUN: %empty-directory(%t)
|
||||||
|
// RUN: %empty-directory(%t/module-generated)
|
||||||
// RUN: %target-swift-frontend %S/Inputs/ExportedImport/A.swift -module-name A -emit-module -emit-module-path %t/A.swiftmodule
|
// RUN: %target-swift-frontend %S/Inputs/ExportedImport/A.swift -module-name A -emit-module -emit-module-path %t/A.swiftmodule
|
||||||
// RUN: %target-swift-frontend %S/Inputs/ExportedImport/B.swift -module-name B -emit-module -emit-module-path %t/B.swiftmodule
|
// RUN: %target-swift-frontend %S/Inputs/ExportedImport/B.swift -module-name B -emit-module -emit-module-path %t/B.swiftmodule
|
||||||
// RUN: %target-swift-frontend %s -module-name ExportedImport -emit-module -emit-module-path /dev/null -I %t -emit-symbol-graph -emit-symbol-graph-dir %t/
|
// RUN: %target-swift-frontend %s -module-name ExportedImport -emit-module -emit-module-path \
|
||||||
|
// RUN: %t/ExportedImport.swiftmodule -I %t -emit-symbol-graph -emit-symbol-graph-dir %t/
|
||||||
// RUN: %FileCheck %s --input-file %t/ExportedImport.symbols.json
|
// RUN: %FileCheck %s --input-file %t/ExportedImport.symbols.json
|
||||||
|
// RUN: %target-swift-symbolgraph-extract -module-name ExportedImport -I %t -output-dir \
|
||||||
|
// RUN: %t/module-generated/ -experimental-allowed-reexported-modules=A,B
|
||||||
|
// RUN: %FileCheck %s --input-file %t/module-generated/ExportedImport.symbols.json
|
||||||
// RUN: ls %t | %FileCheck %s --check-prefix FILES
|
// RUN: ls %t | %FileCheck %s --check-prefix FILES
|
||||||
|
// RUN: ls %t/module-generated/ | %FileCheck %s --check-prefix FILES
|
||||||
|
|
||||||
@_exported import A
|
@_exported import A
|
||||||
@_exported import struct B.StructOne
|
@_exported import struct B.StructOne
|
||||||
@@ -13,7 +19,4 @@
|
|||||||
// CHECK-DAG: "precise":"s:1A11SymbolFromAV"
|
// CHECK-DAG: "precise":"s:1A11SymbolFromAV"
|
||||||
// CHECK-DAG: "precise":"s:1B9StructOneV"
|
// CHECK-DAG: "precise":"s:1B9StructOneV"
|
||||||
|
|
||||||
// FIXME: Symbols from `@_exported import` do not get emitted when using swift-symbolgraph-extract
|
|
||||||
// This is tracked by https://github.com/apple/swift-docc/issues/179.
|
|
||||||
|
|
||||||
// FILES-NOT: ExportedImport@A.symbols.json
|
// FILES-NOT: ExportedImport@A.symbols.json
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
// RUN: %empty-directory(%t)
|
// RUN: %empty-directory(%t)
|
||||||
|
// RUN: %empty-directory(%t/module-generated)
|
||||||
// RUN: %target-swift-frontend %S/Inputs/ExportedImportExtensions/A.swift -module-name A -emit-module -emit-module-path %t/A.swiftmodule
|
// RUN: %target-swift-frontend %S/Inputs/ExportedImportExtensions/A.swift -module-name A -emit-module -emit-module-path %t/A.swiftmodule
|
||||||
// RUN: %target-swift-frontend %S/Inputs/ExportedImportExtensions/B.swift -module-name B -emit-module -emit-module-path %t/B.swiftmodule -I %t
|
// RUN: %target-swift-frontend %S/Inputs/ExportedImportExtensions/B.swift -module-name B -emit-module -emit-module-path %t/B.swiftmodule -I %t
|
||||||
// RUN: %target-swift-frontend %s -module-name ExportedImportExtensions -emit-module -emit-module-path /dev/null -I %t -emit-symbol-graph -emit-symbol-graph-dir %t/ -emit-extension-block-symbols
|
// RUN: %target-swift-frontend %s -module-name ExportedImportExtensions -emit-module -emit-module-path \
|
||||||
|
// RUN: %t/ExportedImportExtensions.swiftmodule -I %t -emit-symbol-graph -emit-symbol-graph-dir %t/ -emit-extension-block-symbols
|
||||||
// RUN: %FileCheck %s --input-file %t/ExportedImportExtensions.symbols.json
|
// RUN: %FileCheck %s --input-file %t/ExportedImportExtensions.symbols.json
|
||||||
|
// RUN: %target-swift-symbolgraph-extract -module-name ExportedImportExtensions -I %t -output-dir %t/module-generated/ \
|
||||||
|
// RUN: -emit-extension-block-symbols -experimental-allowed-reexported-modules=A,B
|
||||||
|
// RUN: %FileCheck %s --input-file %t/module-generated/ExportedImportExtensions.symbols.json
|
||||||
// RUN: ls %t | %FileCheck %s --check-prefix FILES
|
// RUN: ls %t | %FileCheck %s --check-prefix FILES
|
||||||
|
// RUN: ls %t/module-generated/ | %FileCheck %s --check-prefix FILES
|
||||||
|
|
||||||
@_exported import A
|
@_exported import A
|
||||||
@_exported import B
|
@_exported import B
|
||||||
@@ -45,9 +51,6 @@ extension SymbolFromB: P {
|
|||||||
// CHECK-DAG: {"kind":"memberOf","source":"s:1B11SymbolFromBV24ExportedImportExtensionsE12pRequirementyyF","target":"s:1B11SymbolFromBV","targetFallback":"B.SymbolFromB","sourceOrigin":{"identifier":"s:24ExportedImportExtensions1PP12pRequirementyyF","displayName":"P.pRequirement()"}}
|
// CHECK-DAG: {"kind":"memberOf","source":"s:1B11SymbolFromBV24ExportedImportExtensionsE12pRequirementyyF","target":"s:1B11SymbolFromBV","targetFallback":"B.SymbolFromB","sourceOrigin":{"identifier":"s:24ExportedImportExtensions1PP12pRequirementyyF","displayName":"P.pRequirement()"}}
|
||||||
// CHECK-DAG: {"kind":"conformsTo","source":"s:1B11SymbolFromBV","target":"s:24ExportedImportExtensions1PP"}
|
// CHECK-DAG: {"kind":"conformsTo","source":"s:1B11SymbolFromBV","target":"s:24ExportedImportExtensions1PP"}
|
||||||
|
|
||||||
// FIXME: Symbols from `@_exported import` do not get emitted when using swift-symbolgraph-extract
|
|
||||||
// This is tracked by https://github.com/apple/swift-docc/issues/179.
|
|
||||||
|
|
||||||
// FILES-NOT: ExportedImportExtensions@A.symbols.json
|
// FILES-NOT: ExportedImportExtensions@A.symbols.json
|
||||||
// FILES-NOT: ExportedImportExtensions@B.symbols.json
|
// FILES-NOT: ExportedImportExtensions@B.symbols.json
|
||||||
// FILES-NOT: A@B.symbols.json
|
// FILES-NOT: A@B.symbols.json
|
||||||
|
|||||||
29
test/SymbolGraph/Module/NestedExportedImport.swift
Normal file
29
test/SymbolGraph/Module/NestedExportedImport.swift
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// RUN: %empty-directory(%t)
|
||||||
|
// RUN: %empty-directory(%t/module-generated)
|
||||||
|
// RUN: split-file %s %t
|
||||||
|
// RUN: %target-swift-frontend %t/A.swift -module-name A -emit-module -emit-module-path %t/A.swiftmodule
|
||||||
|
// RUN: %target-swift-frontend %t/B.swift -module-name B -emit-module -emit-module-path %t/B.swiftmodule -I %t
|
||||||
|
// RUN: %target-swift-frontend %t/C.swift -module-name C -emit-module -emit-module-path %t/C.swiftmodule -I %t \
|
||||||
|
// RUN: -emit-symbol-graph -emit-symbol-graph-dir %t
|
||||||
|
// RUN: %target-swift-symbolgraph-extract -module-name C -I %t -output-dir \
|
||||||
|
// RUN: %t/module-generated/ -experimental-allowed-reexported-modules=A,B
|
||||||
|
// RUN: %FileCheck %s --input-file %t/C.symbols.json
|
||||||
|
// RUN: %FileCheck %s --input-file %t/module-generated/C.symbols.json
|
||||||
|
|
||||||
|
//--- A.swift
|
||||||
|
public struct A {}
|
||||||
|
public func AFunc() -> Void {}
|
||||||
|
|
||||||
|
//--- B.swift
|
||||||
|
@_exported import A
|
||||||
|
public struct B {}
|
||||||
|
public func BFunc() -> Void {}
|
||||||
|
|
||||||
|
//--- C.swift
|
||||||
|
@_exported import B
|
||||||
|
public struct C {}
|
||||||
|
public func CFunc() -> Void {}
|
||||||
|
|
||||||
|
// CHECK-DAG: "precise":"s:1CAAV"
|
||||||
|
// CHECK-DAG: "precise":"s:1BAAV"
|
||||||
|
// CHECK-DAG: "precise":"s:1AAAV"
|
||||||
Reference in New Issue
Block a user