@@ -95,6 +95,109 @@ struct SimilarExprCollector : public SourceEntityWalker {
95
95
96
96
} // namespace
97
97
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
+
98
201
bool RefactoringActionExtractExprBase::performChange () {
99
202
// Check if the new name is ok.
100
203
if (!Lexer::isIdentifier (PreferredName)) {
0 commit comments