Skip to content

Commit 98f4019

Browse files
committed
[Refactoring] Move ExtractFunction to its own file
1 parent d7ada70 commit 98f4019

File tree

7 files changed

+434
-404
lines changed

7 files changed

+434
-404
lines changed

lib/Refactoring/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ add_swift_host_library(swiftRefactoring STATIC
66
ConvertToSwitchStmt.cpp
77
ConvertToTernaryExpr.cpp
88
ExtractRepeatedExpr.cpp
9+
ExtractFunction.cpp
910
MoveMembersToExtension.cpp
1011
Refactoring.cpp
1112
Renamer.cpp

lib/Refactoring/ExtractExprBase.cpp

+103
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,109 @@ struct SimilarExprCollector : public SourceEntityWalker {
9595

9696
} // namespace
9797

98+
ExtractCheckResult
99+
swift::refactoring::checkExtractConditions(const ResolvedRangeInfo &RangeInfo,
100+
DiagnosticEngine &DiagEngine) {
101+
SmallVector<CannotExtractReason, 2> AllReasons;
102+
// If any declared declaration is referred out of the given range, return
103+
// false.
104+
auto Declared = RangeInfo.DeclaredDecls;
105+
auto It = std::find_if(Declared.begin(), Declared.end(),
106+
[](DeclaredDecl DD) { return DD.ReferredAfterRange; });
107+
if (It != Declared.end()) {
108+
DiagEngine.diagnose(It->VD->getLoc(),
109+
diag::value_decl_referenced_out_of_range,
110+
It->VD->getName());
111+
return ExtractCheckResult();
112+
}
113+
114+
// We cannot extract a range with multi entry points.
115+
if (!RangeInfo.HasSingleEntry) {
116+
DiagEngine.diagnose(SourceLoc(), diag::multi_entry_range);
117+
return ExtractCheckResult();
118+
}
119+
120+
// We cannot extract code that is not sure to exit or not.
121+
if (RangeInfo.exit() == ExitState::Unsure) {
122+
return ExtractCheckResult();
123+
}
124+
125+
// We cannot extract expressions of l-value type.
126+
if (auto Ty = RangeInfo.getType()) {
127+
if (Ty->hasLValueType() || Ty->is<InOutType>())
128+
return ExtractCheckResult();
129+
130+
// Disallow extracting error type expressions/statements
131+
// FIXME: diagnose what happened?
132+
if (Ty->hasError())
133+
return ExtractCheckResult();
134+
135+
if (Ty->isVoid()) {
136+
AllReasons.emplace_back(CannotExtractReason::VoidType);
137+
}
138+
}
139+
140+
// We cannot extract a range with orphaned loop keyword.
141+
switch (RangeInfo.Orphan) {
142+
case swift::ide::OrphanKind::Continue:
143+
DiagEngine.diagnose(SourceLoc(), diag::orphan_loop_keyword, "continue");
144+
return ExtractCheckResult();
145+
case swift::ide::OrphanKind::Break:
146+
DiagEngine.diagnose(SourceLoc(), diag::orphan_loop_keyword, "break");
147+
return ExtractCheckResult();
148+
case swift::ide::OrphanKind::None:
149+
break;
150+
}
151+
152+
// Guard statement can not be extracted.
153+
if (llvm::any_of(RangeInfo.ContainedNodes,
154+
[](ASTNode N) { return N.isStmt(StmtKind::Guard); })) {
155+
return ExtractCheckResult();
156+
}
157+
158+
// Disallow extracting certain kinds of statements.
159+
if (RangeInfo.Kind == RangeKind::SingleStatement) {
160+
Stmt *S = RangeInfo.ContainedNodes[0].get<Stmt *>();
161+
162+
// These aren't independent statement.
163+
if (isa<BraceStmt>(S) || isa<CaseStmt>(S))
164+
return ExtractCheckResult();
165+
}
166+
167+
// Disallow extracting literals.
168+
if (RangeInfo.Kind == RangeKind::SingleExpression) {
169+
Expr *E = RangeInfo.ContainedNodes[0].get<Expr *>();
170+
171+
// Until implementing the performChange() part of extracting trailing
172+
// closures, we disable them for now.
173+
if (isa<AbstractClosureExpr>(E))
174+
return ExtractCheckResult();
175+
176+
if (isa<LiteralExpr>(E))
177+
AllReasons.emplace_back(CannotExtractReason::Literal);
178+
}
179+
180+
switch (RangeInfo.RangeContext->getContextKind()) {
181+
case swift::DeclContextKind::Initializer:
182+
case swift::DeclContextKind::SubscriptDecl:
183+
case swift::DeclContextKind::EnumElementDecl:
184+
case swift::DeclContextKind::AbstractFunctionDecl:
185+
case swift::DeclContextKind::AbstractClosureExpr:
186+
case swift::DeclContextKind::TopLevelCodeDecl:
187+
break;
188+
189+
case swift::DeclContextKind::SerializedLocal:
190+
case swift::DeclContextKind::Package:
191+
case swift::DeclContextKind::Module:
192+
case swift::DeclContextKind::FileUnit:
193+
case swift::DeclContextKind::GenericTypeDecl:
194+
case swift::DeclContextKind::ExtensionDecl:
195+
case swift::DeclContextKind::MacroDecl:
196+
return ExtractCheckResult();
197+
}
198+
return ExtractCheckResult(AllReasons);
199+
}
200+
98201
bool RefactoringActionExtractExprBase::performChange() {
99202
// Check if the new name is ok.
100203
if (!Lexer::isIdentifier(PreferredName)) {

lib/Refactoring/ExtractExprBase.h

+3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ class ExtractCheckResult {
4747
}
4848
};
4949

50+
/// Check whether a given range can be extracted.
51+
/// Return true on successful condition checking,.
52+
/// Return false on failed conditions.
5053
ExtractCheckResult checkExtractConditions(const ResolvedRangeInfo &RangeInfo,
5154
DiagnosticEngine &DiagEngine);
5255

0 commit comments

Comments
 (0)