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