@@ -238,6 +238,199 @@ swift::ide::findGroupNameForUSR(ModuleDecl *M, StringRef USR) {
238
238
return None;
239
239
}
240
240
241
+ // / Sorts import declarations for display.
242
+ static bool compareImports (ImportDecl *LHS, ImportDecl *RHS) {
243
+ auto LHSPath = LHS->getFullAccessPath ();
244
+ auto RHSPath = RHS->getFullAccessPath ();
245
+ for (unsigned i: range (std::min (LHSPath.size (), RHSPath.size ()))) {
246
+ if (int Ret = LHSPath[i].Item .str ().compare (RHSPath[i].Item .str ()))
247
+ return Ret < 0 ;
248
+ }
249
+ return false ;
250
+ };
251
+
252
+ // / Sorts Swift declarations for display.
253
+ static bool compareSwiftDecls (Decl *LHS, Decl *RHS) {
254
+ auto *LHSValue = dyn_cast<ValueDecl>(LHS);
255
+ auto *RHSValue = dyn_cast<ValueDecl>(RHS);
256
+
257
+ if (LHSValue && RHSValue) {
258
+ auto LHSName = LHSValue->getBaseName ();
259
+ auto RHSName = RHSValue->getBaseName ();
260
+ if (int Ret = LHSName.compare (RHSName))
261
+ return Ret < 0 ;
262
+ // FIXME: not sufficient to establish a total order for overloaded decls.
263
+ }
264
+ return LHS->getKind () < RHS->getKind ();
265
+ };
266
+
267
+ // / Represents a single cross-import overlay of the target module whose
268
+ // / declarations are conditionally available when a bystander module is
269
+ // / imported alongside the target module.
270
+ class OverlayItem {
271
+ friend class OverlayCollector ;
272
+ private:
273
+ ModuleDecl *Module; // /< The overlay module.
274
+ StringRef BystanderName; // /< The name of the required bystander module.
275
+ OverlayItem *Underlying; // /< The underlying overlay, or target module.
276
+
277
+ public:
278
+ OverlayItem (ModuleDecl *Overlay, StringRef BystanderName,
279
+ OverlayItem *Underlying)
280
+ : Module(Overlay), BystanderName(BystanderName), Underlying(Underlying) {}
281
+
282
+ // / Gets the set of bystander modules that need to be imported along with the
283
+ // / target module for this overlay to be applied.
284
+ void getBystanders (SmallVectorImpl<StringRef> &Bystanders) const {
285
+ if (Underlying)
286
+ Underlying->getBystanders (Bystanders);
287
+ if (!BystanderName.empty ())
288
+ Bystanders.push_back (BystanderName);
289
+ }
290
+
291
+ // / Gets the set of accessible declarations specified in this overlay, divided
292
+ // / into two groups: the import decls, and everything else.
293
+ std::pair<ArrayRef<Decl*>, ArrayRef<Decl*>>
294
+ getDecls (SmallVectorImpl<Decl *> &Decls, AccessLevel AccessFilter) const {
295
+ Module->getDisplayDecls (Decls);
296
+
297
+ // Filter out parent imports and inaccessible decls.
298
+ SmallPtrSet<ModuleDecl *, 8 > PrevImported;
299
+ getUnderlyingImports (PrevImported);
300
+ auto NewEnd = std::partition (Decls.begin (), Decls.end (), [&](Decl *D) {
301
+ if (auto *ID = dyn_cast<ImportDecl>(D)) {
302
+ if (isUnderlying (ID->getModule ()))
303
+ return false ;
304
+ if (PrevImported.find (ID->getModule ()) != PrevImported.end ())
305
+ return false ;
306
+ }
307
+ if (auto *VD = dyn_cast<ValueDecl>(D)) {
308
+ if (AccessFilter > AccessLevel::Private &&
309
+ VD->getFormalAccess () < AccessFilter)
310
+ return false ;
311
+ }
312
+ return true ;
313
+ });
314
+ if (NewEnd != Decls.end ())
315
+ Decls.erase (NewEnd, Decls.end ());
316
+
317
+ // Separate out the import declarations and sort
318
+ MutableArrayRef<Decl*> Imports, Remainder;
319
+ auto ImportsEnd = std::partition (Decls.begin (), Decls.end (), [](Decl *D) {
320
+ return isa<ImportDecl>(D);
321
+ });
322
+ if (ImportsEnd != Decls.begin ()) {
323
+ Imports = {Decls.begin (), ImportsEnd};
324
+ Remainder = {ImportsEnd, Decls.end ()};
325
+ std::sort (Imports.begin (), Imports.end (), [](Decl *LHS, Decl *RHS) {
326
+ return compareImports (cast<ImportDecl>(LHS), cast<ImportDecl>(RHS));
327
+ });
328
+ } else {
329
+ Remainder = Decls;
330
+ }
331
+ std::sort (Remainder.begin (), Remainder.end (), compareSwiftDecls);
332
+ return {Imports, Remainder};
333
+ }
334
+
335
+ private:
336
+ // / Checks whether the given module is an underlying module of this overlay,
337
+ // / transitively.
338
+ bool isUnderlying (ModuleDecl *M) const {
339
+ if (M == Module)
340
+ return true ;
341
+ return Underlying && Underlying->isUnderlying (M);
342
+ }
343
+
344
+ // / Populates \p Imported with all ModuleDecls directly imported by the base
345
+ // / underlying module (ignoring those of any intermediate underlying modules).
346
+ void getUnderlyingImports (SmallPtrSet<ModuleDecl *, 8 > &Imported) const {
347
+ if (Underlying) {
348
+ Underlying->getUnderlyingImports (Imported);
349
+ } else {
350
+ SmallVector<Decl*, 1 > Decls;
351
+ Module->getDisplayDecls (Decls);
352
+ for (auto *D: Decls) {
353
+ if (auto *ID = dyn_cast<ImportDecl>(D))
354
+ Imported.insert (ID->getModule ());
355
+ }
356
+ }
357
+ }
358
+ };
359
+
360
+ // Collects the set of underscored cross-import overlay modules of a given
361
+ // target module, transitively, reporting the set of bystander modules
362
+ // necessary for their inclusion (on top of the target module).
363
+ //
364
+ // E.g. if module A has a cross-import overlay _ABAdditions that is imported if
365
+ // a bystander module B is also imported, and _ABAdditions has a cross-import
366
+ // overlay __ABAdditionsCAdditions imported when a bystander module C is
367
+ // imported, the collected overlays will include _ABAdditions with bystanders B,
368
+ // and __ABAdditionsCAdditions with bystanders B and C.
369
+ class OverlayCollector {
370
+ ASTContext &Ctx; // /< ASTContext to use for module lookups.
371
+ SmallVector<OverlayItem, 1 > Overlays; // /< The collected overlays.
372
+ OverlayItem TargetModuleItem; // / < The initial worklist item.
373
+
374
+ public:
375
+ OverlayCollector (ModuleDecl *Target, ASTContext &Ctx)
376
+ : Ctx(Ctx), TargetModuleItem(Target, StringRef(), nullptr ) {
377
+ SmallVector<OverlayItem *, 1 > Worklist;
378
+ SmallPtrSet<ModuleDecl *, 1 > Seen;
379
+
380
+ Worklist.push_back (&TargetModuleItem);
381
+ while (!Worklist.empty ()) {
382
+ OverlayItem &Item = *Worklist.back ();
383
+ Worklist.pop_back ();
384
+ if (!Seen.insert (Item.Module ).second )
385
+ continue ;
386
+ processItem (Item, Worklist);
387
+ }
388
+ std::sort (Overlays.begin (), Overlays.end (),
389
+ [](OverlayItem &LHS, OverlayItem &RHS) {
390
+ return LHS.Module ->getNameStr () < RHS.Module ->getNameStr ();
391
+ });
392
+ }
393
+
394
+ // / Gets the underscored cross-import overlays.
395
+ ArrayRef<OverlayItem> getOverlays () {
396
+ return Overlays;
397
+ }
398
+
399
+ // / Maps the given module to the target module if it's one of its underscored
400
+ // / cross-import overlays.
401
+ const ModuleDecl *mapToUnderlyingModule (const ModuleDecl *M) {
402
+ auto i = std::find_if (Overlays.begin (), Overlays.end (),
403
+ [M](OverlayItem &Item) {
404
+ return Item.Module == M;
405
+ });
406
+ return i == Overlays.end () ? M : TargetModuleItem.Module ;
407
+ }
408
+
409
+ private:
410
+ void processItem (OverlayItem &Current,
411
+ SmallVectorImpl<OverlayItem*> &Worklist) {
412
+ SmallVector<Identifier, 1 > BystanderNames, OverlayNames;
413
+ Current.Module ->getDeclaredCrossImportBystanders (BystanderNames);
414
+
415
+ for (Identifier BystanderName: BystanderNames) {
416
+ OverlayNames.clear ();
417
+ Current.Module ->findDeclaredCrossImportOverlays (BystanderName,
418
+ OverlayNames,
419
+ SourceLoc ());
420
+ for (Identifier OverlayName: OverlayNames) {
421
+ StringRef OverlayNameStr = OverlayName.str ();
422
+ if (!OverlayNameStr.startswith (" _" ))
423
+ continue ;
424
+ ModuleDecl *Overlay = Ctx.getModuleByName (OverlayNameStr);
425
+ if (!Overlay)
426
+ continue ;
427
+ Overlays.emplace_back (Overlay, BystanderName.str (), &Current);
428
+ Worklist.push_back (&Overlays.back ());
429
+ }
430
+ }
431
+ }
432
+ };
433
+
241
434
void swift::ide::printSubmoduleInterface (
242
435
ModuleDecl *M,
243
436
ArrayRef<StringRef> FullModuleName,
@@ -246,18 +439,26 @@ void swift::ide::printSubmoduleInterface(
246
439
ASTPrinter &Printer,
247
440
const PrintOptions &Options,
248
441
const bool PrintSynthesizedExtensions) {
442
+ auto &SwiftContext = M->getASTContext ();
443
+ auto &Importer =
444
+ static_cast <ClangImporter &>(*SwiftContext.getClangModuleLoader ());
445
+
249
446
auto AdjustedOptions = Options;
250
447
adjustPrintOptions (AdjustedOptions);
251
448
449
+ // If we end up printing decls from any cross-import overlay modules, make
450
+ // sure we map any qualifying module references to the underlying module.
451
+ Optional<OverlayCollector> OverlayCollector;
452
+ AdjustedOptions.mapModuleToUnderlying = [&](const ModuleDecl *M) {
453
+ return OverlayCollector
454
+ ? OverlayCollector->mapToUnderlyingModule (M)
455
+ : M;
456
+ };
457
+
252
458
SmallVector<Decl *, 1 > Decls;
253
459
M->getDisplayDecls (Decls);
254
460
255
- auto &SwiftContext = M->getASTContext ();
256
- auto &Importer =
257
- static_cast <ClangImporter &>(*SwiftContext.getClangModuleLoader ());
258
-
259
461
const clang::Module *InterestingClangModule = nullptr ;
260
-
261
462
SmallVector<ImportDecl *, 1 > ImportDecls;
262
463
llvm::DenseSet<const clang::Module *> ClangModulesForImports;
263
464
SmallVector<Decl *, 1 > SwiftDecls;
@@ -429,9 +630,8 @@ void swift::ide::printSubmoduleInterface(
429
630
ImportDecls.push_back (createImportDecl (M->getASTContext (), M, SM, {}));
430
631
}
431
632
633
+ // Sort imported clang declarations in source order *within a submodule*.
432
634
auto &ClangSourceManager = Importer.getClangASTContext ().getSourceManager ();
433
-
434
- // Sort imported declarations in source order *within a submodule*.
435
635
for (auto &P : ClangDecls) {
436
636
std::stable_sort (P.second .begin (), P.second .end (),
437
637
[&](std::pair<Decl *, clang::SourceLocation> LHS,
@@ -442,39 +642,12 @@ void swift::ide::printSubmoduleInterface(
442
642
}
443
643
444
644
// Sort Swift declarations so that we print them in a consistent order.
445
- std::sort (ImportDecls.begin (), ImportDecls.end (),
446
- [](ImportDecl *LHS, ImportDecl *RHS) -> bool {
447
- auto LHSPath = LHS->getFullAccessPath ();
448
- auto RHSPath = RHS->getFullAccessPath ();
449
- for (unsigned i = 0 , e = std::min (LHSPath.size (), RHSPath.size ()); i != e;
450
- i++) {
451
- if (int Ret = LHSPath[i].Item .str ().compare (RHSPath[i].Item .str ()))
452
- return Ret < 0 ;
453
- }
454
- return false ;
455
- });
645
+ std::sort (ImportDecls.begin (), ImportDecls.end (), compareImports);
456
646
457
647
// If the group name is specified, we sort them according to their source order,
458
648
// which is the order preserved by getTopLevelDecls.
459
- if (GroupNames.empty ()) {
460
- std::stable_sort (SwiftDecls.begin (), SwiftDecls.end (),
461
- [&](Decl *LHS, Decl *RHS) -> bool {
462
- auto *LHSValue = dyn_cast<ValueDecl>(LHS);
463
- auto *RHSValue = dyn_cast<ValueDecl>(RHS);
464
-
465
- if (LHSValue && RHSValue) {
466
- auto LHSName = LHSValue->getBaseName ();
467
- auto RHSName = RHSValue->getBaseName ();
468
- if (int Ret = LHSName.compare (RHSName))
469
- return Ret < 0 ;
470
- // FIXME: this is not sufficient to establish a total order for overloaded
471
- // decls.
472
- return LHS->getKind () < RHS->getKind ();
473
- }
474
-
475
- return LHS->getKind () < RHS->getKind ();
476
- });
477
- }
649
+ if (GroupNames.empty ())
650
+ std::stable_sort (SwiftDecls.begin (), SwiftDecls.end (), compareSwiftDecls);
478
651
479
652
ASTPrinter *PrinterToUse = &Printer;
480
653
@@ -646,6 +819,56 @@ void swift::ide::printSubmoduleInterface(
646
819
if (PrintDecl (D))
647
820
Printer << " \n " ;
648
821
}
822
+
823
+ // If we're printing the entire target module (not specific sub-groups),
824
+ // also print the decls from any underscored Swift cross-import overlays it
825
+ // is the underlying module of, transitively.
826
+ if (GroupNames.empty ()) {
827
+ OverlayCollector.emplace (M, SwiftContext);
828
+
829
+ SmallVector<Decl *, 1 > OverlayDecls;
830
+ SmallVector<StringRef, 1 > Bystanders;
831
+
832
+ for (auto &Overlay: OverlayCollector->getOverlays ()) {
833
+ OverlayDecls.clear ();
834
+ auto DeclLists = Overlay.getDecls (OverlayDecls, Options.AccessFilter );
835
+
836
+ // Ignore overlays without any decls
837
+ if (OverlayDecls.empty ())
838
+ continue ;
839
+
840
+ Bystanders.clear ();
841
+ Overlay.getBystanders (Bystanders);
842
+ assert (!Bystanders.empty () && " Overlay with no bystanders?" );
843
+
844
+ std::string BystanderList;
845
+ for (size_t I: range (Bystanders.size ())) {
846
+ if (I == Bystanders.size () - 1 ) {
847
+ if (I != 0 )
848
+ BystanderList += " and " ;
849
+ } else if (I != 0 ) {
850
+ BystanderList += " , " ;
851
+ }
852
+ BystanderList += Bystanders[I].str ();
853
+ }
854
+
855
+ Printer << " \n // MARK: - " << BystanderList << " Additions\n\n " ;
856
+ for (auto *Import : DeclLists.first )
857
+ PrintDecl (Import);
858
+ Printer << " \n " ;
859
+
860
+ std::string PerDeclComment = " // Available when " + BystanderList;
861
+ PerDeclComment += Bystanders.size () == 1 ? " is" : " are" ;
862
+ PerDeclComment += " imported with " + M->getNameStr ().str ();
863
+
864
+ for (auto *D : DeclLists.second ) {
865
+ // FIXME: only print this comment if the decl is actually printed.
866
+ Printer << PerDeclComment << " \n " ;
867
+ if (PrintDecl (D))
868
+ Printer << " \n " ;
869
+ }
870
+ }
871
+ }
649
872
}
650
873
}
651
874
0 commit comments