Skip to content

Commit 34098a7

Browse files
author
Nathan Hawes
committed
[IDE][DocSupport] Fix DocInfo missing decls when generated for clang submodules.
Out handling of clang submodules was handled differently between DocInfo and InterfaceGen. For InterfaceGen submodules were mapped back to their top-level clang modules (or their Swift overlay if it had one) before being passed into printSubmoduleInterface, along with the dot separated name of the submodule. For DocInfo, they were not, and only the rightmost component of their name was passed. The call to retrieve the decls from a ModuleDecl doesn't work if the ModuleDecl wraps a clang submodule, so we were missing these decls. InterfaceGen for submodules also shouldn't have been mapping the module back to the overlay of top-level clang module, as that meant we ended up printing import decls from the Swift overlay in the submodule's interface. Resolves rdar://problem/57338105
1 parent 5239668 commit 34098a7

File tree

9 files changed

+545
-236
lines changed

9 files changed

+545
-236
lines changed

include/swift/IDE/ModuleInterfacePrinting.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,11 @@ bool printTypeInterface(ModuleDecl *M, Type Ty, ASTPrinter &Printer,
5454
bool printTypeInterface(ModuleDecl *M, StringRef TypeUSR, ASTPrinter &Printer,
5555
std::string &TypeName, std::string &Error);
5656

57-
void printModuleInterface(ModuleDecl *M, Optional<StringRef> Group,
57+
void printModuleInterface(ModuleDecl *M, ArrayRef<StringRef> GroupNames,
5858
ModuleTraversalOptions TraversalOptions,
5959
ASTPrinter &Printer, const PrintOptions &Options,
6060
const bool PrintSynthesizedExtensions);
6161

62-
// FIXME: this API should go away when Swift can represent Clang submodules as
63-
// 'swift::ModuleDecl *' objects.
64-
void printSubmoduleInterface(ModuleDecl *M, ArrayRef<StringRef> FullModuleName,
65-
ArrayRef<StringRef> GroupNames,
66-
ModuleTraversalOptions TraversalOptions,
67-
ASTPrinter &Printer, const PrintOptions &Options,
68-
const bool PrintSynthesizedExtensions);
69-
7062
/// Print the interface for a header that has been imported via the implicit
7163
/// objc header importing feature.
7264
void printHeaderInterface(StringRef Filename, ASTContext &Ctx,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2400,7 +2400,7 @@ class FilteringDeclaredDeclConsumer : public swift::VisibleDeclConsumer {
24002400
FilteringDeclaredDeclConsumer(swift::VisibleDeclConsumer &consumer,
24012401
const ClangModuleUnit *CMU)
24022402
: NextConsumer(consumer), ModuleFilter(CMU) {
2403-
assert(CMU);
2403+
assert(CMU && CMU->isTopLevel() && "Only top-level modules supported");
24042404
}
24052405

24062406
void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason,

lib/IDE/ModuleInterfacePrinting.cpp

Lines changed: 43 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,6 @@ printTypeInterface(ModuleDecl *M, StringRef TypeUSR, ASTPrinter &Printer,
189189
Printer, TypeName, Error);
190190
}
191191

192-
void swift::ide::printModuleInterface(ModuleDecl *M, Optional<StringRef> Group,
193-
ModuleTraversalOptions TraversalOptions,
194-
ASTPrinter &Printer,
195-
const PrintOptions &Options,
196-
const bool PrintSynthesizedExtensions) {
197-
printSubmoduleInterface(M, M->getName().str(),
198-
Group.hasValue() ? Group.getValue() : ArrayRef<StringRef>(),
199-
TraversalOptions, Printer, Options,
200-
PrintSynthesizedExtensions);
201-
}
202-
203192
static void adjustPrintOptions(PrintOptions &AdjustedOptions) {
204193
// Don't print empty curly braces while printing the module interface.
205194
AdjustedOptions.FunctionDefinitions = false;
@@ -230,7 +219,7 @@ static bool extensionHasClangNode(ExtensionDecl *ext) {
230219

231220
Optional<StringRef>
232221
swift::ide::findGroupNameForUSR(ModuleDecl *M, StringRef USR) {
233-
for (auto File : M->getFiles()) {
222+
for (auto File : M->getTopLevelModule()->getFiles()) {
234223
if (auto Name = File->getGroupNameByUSR(USR)) {
235224
return Name;
236225
}
@@ -539,53 +528,45 @@ static void printCrossImportOverlays(ModuleDecl *Declaring, ASTContext &Ctx,
539528
}
540529
}
541530

542-
void swift::ide::printSubmoduleInterface(
543-
ModuleDecl *M,
544-
ArrayRef<StringRef> FullModuleName,
531+
void swift::ide::printModuleInterface(
532+
ModuleDecl *TargetMod,
545533
ArrayRef<StringRef> GroupNames,
546534
ModuleTraversalOptions TraversalOptions,
547535
ASTPrinter &Printer,
548536
const PrintOptions &Options,
549537
const bool PrintSynthesizedExtensions) {
550-
auto &SwiftContext = M->getASTContext();
538+
539+
// Clang submodules aren't handled well by `getDisplayDecls()` (no decls are
540+
// returned), so map them to their top-level module and filter out the extra
541+
// results below.
542+
const clang::Module *TargetClangMod = TargetMod->findUnderlyingClangModule();
543+
ModuleDecl *TopLevelMod = TargetMod->getTopLevelModule();
544+
bool IsSubmodule = TargetMod != TopLevelMod;
545+
546+
auto &SwiftContext = TopLevelMod->getASTContext();
551547
auto &Importer =
552548
static_cast<ClangImporter &>(*SwiftContext.getClangModuleLoader());
553549

554550
auto AdjustedOptions = Options;
555551
adjustPrintOptions(AdjustedOptions);
556552

557553
SmallVector<Decl *, 1> Decls;
558-
M->getDisplayDecls(Decls);
554+
TopLevelMod->getDisplayDecls(Decls);
559555

560-
const clang::Module *InterestingClangModule = nullptr;
561556
SmallVector<ImportDecl *, 1> ImportDecls;
562557
llvm::DenseSet<const clang::Module *> ClangModulesForImports;
563558
SmallVector<Decl *, 1> SwiftDecls;
564559
llvm::DenseMap<const clang::Module *,
565560
SmallVector<std::pair<Decl *, clang::SourceLocation>, 1>>
566561
ClangDecls;
567562

568-
// Drop top-level module name.
569-
FullModuleName = FullModuleName.slice(1);
570-
571-
InterestingClangModule = M->findUnderlyingClangModule();
572-
if (InterestingClangModule) {
573-
for (StringRef Name : FullModuleName) {
574-
InterestingClangModule = InterestingClangModule->findSubmodule(Name);
575-
if (!InterestingClangModule)
576-
return;
577-
}
578-
} else {
579-
assert(FullModuleName.empty());
580-
}
581-
582563
// If we're printing recursively, find all of the submodules to print.
583-
if (InterestingClangModule) {
564+
if (TargetClangMod) {
584565
if (TraversalOptions) {
585566
SmallVector<const clang::Module *, 8> Worklist;
586567
SmallPtrSet<const clang::Module *, 8> Visited;
587-
Worklist.push_back(InterestingClangModule);
588-
Visited.insert(InterestingClangModule);
568+
Worklist.push_back(TargetClangMod);
569+
Visited.insert(TargetClangMod);
589570
while (!Worklist.empty()) {
590571
const clang::Module *CM = Worklist.pop_back_val();
591572
if (!(TraversalOptions & ModuleTraversal::VisitHidden) &&
@@ -604,17 +585,17 @@ void swift::ide::printSubmoduleInterface(
604585
}
605586
}
606587
} else {
607-
ClangDecls.insert({ InterestingClangModule, {} });
588+
ClangDecls.insert({ TargetClangMod, {} });
608589
}
609590
}
610591

611-
// Collect those submodules that are actually imported but have no import decls
612-
// in the module.
592+
// Collect those submodules that are actually imported but have no import
593+
// decls in the module.
613594
llvm::SmallPtrSet<const clang::Module *, 16> NoImportSubModules;
614-
if (InterestingClangModule) {
595+
if (TargetClangMod) {
615596
// Assume all submodules are missing.
616-
for (auto It =InterestingClangModule->submodule_begin();
617-
It != InterestingClangModule->submodule_end(); It++) {
597+
for (auto It = TargetClangMod->submodule_begin();
598+
It != TargetClangMod->submodule_end(); It++) {
618599
NoImportSubModules.insert(*It);
619600
}
620601
}
@@ -631,18 +612,18 @@ void swift::ide::printSubmoduleInterface(
631612
}
632613

633614
auto ShouldPrintImport = [&](ImportDecl *ImportD) -> bool {
634-
if (!InterestingClangModule)
615+
if (!TargetClangMod)
635616
return true;
636-
auto ClangMod = ImportD->getClangModule();
637-
if (!ClangMod)
617+
auto ImportedMod = ImportD->getClangModule();
618+
if (!ImportedMod)
638619
return true;
639-
if (!ClangMod->isSubModule())
620+
if (!ImportedMod->isSubModule())
640621
return true;
641-
if (ClangMod == InterestingClangModule)
622+
if (ImportedMod == TargetClangMod)
642623
return false;
643624
// FIXME: const-ness on the clang API.
644-
return ClangMod->isSubModuleOf(
645-
const_cast<clang::Module*>(InterestingClangModule));
625+
return ImportedMod->isSubModuleOf(
626+
const_cast<clang::Module*>(TargetClangMod));
646627
};
647628

648629
if (auto ID = dyn_cast<ImportDecl>(D)) {
@@ -690,14 +671,16 @@ void swift::ide::printSubmoduleInterface(
690671
}
691672
}
692673

693-
if (FullModuleName.empty()) {
674+
if (!IsSubmodule) {
694675
// If group name is given and the decl does not belong to the group, skip it.
695676
if (!GroupNames.empty()){
696-
if (auto Target = D->getGroupName()) {
677+
if (auto TargetGroup = D->getGroupName()) {
697678
if (std::find(GroupNames.begin(), GroupNames.end(),
698-
Target.getValue()) != GroupNames.end()) {
699-
FileRangedDecls.insert(std::make_pair(D->getSourceFileName().getValue(),
700-
std::vector<Decl*>())).first->getValue().push_back(D);
679+
TargetGroup.getValue()) != GroupNames.end()) {
680+
FileRangedDecls.insert({
681+
D->getSourceFileName().getValue(),
682+
std::vector<Decl*>()
683+
}).first->getValue().push_back(D);
701684
}
702685
}
703686
continue;
@@ -725,8 +708,9 @@ void swift::ide::printSubmoduleInterface(
725708
}
726709

727710
// Create the missing import decls and add to the collector.
728-
for (auto *SM : NoImportSubModules) {
729-
ImportDecls.push_back(createImportDecl(M->getASTContext(), M, SM, {}));
711+
for (auto *SubMod : NoImportSubModules) {
712+
ImportDecls.push_back(createImportDecl(TopLevelMod->getASTContext(),
713+
TopLevelMod, SubMod, {}));
730714
}
731715

732716
// Sort imported clang declarations in source order *within a submodule*.
@@ -760,7 +744,7 @@ void swift::ide::printSubmoduleInterface(
760744
};
761745

762746
// Imports from the stdlib are internal details that don't need to be exposed.
763-
if (!M->isStdlibModule()) {
747+
if (!TargetMod->isStdlibModule()) {
764748
for (auto *D : ImportDecls)
765749
PrintDecl(D);
766750
Printer << "\n";
@@ -785,8 +769,7 @@ void swift::ide::printSubmoduleInterface(
785769
}
786770
}
787771

788-
if (!(TraversalOptions & ModuleTraversal::SkipOverlay) ||
789-
!InterestingClangModule) {
772+
if (!(TraversalOptions & ModuleTraversal::SkipOverlay) || !TargetClangMod) {
790773
for (auto *D : SwiftDecls) {
791774
if (PrintDecl(D))
792775
Printer << "\n";
@@ -796,8 +779,8 @@ void swift::ide::printSubmoduleInterface(
796779
// also print the decls from any underscored Swift cross-import overlays it
797780
// is the underlying module of, transitively.
798781
if (GroupNames.empty()) {
799-
printCrossImportOverlays(M, SwiftContext, *PrinterToUse, AdjustedOptions,
800-
PrintSynthesizedExtensions);
782+
printCrossImportOverlays(TargetMod, SwiftContext, *PrinterToUse,
783+
AdjustedOptions, PrintSynthesizedExtensions);
801784
}
802785
}
803786
}

test/SourceKit/DocSupport/doc_clang_module.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,7 @@
99
// RUN: %sourcekitd-test -req=doc-info -module Foo -- -F %S/../Inputs/libIDE-mock-sdk \
1010
// RUN: -target %target-triple %clang-importer-sdk-nosource -I %t | %sed_clean > %t.response
1111
// RUN: %diff -u %s.response %t.response
12+
13+
// RUN: %sourcekitd-test -req=doc-info -module Foo.FooSub -- -F %S/../Inputs/libIDE-mock-sdk \
14+
// RUN: -target %target-triple %clang-importer-sdk-nosource -I %t | %sed_clean > %t.response
15+
// RUN: %diff -u %s.sub.response %t.response

0 commit comments

Comments
 (0)