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:
Daniel Grumberg
2024-05-02 15:39:26 +01:00
committed by GitHub
16 changed files with 271 additions and 125 deletions

View File

@@ -18,6 +18,7 @@
#define SWIFT_MODULE_H
#include "swift/AST/AccessNotes.h"
#include "swift/AST/AttrKind.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DeclContext.h"
#include "swift/AST/Identifier.h"
@@ -551,7 +552,7 @@ public:
ModuleDecl *getUnderlyingModuleIfOverlay() const;
/// 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
/// overlay of the other.
@@ -1094,6 +1095,24 @@ public:
/// for that.
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)>;
/// 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));
}
/// 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,
/// emit a diagnostic and a fix-it suggesting adding the missing import.
bool diagnoseMissingImportForMember(const ValueDecl *decl,

View File

@@ -1573,6 +1573,10 @@ def output_dir : Separate<["-"], "output-dir">,
HelpText<"Output directory">,
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">,
Flags<[NoDriverOption, SwiftSymbolGraphExtractOption]>,
HelpText<"Skip members inherited through classes or default implementations">;

View File

@@ -162,6 +162,15 @@ namespace swift {
void
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 {
// The extension with the declarations to apply.
ExtensionDecl *Ext;

View File

@@ -11,6 +11,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/TargetParser/Triple.h"
#include "llvm/ADT/ArrayRef.h"
#include "swift/AST/AttrKind.h"
#ifndef SWIFT_SYMBOLGRAPHGEN_SYMBOLGRAPHOPTIONS_H
@@ -63,6 +65,10 @@ struct SymbolGraphOptions {
/// but SourceKit should be able to load the information when pulling symbol
/// information for individual queries.
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

View File

@@ -26,6 +26,7 @@
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/FileUnit.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Import.h"
#include "swift/AST/ImportCache.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/LinkLibrary.h"
@@ -39,6 +40,7 @@
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/SynthesizedFileUnit.h"
#include "swift/AST/Type.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Compiler.h"
#include "swift/Basic/SourceManager.h"
@@ -1288,42 +1290,6 @@ bool ModuleDecl::shouldCollectDisplayDecls() const {
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 {
FORWARD(getLocalTypeDecls, (Results));
}
@@ -1544,41 +1510,102 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const {
return Result;
}
void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results, bool Recursive) const {
if (Recursive && isParsedModule(this)) {
SmallPtrSet<ModuleDecl *, 4> Modules;
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;
void ModuleDecl::ImportCollector::collect(
const ImportedModule &importedModule) {
auto *module = importedModule.importedModule;
auto &Decls = QI.getSecond();
Results.append(Decls.begin(), Decls.end());
if (!module->shouldCollectDisplayDecls())
return;
if (importFilter && !importFilter(module))
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);
}
for (const ModuleDecl *import : Modules) {
import->getDisplayDecls(Results, Recursive);
}
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?
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
if (Recursive) {
llvm::DenseSet<Decl *> visited;
for (auto *D : Results) {
for (auto *D : results) {
// decls synthesized from implicit clang decls may appear multiple times;
// e.g. if multiple modules with underlying clang modules are re-exported.
// including duplicates of these is harmless, so skip them when counting
// this assertion
if (const auto *CD = D->getClangDecl()) {
if (CD->isImplicit()) continue;
if (CD->isImplicit())
continue;
}
auto inserted = visited.insert(D).second;
assert(inserted && "there should be no duplicate decls");
}
}
#endif
}
@@ -2394,7 +2421,7 @@ ModuleDecl::getDeclaringModuleAndBystander() {
return *(declaringModuleAndBystander = {nullptr, Identifier()});
}
bool ModuleDecl::isClangOverlayOf(ModuleDecl *potentialUnderlying) {
bool ModuleDecl::isClangOverlayOf(ModuleDecl *potentialUnderlying) const {
return getUnderlyingModuleIfOverlay() == potentialUnderlying;
}

View File

@@ -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;
Options.OutputDir = OutputDir;
Options.Target = Target;
@@ -175,6 +182,7 @@ int swift_symbolgraph_extract_main(ArrayRef<const char *> Args,
Options.EmitExtensionBlockSymbols =
ParsedArgs.hasFlag(OPT_emit_extension_block_symbols,
OPT_omit_extension_block_symbols, /*default=*/false);
Options.AllowedReexportedModules = AllowedRexports;
if (auto *A = ParsedArgs.getLastArg(OPT_minimum_access_level)) {
Options.MinimumAccessLevel =

View File

@@ -10,9 +10,10 @@
//
//===----------------------------------------------------------------------===//
#include "swift/Sema/IDETypeChecking.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTDemangler.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Attr.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
@@ -25,20 +26,30 @@
#include "swift/AST/Requirement.h"
#include "swift/AST/SourceFile.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/SourceEntityWalker.h"
#include "swift/Parse/Lexer.h"
#include "swift/Sema/IDETypeCheckingRequests.h"
#include "llvm/ADT/SmallVector.h"
using namespace swift;
void
swift::getTopLevelDeclsForDisplay(ModuleDecl *M,
SmallVectorImpl<Decl*> &Results,
void swift::getTopLevelDeclsForDisplay(ModuleDecl *M,
SmallVectorImpl<Decl *> &Results,
bool Recursive) {
auto startingSize = Results.size();
auto getDisplayDeclsForModule =
[Recursive](ModuleDecl *M, SmallVectorImpl<Decl *> &Results) {
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.
// FIXME: We can remove this if @_nonSendable stops creating extensions.
@@ -48,20 +59,20 @@ swift::getTopLevelDeclsForDisplay(ModuleDecl *M,
// Restrict this logic to public and package types. Non-public types
// may refer to implementation details and fail at deserialization.
auto accessScope = NTD->getFormalAccessScope();
if (!M->isMainModule() &&
!accessScope.isPublic() && !accessScope.isPackage())
if (!M->isMainModule() && !accessScope.isPublic() &&
!accessScope.isPackage())
continue;
auto proto = M->getASTContext().getProtocol(KnownProtocolKind::Sendable);
if (proto)
(void) M->lookupConformance(NTD->getDeclaredInterfaceType(), proto);
(void)M->lookupConformance(NTD->getDeclaredInterfaceType(), proto);
}
}
// Remove what we fetched and fetch again, possibly now with additional
// extensions.
Results.resize(startingSize);
M->getDisplayDecls(Results, Recursive);
getDisplayDeclsForModule(M, Results);
}
static bool shouldPrintAsFavorable(const Decl *D, const PrintOptions &Options) {

View File

@@ -43,9 +43,14 @@ bool areModulesEqual(const ModuleDecl *lhs, const ModuleDecl *rhs, bool isClangE
} // anonymous namespace
SymbolGraphASTWalker::SymbolGraphASTWalker(ModuleDecl &M,
const SymbolGraphOptions &Options)
: Options(Options), M(M), MainGraph(*this, M, std::nullopt, Ctx) {}
SymbolGraphASTWalker::SymbolGraphASTWalker(
ModuleDecl &M, const SmallPtrSet<ModuleDecl *, 4> ExportedImportedModules,
const llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4>
ModuleDecl &M,
const SmallPtrSet<const ModuleDecl *, 4> ExportedImportedModules,
const llvm::SmallDenseMap<const ModuleDecl *, SmallPtrSet<Decl *, 4>, 4>
QualifiedExportedImports,
const SymbolGraphOptions &Options)
: Options(Options), M(M), ExportedImportedModules(ExportedImportedModules),

View File

@@ -48,9 +48,10 @@ struct SymbolGraphASTWalker : public SourceEntityWalker {
const ModuleDecl &M;
// 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.
SymbolGraph MainGraph;
@@ -60,10 +61,14 @@ struct SymbolGraphASTWalker : public SourceEntityWalker {
// MARK: - Initialization
SymbolGraphASTWalker(ModuleDecl &M,
const SmallPtrSet<ModuleDecl *, 4> ExportedImportedModules,
const llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> QualifiedExportedImports,
SymbolGraphASTWalker(
ModuleDecl &M,
const SmallPtrSet<const ModuleDecl *, 4> ExportedImportedModules,
const llvm::SmallDenseMap<const ModuleDecl *, SmallPtrSet<Decl *, 4>, 4>
QualifiedExportedImports,
const SymbolGraphOptions &Options);
SymbolGraphASTWalker(ModuleDecl &M, const SymbolGraphOptions &Options);
virtual ~SymbolGraphASTWalker() {}
// MARK: - Utilities

View File

@@ -10,12 +10,16 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/JSON.h"
#include "llvm/Support/Path.h"
#include "swift/SymbolGraphGen/SymbolGraphGen.h"
#include "swift/AST/ASTContext.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/SymbolGraphGen/SymbolGraphGen.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Path.h"
#include "SymbolGraphASTWalker.h"
@@ -54,25 +58,36 @@ int serializeSymbolGraph(SymbolGraph &SG,
// MARK: - Main Entry Point
/// Emit a symbol graph JSON file for a `ModuleDecl`.
int
symbolgraphgen::emitSymbolGraphForModule(ModuleDecl *M,
const SymbolGraphOptions &Options) {
SmallVector<Decl *, 64> ModuleDecls;
swift::getTopLevelDeclsForDisplay(M, ModuleDecls, /*recursive*/true);
int symbolgraphgen::emitSymbolGraphForModule(
ModuleDecl *M, const SymbolGraphOptions &Options) {
ModuleDecl::ImportCollector importCollector(Options.MinimumAccessLevel);
SmallPtrSet<ModuleDecl *, 4> ExportedImportedModules;
llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> QualifiedImports;
auto shouldIncludeImport = [&](AttributedImport<ImportedModule> import) {
auto docVisibility = import.docVisibility.value_or(AccessLevel::Public);
return docVisibility >= Options.MinimumAccessLevel;
auto importFilter = [&Options](const ModuleDecl *module) {
if (!module)
return false;
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)
llvm::errs() << ModuleDecls.size()
<< " 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) {
Walker.walk(Decl);
@@ -109,8 +124,7 @@ printSymbolGraphForDecl(const ValueDecl *D, Type BaseTy,
llvm::json::OStream JOS(OS, Options.PrettyPrint ? 2 : 0);
ModuleDecl *MD = D->getModuleContext();
llvm::SmallDenseMap<ModuleDecl *, SmallPtrSet<Decl *, 4>, 4> QualifiedImports;
SymbolGraphASTWalker Walker(*MD, {}, QualifiedImports, Options);
SymbolGraphASTWalker Walker(*MD, Options);
markup::MarkupContext MarkupCtx;
SymbolGraph Graph(Walker, *MD, std::nullopt, MarkupCtx, std::nullopt,
/*IsForSingleNode=*/true);

View File

@@ -1,8 +1,12 @@
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/module-generated)
// 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/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: %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

View File

@@ -23,8 +23,8 @@
// INTERNAL-DAG: "precise":"s:1A11SymbolFromAV"
// INTERNAL-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.
// FIXME: Functionality doesn't currently work swift-symbolgraph-extract as documentation visibility attribute isn't
// exposed in the module interface
// FILES-NOT: DocAttrExportedImport@A.symbols.json

View File

@@ -1,7 +1,12 @@
// 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 -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: %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

View File

@@ -1,9 +1,15 @@
// 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/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: %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/module-generated/ | %FileCheck %s --check-prefix FILES
@_exported import A
@_exported import struct B.StructOne
@@ -13,7 +19,4 @@
// CHECK-DAG: "precise":"s:1A11SymbolFromAV"
// 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

View File

@@ -1,9 +1,15 @@
// 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/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: %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/module-generated/ | %FileCheck %s --check-prefix FILES
@_exported import A
@_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":"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@B.symbols.json
// FILES-NOT: A@B.symbols.json

View 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"