Skip to content

Commit ef4ee95

Browse files
committed
[Refactoring] Move FillProtocolStubs to its own file
1 parent d09be61 commit ef4ee95

File tree

3 files changed

+147
-128
lines changed

3 files changed

+147
-128
lines changed

lib/Refactoring/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_swift_host_library(swiftRefactoring STATIC
1010
ExtractExprBase.cpp
1111
ExtractRepeatedExpr.cpp
1212
ExtractFunction.cpp
13+
FillProtocolStubs.cpp
1314
MoveMembersToExtension.cpp
1415
Refactoring.cpp
1516
Renamer.cpp

lib/Refactoring/FillProtocolStubs.cpp

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "RefactoringActions.h"
14+
#include "swift/AST/ProtocolConformance.h"
15+
16+
using namespace swift::refactoring;
17+
18+
namespace {
19+
/// The helper class analyzes a given nominal decl or an extension decl to
20+
/// decide whether stubs are required to filled in and the context in which
21+
/// these stubs should be filled.
22+
class FillProtocolStubContext {
23+
24+
std::vector<ValueDecl *>
25+
getUnsatisfiedRequirements(const IterableDeclContext *IDC);
26+
27+
/// Context in which the content should be filled; this could be either a
28+
/// nominal type declaraion or an extension declaration.
29+
DeclContext *DC;
30+
31+
/// The type that adopts the required protocol stubs. For nominal type decl,
32+
/// this should be the declared type itself; for extension decl, this should
33+
/// be the extended type at hand.
34+
Type Adopter;
35+
36+
/// The start location of the decl, either nominal type or extension, for the
37+
/// printer to figure out the right indentation.
38+
SourceLoc StartLoc;
39+
40+
/// The location of '{' for the decl, thus we know where to insert the filling
41+
/// stubs.
42+
SourceLoc BraceStartLoc;
43+
44+
/// The value decls that should be satisfied; this could be either function
45+
/// decls, property decls, or required type alias.
46+
std::vector<ValueDecl *> FillingContents;
47+
48+
public:
49+
FillProtocolStubContext(ExtensionDecl *ED)
50+
: DC(ED), Adopter(ED->getExtendedType()), StartLoc(ED->getStartLoc()),
51+
BraceStartLoc(ED->getBraces().Start),
52+
FillingContents(getUnsatisfiedRequirements(ED)){};
53+
54+
FillProtocolStubContext(NominalTypeDecl *ND)
55+
: DC(ND), Adopter(ND->getDeclaredType()), StartLoc(ND->getStartLoc()),
56+
BraceStartLoc(ND->getBraces().Start),
57+
FillingContents(getUnsatisfiedRequirements(ND)){};
58+
59+
FillProtocolStubContext() : DC(nullptr), Adopter(), FillingContents({}){};
60+
61+
static FillProtocolStubContext
62+
getContextFromCursorInfo(ResolvedCursorInfoPtr Tok);
63+
64+
ArrayRef<ValueDecl *> getFillingContents() const {
65+
return llvm::makeArrayRef(FillingContents);
66+
}
67+
68+
DeclContext *getFillingContext() const { return DC; }
69+
70+
bool canProceed() const {
71+
return StartLoc.isValid() && BraceStartLoc.isValid() &&
72+
!getFillingContents().empty();
73+
}
74+
75+
Type getAdopter() const { return Adopter; }
76+
SourceLoc getContextStartLoc() const { return StartLoc; }
77+
SourceLoc getBraceStartLoc() const { return BraceStartLoc; }
78+
};
79+
80+
FillProtocolStubContext FillProtocolStubContext::getContextFromCursorInfo(
81+
ResolvedCursorInfoPtr CursorInfo) {
82+
if (!CursorInfo->isValid())
83+
return FillProtocolStubContext();
84+
auto ValueRefInfo = dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
85+
if (!ValueRefInfo) {
86+
return FillProtocolStubContext();
87+
}
88+
if (!ValueRefInfo->isRef()) {
89+
// If the type name is on the declared nominal, e.g. "class A {}"
90+
if (auto ND = dyn_cast<NominalTypeDecl>(ValueRefInfo->getValueD())) {
91+
return FillProtocolStubContext(ND);
92+
}
93+
} else if (auto *ED = ValueRefInfo->getExtTyRef()) {
94+
// If the type ref is on a declared extension, e.g. "extension A {}"
95+
return FillProtocolStubContext(ED);
96+
}
97+
return FillProtocolStubContext();
98+
}
99+
} // namespace
100+
101+
std::vector<ValueDecl *> FillProtocolStubContext::getUnsatisfiedRequirements(
102+
const IterableDeclContext *IDC) {
103+
// The results to return.
104+
std::vector<ValueDecl *> NonWitnessedReqs;
105+
106+
// For each conformance of the extended nominal.
107+
for (ProtocolConformance *Con : IDC->getLocalConformances()) {
108+
109+
// Collect non-witnessed requirements.
110+
Con->forEachNonWitnessedRequirement(
111+
[&](ValueDecl *VD) { NonWitnessedReqs.push_back(VD); });
112+
}
113+
114+
return NonWitnessedReqs;
115+
}
116+
117+
bool RefactoringActionFillProtocolStub::isApplicable(ResolvedCursorInfoPtr Tok,
118+
DiagnosticEngine &Diag) {
119+
return FillProtocolStubContext::getContextFromCursorInfo(Tok).canProceed();
120+
}
121+
122+
bool RefactoringActionFillProtocolStub::performChange() {
123+
// Get the filling protocol context from the input token.
124+
FillProtocolStubContext Context =
125+
FillProtocolStubContext::getContextFromCursorInfo(CursorInfo);
126+
127+
assert(Context.canProceed());
128+
assert(!Context.getFillingContents().empty());
129+
assert(Context.getFillingContext());
130+
SmallString<128> Text;
131+
{
132+
llvm::raw_svector_ostream SS(Text);
133+
Type Adopter = Context.getAdopter();
134+
SourceLoc Loc = Context.getContextStartLoc();
135+
auto Contents = Context.getFillingContents();
136+
137+
// For each unsatisfied requirement, print the stub to the buffer.
138+
std::for_each(Contents.begin(), Contents.end(), [&](ValueDecl *VD) {
139+
printRequirementStub(VD, Context.getFillingContext(), Adopter, Loc, SS);
140+
});
141+
}
142+
143+
// Insert all stubs after '{' in the extension/nominal type decl.
144+
EditConsumer.insertAfter(SM, Context.getBraceStartLoc(), Text);
145+
return false;
146+
}

lib/Refactoring/Refactoring.cpp

Lines changed: 0 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -545,134 +545,6 @@ StringRef getDefaultPreferredName(RefactoringKind Kind) {
545545
}
546546
}
547547

