@@ -25,12 +25,10 @@ namespace {
25
25
26
26
// / Compare the two \c ModuleDecl instances to see whether they are the same.
27
27
// /
28
- // / Pass \c true to the \c ignoreUnderlying argument to consider two modules the same even if
29
- // / one is a Swift module and the other a non-Swift module. This allows a Swift module and its
30
- // / underlying Clang module to compare as equal.
31
- bool areModulesEqual (const ModuleDecl *lhs, const ModuleDecl *rhs, bool ignoreUnderlying = false ) {
32
- return lhs->getNameStr () == rhs->getNameStr ()
33
- && (ignoreUnderlying || lhs->isNonSwiftModule () == rhs->isNonSwiftModule ());
28
+ // / This does a by-name comparison to consider a module's underlying Clang module to be equivalent
29
+ // / to the wrapping module of the same name.
30
+ bool areModulesEqual (const ModuleDecl *lhs, const ModuleDecl *rhs) {
31
+ return lhs->getNameStr () == rhs->getNameStr ();
34
32
}
35
33
36
34
} // anonymous namespace
@@ -50,11 +48,13 @@ SymbolGraphASTWalker::SymbolGraphASTWalker(ModuleDecl &M,
50
48
SymbolGraph *SymbolGraphASTWalker::getModuleSymbolGraph (const Decl *D) {
51
49
auto *M = D->getModuleContext ();
52
50
const auto *DC = D->getDeclContext ();
51
+ SmallVector<const NominalTypeDecl *, 2 > ParentTypes = {};
53
52
const Decl *ExtendedNominal = nullptr ;
54
53
while (DC) {
55
54
M = DC->getParentModule ();
56
55
if (const auto *NTD = dyn_cast_or_null<NominalTypeDecl>(DC->getAsDecl ())) {
57
56
DC = NTD->getDeclContext ();
57
+ ParentTypes.push_back (NTD);
58
58
} else if (const auto *Ext = dyn_cast_or_null<ExtensionDecl>(DC->getAsDecl ())) {
59
59
DC = Ext->getExtendedNominal ()->getDeclContext ();
60
60
if (!ExtendedNominal)
@@ -64,10 +64,10 @@ SymbolGraph *SymbolGraphASTWalker::getModuleSymbolGraph(const Decl *D) {
64
64
}
65
65
}
66
66
67
- if (areModulesEqual (&this ->M , M, true )) {
67
+ if (areModulesEqual (&this ->M , M)) {
68
68
return &MainGraph;
69
69
} else if (MainGraph.DeclaringModule .hasValue () &&
70
- areModulesEqual (MainGraph.DeclaringModule .getValue (), M, true )) {
70
+ areModulesEqual (MainGraph.DeclaringModule .getValue (), M)) {
71
71
// Cross-import overlay modules already appear as "extensions" of their declaring module; we
72
72
// should put actual extensions of that module into the main graph
73
73
return &MainGraph;
@@ -79,9 +79,8 @@ SymbolGraph *SymbolGraphASTWalker::getModuleSymbolGraph(const Decl *D) {
79
79
return &MainGraph;
80
80
}
81
81
82
- if (ExtendedNominal && isFromExportedImportedModule (ExtendedNominal)) {
83
- return &MainGraph;
84
- } else if (!ExtendedNominal && isConsideredExportedImported (D)) {
82
+ // If this type is the child of a type which was re-exported in a qualified export, use the main graph.
83
+ if (llvm::any_of (ParentTypes, [&](const NominalTypeDecl *NTD){ return isQualifiedExportedImport (NTD); })) {
85
84
return &MainGraph;
86
85
}
87
86
@@ -230,7 +229,7 @@ bool SymbolGraphASTWalker::walkToDeclPre(Decl *D, CharSourceRange Range) {
230
229
if (const auto *ExtendedNominal = Extension->getExtendedNominal ()) {
231
230
auto ExtendedModule = ExtendedNominal->getModuleContext ();
232
231
auto ExtendedSG = getModuleSymbolGraph (ExtendedNominal);
233
- if (ExtendedModule != &M ) {
232
+ if (! isOurModule (ExtendedModule) ) {
234
233
ExtendedSG->recordNode (Symbol (ExtendedSG, VD, nullptr ));
235
234
return true ;
236
235
}
@@ -244,22 +243,10 @@ bool SymbolGraphASTWalker::walkToDeclPre(Decl *D, CharSourceRange Range) {
244
243
}
245
244
246
245
bool SymbolGraphASTWalker::isConsideredExportedImported (const Decl *D) const {
247
- // First check the decl itself to see if it was directly re-exported.
248
- if (isFromExportedImportedModule (D))
249
- return true ;
250
-
251
- const auto *DC = D->getDeclContext ();
252
-
253
- // Next, see if the decl is a child symbol of another decl that was re-exported.
254
- if (DC) {
255
- if (const auto *VD = dyn_cast_or_null<ValueDecl>(DC->getAsDecl ())) {
256
- if (isFromExportedImportedModule (VD))
257
- return true ;
258
- }
259
- }
260
-
261
- // Finally, check to see if this decl is an extension of something else that was re-exported.
246
+ // Check to see if this decl is an extension of something else that was re-exported.
247
+ // Do this first in case there's a chain of extensions that leads somewhere that's not a re-export.
262
248
// FIXME: this considers synthesized members of extensions to be valid
249
+ const auto *DC = D->getDeclContext ();
263
250
const Decl *ExtendedNominal = nullptr ;
264
251
while (DC && !ExtendedNominal) {
265
252
if (const auto *ED = dyn_cast_or_null<ExtensionDecl>(DC->getAsDecl ())) {
@@ -269,10 +256,23 @@ bool SymbolGraphASTWalker::isConsideredExportedImported(const Decl *D) const {
269
256
}
270
257
}
271
258
272
- if (ExtendedNominal && isFromExportedImportedModule (ExtendedNominal)) {
259
+ if (ExtendedNominal && isConsideredExportedImported (ExtendedNominal)) {
273
260
return true ;
274
261
}
275
262
263
+ // Check to see if the decl is a child symbol of another decl that was re-exported.
264
+ DC = D->getDeclContext ();
265
+ if (DC) {
266
+ if (const auto *VD = dyn_cast_or_null<ValueDecl>(DC->getAsDecl ())) {
267
+ if (isConsideredExportedImported (VD))
268
+ return true ;
269
+ }
270
+ }
271
+
272
+ // Check the decl itself to see if it was directly re-exported.
273
+ if (isFromExportedImportedModule (D) || isQualifiedExportedImport (D))
274
+ return true ;
275
+
276
276
// If none of the other checks passed, this wasn't from a re-export.
277
277
return false ;
278
278
}
@@ -293,3 +293,7 @@ bool SymbolGraphASTWalker::isExportedImportedModule(const ModuleDecl *M) const {
293
293
return areModulesEqual (M, MD->getModuleContext ());
294
294
});
295
295
}
296
+
297
+ bool SymbolGraphASTWalker::isOurModule (const ModuleDecl *M) const {
298
+ return areModulesEqual (M, &this ->M ) || isExportedImportedModule (M);
299
+ }
0 commit comments