19
19
#include " swift/AST/FileSystem.h"
20
20
#include " swift/AST/Module.h"
21
21
#include " swift/AST/ModuleNameLookup.h"
22
+ #include " swift/AST/NameLookupRequests.h"
22
23
#include " swift/AST/ProtocolConformance.h"
24
+ #include " swift/AST/TypeCheckRequests.h"
23
25
#include " swift/AST/TypeRepr.h"
24
26
#include " swift/Basic/STLExtras.h"
25
27
#include " swift/Frontend/Frontend.h"
@@ -569,13 +571,14 @@ class InheritedProtocolCollector {
569
571
});
570
572
}
571
573
574
+ // Preserve the behavior of previous implementations which formatted of
575
+ // empty extensions compactly with '{}' on the same line.
576
+ PrintOptions extensionPrintOptions = printOptions;
577
+ extensionPrintOptions.PrintEmptyMembersOnSameLine = true ;
578
+
572
579
// Then walk the remaining ones, and see what we need to print.
573
- // Note: We could do this in one pass, but the logic is easier to
574
- // understand if we build up the list and then print it, even if it takes
575
- // a bit more memory.
576
580
// FIXME: This will pick the availability attributes from the first sight
577
581
// of a protocol rather than the maximally available case.
578
- SmallVector<ProtocolAndAvailability, 16 > protocolsToPrint;
579
582
for (const auto &protoAndAvailability : ExtraProtocols) {
580
583
auto proto = std::get<0 >(protoAndAvailability);
581
584
auto availability = std::get<1 >(protoAndAvailability);
@@ -601,58 +604,64 @@ class InheritedProtocolCollector {
601
604
if (isPublicOrUsableFromInline (inherited) &&
602
605
conformanceDeclaredInModule (M, nominal, inherited) &&
603
606
!M->isImportedImplementationOnly (inherited->getParentModule ())) {
604
- protocolsToPrint.push_back (
605
- ProtocolAndAvailability (inherited, availability, isUnchecked,
606
- otherAttrs));
607
+ auto protoAndAvailability = ProtocolAndAvailability (
608
+ inherited, availability, isUnchecked, otherAttrs);
609
+ printSynthesizedExtension (out, extensionPrintOptions, M, nominal,
610
+ protoAndAvailability);
607
611
return TypeWalker::Action::SkipChildren;
608
612
}
609
613
610
614
return TypeWalker::Action::Continue;
611
615
});
612
616
}
613
- if (protocolsToPrint.empty ())
614
- return ;
615
-
616
- for (const auto &protoAndAvailability : protocolsToPrint) {
617
- StreamPrinter printer (out);
618
- auto proto = std::get<0 >(protoAndAvailability);
619
- auto availability = std::get<1 >(protoAndAvailability);
620
- auto isUnchecked = std::get<2 >(protoAndAvailability);
621
- auto otherAttrs = std::get<3 >(protoAndAvailability);
622
-
623
- PrintOptions curPrintOptions = printOptions;
624
- auto printBody = [&] {
625
- // FIXME: Shouldn't this be an implicit conversion?
626
- TinyPtrVector<const DeclAttribute *> attrs;
627
- attrs.insert (attrs.end (), availability.begin (), availability.end ());
628
- auto spiAttributes = proto->getAttrs ().getAttributes <SPIAccessControlAttr>();
629
- attrs.insert (attrs.end (), spiAttributes.begin (), spiAttributes.end ());
630
- attrs.insert (attrs.end (), otherAttrs.begin (), otherAttrs.end ());
631
- DeclAttributes::print (printer, curPrintOptions, attrs);
632
-
633
- printer << " extension " ;
634
- {
635
- bool oldFullyQualifiedTypesIfAmbiguous =
636
- curPrintOptions.FullyQualifiedTypesIfAmbiguous ;
637
- curPrintOptions.FullyQualifiedTypesIfAmbiguous =
638
- curPrintOptions.FullyQualifiedExtendedTypesIfAmbiguous ;
639
- nominal->getDeclaredType ().print (printer, curPrintOptions);
640
- curPrintOptions.FullyQualifiedTypesIfAmbiguous =
641
- oldFullyQualifiedTypesIfAmbiguous;
642
- }
643
- printer << " : " ;
644
-
645
- if (isUnchecked)
646
- printer << " @unchecked " ;
617
+ }
647
618
648
- proto->getDeclaredInterfaceType ()->print (printer, curPrintOptions);
619
+ // / Prints a dummy extension on \p nominal to \p out for a public conformance
620
+ // / to the protocol contained by \p protoAndAvailability.
621
+ static void
622
+ printSynthesizedExtension (raw_ostream &out, const PrintOptions &printOptions,
623
+ ModuleDecl *M, const NominalTypeDecl *nominal,
624
+ ProtocolAndAvailability &protoAndAvailability) {
625
+ StreamPrinter printer (out);
626
+
627
+ auto proto = std::get<0 >(protoAndAvailability);
628
+ auto availability = std::get<1 >(protoAndAvailability);
629
+ auto isUnchecked = std::get<2 >(protoAndAvailability);
630
+ auto otherAttrs = std::get<3 >(protoAndAvailability);
631
+
632
+ // Create a synthesized ExtensionDecl for the conformance.
633
+ ASTContext &ctx = M->getASTContext ();
634
+ auto inherits = ctx.AllocateCopy (llvm::makeArrayRef (InheritedEntry (
635
+ TypeLoc::withoutLoc (proto->getDeclaredInterfaceType ()), isUnchecked)));
636
+ auto extension =
637
+ ExtensionDecl::create (ctx, SourceLoc (), nullptr , inherits,
638
+ nominal->getModuleScopeContext (), nullptr );
639
+ extension->setImplicit ();
640
+
641
+ // Build up synthesized DeclAttributes for the extension.
642
+ TinyPtrVector<const DeclAttribute *> attrs;
643
+ attrs.insert (attrs.end (), availability.begin (), availability.end ());
644
+ auto spiAttributes =
645
+ proto->getAttrs ().getAttributes <SPIAccessControlAttr>();
646
+ attrs.insert (attrs.end (), spiAttributes.begin (), spiAttributes.end ());
647
+ attrs.insert (attrs.end (), otherAttrs.begin (), otherAttrs.end ());
648
+
649
+ // Since DeclAttributes is a linked list where each added attribute becomes
650
+ // the head, we need to add these attributes in reverse order to reproduce
651
+ // the order in which previous implementations printed these attributes.
652
+ DeclAttributes declAttrs;
653
+ for (auto attr = attrs.rbegin (), end = attrs.rend (); attr != end; ++attr) {
654
+ declAttrs.add (const_cast <DeclAttribute *>(*attr));
655
+ }
656
+ extension->getAttrs () = declAttrs;
649
657
650
- printer << " {}" ;
651
- };
658
+ ctx.evaluator .cacheOutput (ExtendedTypeRequest{extension},
659
+ nominal->getDeclaredType ());
660
+ ctx.evaluator .cacheOutput (ExtendedNominalRequest{extension},
661
+ const_cast <NominalTypeDecl *>(nominal));
652
662
653
- printBody ();
654
- printer << " \n " ;
655
- }
663
+ extension->print (printer, printOptions);
664
+ printer << " \n " ;
656
665
}
657
666
658
667
// / If there were any conditional conformances that couldn't be printed,
0 commit comments