@@ -2068,6 +2068,211 @@ bool RefactoringActionExpandTernaryExpr::performChange() {
2068
2068
return false ; // don't abort
2069
2069
}
2070
2070
2071
+ bool RefactoringActionConvertIfLetExprToGuardExpr::
2072
+ isApplicable (ResolvedRangeInfo Info, DiagnosticEngine &Diag) {
2073
+
2074
+ if (Info.Kind != RangeKind::SingleStatement
2075
+ && Info.Kind != RangeKind::MultiStatement)
2076
+ return false ;
2077
+
2078
+ if (Info.ContainedNodes .empty ())
2079
+ return false ;
2080
+
2081
+ IfStmt *If = nullptr ;
2082
+
2083
+ if (Info.ContainedNodes .size () == 1 ) {
2084
+ if (auto S = Info.ContainedNodes [0 ].dyn_cast <Stmt*>()) {
2085
+ If = dyn_cast<IfStmt>(S);
2086
+ }
2087
+ }
2088
+
2089
+ if (!If)
2090
+ return false ;
2091
+
2092
+ auto CondList = If->getCond ();
2093
+
2094
+ if (CondList.size () == 1 ) {
2095
+ auto E = CondList[0 ];
2096
+ auto P = E.getKind ();
2097
+ if (P == swift::StmtConditionElement::CK_PatternBinding)
2098
+ return true ;
2099
+ }
2100
+
2101
+ return false ;
2102
+ }
2103
+
2104
+ bool RefactoringActionConvertIfLetExprToGuardExpr::performChange () {
2105
+
2106
+ IfStmt *If = nullptr ;
2107
+
2108
+ if (RangeInfo.ContainedNodes .size () == 1 ) {
2109
+ if (auto S = RangeInfo.ContainedNodes [0 ].dyn_cast <Stmt*>()) {
2110
+ If = dyn_cast<IfStmt>(S);
2111
+ }
2112
+ }
2113
+
2114
+ if (!If)
2115
+ return true ; // abort
2116
+
2117
+ auto CondList = If->getCond ();
2118
+
2119
+ if (CondList.size () != 1 )
2120
+ return true ; // abort
2121
+
2122
+ auto E = CondList[0 ];
2123
+ auto P = E.getPatternOrNull ();
2124
+ if (!P)
2125
+ return true ; // abort
2126
+
2127
+ // Get if-let condition
2128
+ SourceRange range = E.getSourceRange ();
2129
+ SourceManager &SM = RangeInfo.RangeContext ->getASTContext ().SourceMgr ;
2130
+ auto CondCharRange = Lexer::getCharSourceRangeFromSourceRange (SM, range);
2131
+
2132
+ auto Body = dyn_cast_or_null<BraceStmt>(If->getThenStmt ());
2133
+
2134
+ if (!Body)
2135
+ return true ; // abort
2136
+
2137
+ // Get if-let then body.
2138
+ auto firstElement = Body->getElements ()[0 ];
2139
+ auto lastElement = Body->getElements ().back ();
2140
+ SourceRange bodyRange = firstElement.getSourceRange ();
2141
+ bodyRange.widen (lastElement.getSourceRange ());
2142
+ auto BodyCharRange = Lexer::getCharSourceRangeFromSourceRange (SM, bodyRange);
2143
+
2144
+ llvm::SmallString<64 > DeclBuffer;
2145
+ llvm::raw_svector_ostream OS (DeclBuffer);
2146
+
2147
+ llvm::StringRef Space = " " ;
2148
+ llvm::StringRef NewLine = " \n " ;
2149
+
2150
+ OS << tok::kw_guard << Space;
2151
+ OS << CondCharRange.str ().str () << Space;
2152
+ OS << tok::kw_else << Space;
2153
+ OS << tok::l_brace << NewLine;
2154
+
2155
+ // Get if-let else body.
2156
+ auto ElseBody = dyn_cast_or_null<BraceStmt>(If->getElseStmt ());
2157
+ if (ElseBody) {
2158
+ auto firstElseElement = ElseBody->getElements ()[0 ];
2159
+ auto lastElseElement = ElseBody->getElements ().back ();
2160
+ SourceRange elseBodyRange = firstElseElement.getSourceRange ();
2161
+ elseBodyRange.widen (lastElseElement.getSourceRange ());
2162
+ auto ElseBodyCharRange = Lexer::getCharSourceRangeFromSourceRange (SM, elseBodyRange);
2163
+ OS << ElseBodyCharRange.str ().str () << NewLine;
2164
+ }
2165
+
2166
+ OS << tok::kw_return << NewLine;
2167
+ OS << tok::r_brace << NewLine;
2168
+ OS << BodyCharRange.str ().str ();
2169
+
2170
+ // Replace if-let to guard
2171
+ auto ReplaceRange = RangeInfo.ContentRange ;
2172
+ EditConsumer.accept (SM, ReplaceRange, DeclBuffer.str ());
2173
+
2174
+ return false ;
2175
+ }
2176
+
2177
+ bool RefactoringActionConvertGuardExprToIfLetExpr::
2178
+ isApplicable (ResolvedRangeInfo Info, DiagnosticEngine &Diag) {
2179
+ if (Info.Kind != RangeKind::SingleStatement
2180
+ && Info.Kind != RangeKind::MultiStatement)
2181
+ return false ;
2182
+
2183
+ if (Info.ContainedNodes .empty ())
2184
+ return false ;
2185
+
2186
+ GuardStmt *guardStmt = nullptr ;
2187
+
2188
+ if (Info.ContainedNodes .size () > 0 ) {
2189
+ if (auto S = Info.ContainedNodes [0 ].dyn_cast <Stmt*>()) {
2190
+ guardStmt = dyn_cast<GuardStmt>(S);
2191
+ }
2192
+ }
2193
+
2194
+ if (!guardStmt)
2195
+ return false ;
2196
+
2197
+ auto CondList = guardStmt->getCond ();
2198
+
2199
+ if (CondList.size () == 1 ) {
2200
+ auto E = CondList[0 ];
2201
+ auto P = E.getKind ();
2202
+ if (P == swift::StmtConditionElement::CK_PatternBinding)
2203
+ return true ;
2204
+ }
2205
+
2206
+ return false ;
2207
+ }
2208
+
2209
+ bool RefactoringActionConvertGuardExprToIfLetExpr::performChange () {
2210
+
2211
+ // Get guard stmt
2212
+ GuardStmt *Guard = nullptr ;
2213
+ if (RangeInfo.ContainedNodes .size () > 0 ) {
2214
+ if (auto S = RangeInfo.ContainedNodes [0 ].dyn_cast <Stmt*>()) {
2215
+ Guard = dyn_cast<GuardStmt>(S);
2216
+ }
2217
+ }
2218
+ if (!Guard)
2219
+ return true ; // abort
2220
+
2221
+ // Get guard condition
2222
+ auto CondList = Guard->getCond ();
2223
+ if (CondList.size () != 1 )
2224
+ return true ; // abort
2225
+
2226
+ auto E = CondList[0 ];
2227
+ auto P = E.getPatternOrNull ();
2228
+ if (!P)
2229
+ return true ; // abort
2230
+
2231
+ // Get guard condition source
2232
+ SourceRange range = E.getSourceRange ();
2233
+ SourceManager &SM = RangeInfo.RangeContext ->getASTContext ().SourceMgr ;
2234
+ auto CondCharRange = Lexer::getCharSourceRangeFromSourceRange (SM, range);
2235
+
2236
+ llvm::SmallString<64 > DeclBuffer;
2237
+ llvm::raw_svector_ostream OS (DeclBuffer);
2238
+
2239
+ llvm::StringRef Space = " " ;
2240
+ llvm::StringRef NewLine = " \n " ;
2241
+
2242
+ OS << tok::kw_if << Space;
2243
+ OS << CondCharRange.str ().str () << Space;
2244
+ OS << tok::l_brace << NewLine;
2245
+
2246
+ // Get nodes after guard to place them at if-let body
2247
+ if (RangeInfo.ContainedNodes .size () > 1 ) {
2248
+ auto S = RangeInfo.ContainedNodes [1 ].getSourceRange ();
2249
+ S.widen (RangeInfo.ContainedNodes .back ().getSourceRange ());
2250
+ auto BodyCharRange = Lexer::getCharSourceRangeFromSourceRange (SM, S);
2251
+ OS << BodyCharRange.str ().str () << NewLine;
2252
+ }
2253
+ OS << tok::r_brace;
2254
+
2255
+ // Get guard body
2256
+ auto Body = dyn_cast_or_null<BraceStmt>(Guard->getBody ());
2257
+
2258
+ if (Body && Body->getElements ().size () > 1 ) {
2259
+ auto firstElement = Body->getElements ()[0 ];
2260
+ auto lastElement = Body->getElements ().back ();
2261
+ SourceRange bodyRange = firstElement.getSourceRange ();
2262
+ bodyRange.widen (lastElement.getSourceRange ());
2263
+ auto BodyCharRange = Lexer::getCharSourceRangeFromSourceRange (SM, bodyRange);
2264
+ OS << Space << tok::kw_else << Space << tok::l_brace << NewLine;
2265
+ OS << BodyCharRange.str ().str () << NewLine;
2266
+ OS << tok::r_brace;
2267
+ }
2268
+
2269
+ // Replace guard to if-let
2270
+ auto ReplaceRange = RangeInfo.ContentRange ;
2271
+ EditConsumer.accept (SM, ReplaceRange, DeclBuffer.str ());
2272
+
2273
+ return false ;
2274
+ }
2275
+
2071
2276
// / Struct containing info about an IfStmt that can be converted into an IfExpr.
2072
2277
struct ConvertToTernaryExprInfo {
2073
2278
ConvertToTernaryExprInfo () {}
0 commit comments