Skip to content

Commit 48b58eb

Browse files
committed
[AST] Introduce BraceStmt::getSingleActiveElement
Use this to replace `Parser::shouldReturnSingleExpressionElement`. This should be NFC.
1 parent ef46563 commit 48b58eb

File tree

6 files changed

+52
-54
lines changed

6 files changed

+52
-54
lines changed

include/swift/AST/Stmt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ class BraceStmt final : public Stmt,
212212

213213
ASTNode findAsyncNode();
214214

215+
/// If this brace contains a single ASTNode, or a \c #if that has a single active
216+
/// element, returns it. This will always be the last element of the brace.
217+
/// Otherwise returns \c nullptr.
218+
ASTNode getSingleActiveElement() const;
219+
215220
/// If this brace is wrapping a single expression, returns it. Otherwise
216221
/// returns \c nullptr.
217222
Expr *getSingleExpressionElement() const;

include/swift/Parse/Parser.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -691,11 +691,6 @@ class Parser {
691691
/// \param DiagText name for the string literal in the diagnostic.
692692
Optional<StringRef>
693693
getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText);
694-
695-
/// Returns true when body elements are eligible as single-expression implicit returns.
696-
///
697-
/// \param Body elements to search for implicit single-expression returns.
698-
bool shouldReturnSingleExpressionElement(ArrayRef<ASTNode> Body);
699694

700695
/// Returns true to indicate that experimental concurrency syntax should be
701696
/// parsed if the parser is generating only a syntax tree or if the user has

lib/AST/Stmt.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,31 @@ ASTNode BraceStmt::findAsyncNode() {
299299
return asyncFinder.getAsyncNode();
300300
}
301301

302+
static bool hasSingleActiveElement(ArrayRef<ASTNode> elts) {
303+
while (true) {
304+
// Single element brace.
305+
if (elts.size() == 1)
306+
return true;
307+
308+
// See if we have a #if as the first element of a 2 element brace, if so we
309+
// can recuse into its active clause. If so, the second element will be the
310+
// active element.
311+
if (elts.size() == 2) {
312+
if (auto *D = elts.front().dyn_cast<Decl *>()) {
313+
if (auto *ICD = dyn_cast<IfConfigDecl>(D)) {
314+
elts = ICD->getActiveClauseElements();
315+
continue;
316+
}
317+
}
318+
}
319+
return false;
320+
}
321+
}
322+
323+
ASTNode BraceStmt::getSingleActiveElement() const {
324+
return hasSingleActiveElement(getElements()) ? getLastElement() : nullptr;
325+
}
326+
302327
Expr *BraceStmt::getSingleExpressionElement() const {
303328
if (getElements().size() != 1)
304329
return nullptr;

lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8032,8 +8032,7 @@ Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) {
80328032
AFD->setHasSingleExpressionBody(false);
80338033
AFD->setBodyParsed(BS, fp);
80348034

8035-
if (Parser::shouldReturnSingleExpressionElement(BS->getElements())) {
8036-
auto Element = BS->getLastElement();
8035+
if (auto Element = BS->getSingleActiveElement()) {
80378036
if (auto *stmt = Element.dyn_cast<Stmt *>()) {
80388037
if (isa<FuncDecl>(AFD)) {
80398038
if (auto *returnStmt = dyn_cast<ReturnStmt>(stmt)) {

lib/Parse/ParseExpr.cpp

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2903,37 +2903,36 @@ ParserResult<Expr> Parser::parseExprClosure() {
29032903
closure->setParameterList(params);
29042904
closure->setHasAnonymousClosureVars();
29052905
}
2906-
2906+
2907+
auto *BS = BraceStmt::create(Context, leftBrace, bodyElements, rightBrace);
2908+
29072909
// If the body consists of a single expression, turn it into a return
29082910
// statement.
29092911
bool hasSingleExpressionBody = false;
2910-
if (!missingRBrace &&
2911-
Parser::shouldReturnSingleExpressionElement(bodyElements)) {
2912-
auto Element = bodyElements.back();
2913-
2914-
if (Element.is<Stmt *>()) {
2915-
if (auto returnStmt = dyn_cast<ReturnStmt>(Element.get<Stmt *>())) {
2916-
hasSingleExpressionBody = true;
2917-
if (!returnStmt->hasResult()) {
2918-
auto returnExpr = TupleExpr::createEmpty(Context,
2919-
SourceLoc(),
2920-
SourceLoc(),
2921-
/*implicit*/true);
2922-
returnStmt->setResult(returnExpr);
2912+
if (!missingRBrace) {
2913+
if (auto Element = BS->getSingleActiveElement()) {
2914+
if (Element.is<Stmt *>()) {
2915+
if (auto returnStmt = dyn_cast<ReturnStmt>(Element.get<Stmt *>())) {
2916+
hasSingleExpressionBody = true;
2917+
if (!returnStmt->hasResult()) {
2918+
auto returnExpr = TupleExpr::createEmpty(Context,
2919+
SourceLoc(),
2920+
SourceLoc(),
2921+
/*implicit*/true);
2922+
returnStmt->setResult(returnExpr);
2923+
}
29232924
}
2925+
} else if (Element.is<Expr *>()) {
2926+
// Create the wrapping return.
2927+
hasSingleExpressionBody = true;
2928+
auto returnExpr = Element.get<Expr*>();
2929+
BS->setLastElement(new (Context) ReturnStmt(SourceLoc(), returnExpr));
29242930
}
2925-
} else if (Element.is<Expr *>()) {
2926-
// Create the wrapping return.
2927-
hasSingleExpressionBody = true;
2928-
auto returnExpr = Element.get<Expr*>();
2929-
bodyElements.back() = new (Context) ReturnStmt(SourceLoc(), returnExpr);
29302931
}
29312932
}
29322933

29332934
// Set the body of the closure.
2934-
closure->setBody(BraceStmt::create(Context, leftBrace, bodyElements,
2935-
rightBrace),
2936-
hasSingleExpressionBody);
2935+
closure->setBody(BS, hasSingleExpressionBody);
29372936

29382937
// If the closure includes a capture list, create an AST node for it as well.
29392938
Expr *result = closure;

lib/Parse/Parser.cpp

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,31 +1096,6 @@ Parser::getStringLiteralIfNotInterpolated(SourceLoc Loc,
10961096
Segments.front().Length));
10971097
}
10981098

1099-
bool Parser::shouldReturnSingleExpressionElement(ArrayRef<ASTNode> Body) {
1100-
// If the body consists of an #if declaration with a single
1101-
// expression active clause, find a single expression.
1102-
if (Body.size() == 2) {
1103-
if (auto *D = Body.front().dyn_cast<Decl *>()) {
1104-
// Step into nested active clause.
1105-
while (auto *ICD = dyn_cast<IfConfigDecl>(D)) {
1106-
auto ACE = ICD->getActiveClauseElements();
1107-
if (ACE.size() == 1) {
1108-
assert(Body.back() == ACE.back() &&
1109-
"active clause not found in body");
1110-
return true;
1111-
} else if (ACE.size() == 2) {
1112-
if (auto *ND = ACE.front().dyn_cast<Decl *>()) {
1113-
D = ND;
1114-
continue;
1115-
}
1116-
}
1117-
break;
1118-
}
1119-
}
1120-
}
1121-
return Body.size() == 1;
1122-
}
1123-
11241099
struct ParserUnit::Implementation {
11251100
LangOptions LangOpts;
11261101
TypeCheckerOptions TypeCheckerOpts;

0 commit comments

Comments
 (0)