548-
/// The helper class analyzes a given nominal decl or an extension decl to
549-
/// decide whether stubs are required to filled in and the context in which
550-
/// these stubs should be filled.
551-
class FillProtocolStubContext {
552-
553-
std::vector<ValueDecl*>
554-
getUnsatisfiedRequirements(const IterableDeclContext *IDC);
555-
556-
/// Context in which the content should be filled; this could be either a
557-
/// nominal type declaraion or an extension declaration.
558-
DeclContext *DC;
559-
560-
/// The type that adopts the required protocol stubs. For nominal type decl, this
561-
/// should be the declared type itself; for extension decl, this should be the
562-
/// extended type at hand.
563-
Type Adopter;
564-
565-
/// The start location of the decl, either nominal type or extension, for the
566-
/// printer to figure out the right indentation.
567-
SourceLoc StartLoc;
568-
569-
/// The location of '{' for the decl, thus we know where to insert the filling
570-
/// stubs.
571-
SourceLoc BraceStartLoc;
572-
573-
/// The value decls that should be satisfied; this could be either function
574-
/// decls, property decls, or required type alias.
575-
std::vector<ValueDecl*> FillingContents;
576-
577-
public:
578-
FillProtocolStubContext(ExtensionDecl *ED) : DC(ED),
579-
Adopter(ED->getExtendedType()), StartLoc(ED->getStartLoc()),
580-
BraceStartLoc(ED->getBraces().Start),
581-
FillingContents(getUnsatisfiedRequirements(ED)) {};
582-
583-
FillProtocolStubContext(NominalTypeDecl *ND) : DC(ND),
584-
Adopter(ND->getDeclaredType()), StartLoc(ND->getStartLoc()),
585-
BraceStartLoc(ND->getBraces().Start),
586-
FillingContents(getUnsatisfiedRequirements(ND)) {};
587-
588-
FillProtocolStubContext() : DC(nullptr), Adopter(), FillingContents({}) {};
589-
590-
static FillProtocolStubContext
591-
getContextFromCursorInfo(ResolvedCursorInfoPtr Tok);
592-
593-
ArrayRef<ValueDecl*> getFillingContents() const {
594-
return llvm::makeArrayRef(FillingContents);
595-
}
596-
597-
DeclContext *getFillingContext() const { return DC; }
598-
599-
bool canProceed() const {
600-
return StartLoc.isValid() && BraceStartLoc.isValid() &&
601-
!getFillingContents().empty();
602-
}
603-
604-
Type getAdopter() const { return Adopter; }
605-
SourceLoc getContextStartLoc() const { return StartLoc; }
606-
SourceLoc getBraceStartLoc() const { return BraceStartLoc; }
607-
};
608-
609-
FillProtocolStubContext FillProtocolStubContext::getContextFromCursorInfo(
610-
ResolvedCursorInfoPtr CursorInfo) {
611-
if (!CursorInfo->isValid())
612-
return FillProtocolStubContext();
613-
auto ValueRefInfo = dyn_cast<ResolvedValueRefCursorInfo>(CursorInfo);
614-
if (!ValueRefInfo) {
615-
return FillProtocolStubContext();
616-
}
617-
if (!ValueRefInfo->isRef()) {
618-
// If the type name is on the declared nominal, e.g. "class A {}"
619-
if (auto ND = dyn_cast<NominalTypeDecl>(ValueRefInfo->getValueD())) {
620-
return FillProtocolStubContext(ND);
621-
}
622-
} else if (auto *ED = ValueRefInfo->getExtTyRef()) {
623-
// If the type ref is on a declared extension, e.g. "extension A {}"
624-
return FillProtocolStubContext(ED);
625-
}
626-
return FillProtocolStubContext();
627-
}
628-
629-
std::vector<ValueDecl*> FillProtocolStubContext::
630-
getUnsatisfiedRequirements(const IterableDeclContext *IDC) {
631-
// The results to return.
632-
std::vector<ValueDecl*> NonWitnessedReqs;
633-
634-
// For each conformance of the extended nominal.
635-
for(ProtocolConformance *Con : IDC->getLocalConformances()) {
636-
637-
// Collect non-witnessed requirements.
638-
Con->forEachNonWitnessedRequirement(
639-
[&](ValueDecl *VD) { NonWitnessedReqs.push_back(VD); });
640-
}
641-
642-
return NonWitnessedReqs;
643-
}
644-
645-
bool RefactoringActionFillProtocolStub::isApplicable(ResolvedCursorInfoPtr Tok,
646-
DiagnosticEngine &Diag) {
647-
return FillProtocolStubContext::getContextFromCursorInfo(Tok).canProceed();
648-
}
649-
650-
bool RefactoringActionFillProtocolStub::performChange() {
651-
// Get the filling protocol context from the input token.
652-
FillProtocolStubContext Context = FillProtocolStubContext::
653-
getContextFromCursorInfo(CursorInfo);
654-
655-
assert(Context.canProceed());
656-
assert(!Context.getFillingContents().empty());
657-
assert(Context.getFillingContext());
658-
SmallString<128> Text;
659-
{
660-
llvm::raw_svector_ostream SS(Text);
661-
Type Adopter = Context.getAdopter();
662-
SourceLoc Loc = Context.getContextStartLoc();
663-
auto Contents = Context.getFillingContents();
664-
665-
// For each unsatisfied requirement, print the stub to the buffer.
666-
std::for_each(Contents.begin(), Contents.end(), [&](ValueDecl *VD) {
667-
printRequirementStub(VD, Context.getFillingContext(), Adopter, Loc, SS);
668-
});
669-
}
670-
671-
// Insert all stubs after '{' in the extension/nominal type decl.
672-
EditConsumer.insertAfter(SM, Context.getBraceStartLoc(), Text);
673-
return false;
674-
}
675-
676548
static SmallVector<RefactorAvailabilityInfo, 0>
677549
collectRefactoringsAtCursor(SourceFile *SF, unsigned Line, unsigned Column,
678550
ArrayRef<DiagnosticConsumer *> DiagConsumers) {

0 commit comments

Comments
 (0)