@@ -1668,109 +1668,70 @@ bool RefactoringActionReplaceBodiesWithFatalError::performChange() {
1668
1668
return false ;
1669
1669
}
1670
1670
1671
- struct CollapsibleNestedIfInfo {
1672
- IfStmt *OuterIf;
1673
- IfStmt *InnerIf;
1674
- bool FinishedOuterIf;
1675
- bool FoundNonCollapsibleItem;
1676
- CollapsibleNestedIfInfo ():
1677
- OuterIf (nullptr ), InnerIf(nullptr ),
1678
- FinishedOuterIf (false ), FoundNonCollapsibleItem(false ) {}
1679
- bool isValid () {
1680
- return OuterIf && InnerIf && FinishedOuterIf && !FoundNonCollapsibleItem;
1681
- }
1682
- };
1683
-
1684
- static CollapsibleNestedIfInfo findCollapseNestedIfTarget (ResolvedCursorInfo CursorInfo) {
1671
+ static std::pair<IfStmt *, IfStmt *>
1672
+ findCollapseNestedIfTarget (ResolvedCursorInfo CursorInfo) {
1685
1673
if (CursorInfo.Kind != CursorInfoKind::StmtStart)
1686
- return CollapsibleNestedIfInfo ();
1687
- struct IfStmtFinder : public SourceEntityWalker {
1688
- SourceLoc StartLoc;
1689
- CollapsibleNestedIfInfo IfInfo;
1690
- IfStmtFinder (SourceLoc StartLoc): StartLoc(StartLoc), IfInfo() {}
1691
- bool finishedInnerIfButNotFinishedOuterIf () {
1692
- return IfInfo.InnerIf && !IfInfo.FinishedOuterIf ;
1693
- }
1694
- bool walkToStmtPre (Stmt *S) {
1695
- if (finishedInnerIfButNotFinishedOuterIf ()) {
1696
- IfInfo.FoundNonCollapsibleItem = true ;
1697
- return false ;
1698
- }
1674
+ return {};
1699
1675
1700
- bool StmtIsOuterIfBrace =
1701
- IfInfo.OuterIf && !IfInfo.InnerIf && S->getKind () == StmtKind::Brace;
1702
- if (StmtIsOuterIfBrace) {
1703
- return true ;
1704
- }
1676
+ // Ensure the statement is 'if' statement. It must not have 'else' clause.
1677
+ IfStmt *OuterIf = dyn_cast<IfStmt>(CursorInfo.TrailingStmt );
1678
+ if (!OuterIf)
1679
+ return {};
1680
+ if (OuterIf->getElseStmt ())
1681
+ return {};
1705
1682
1706
- auto *IFS = dyn_cast<IfStmt>(S);
1707
- if (!IFS) {
1708
- return false ;
1709
- }
1710
- if (!IfInfo.OuterIf ) {
1711
- IfInfo.OuterIf = IFS;
1712
- return true ;
1713
- } else {
1714
- IfInfo.InnerIf = IFS;
1715
- return false ;
1716
- }
1717
- }
1718
- bool walkToStmtPost (Stmt *S) {
1719
- assert (S != IfInfo.InnerIf && " Should not traverse inner if statement" );
1720
- if (S == IfInfo.OuterIf ) {
1721
- IfInfo.FinishedOuterIf = true ;
1722
- }
1723
- return true ;
1724
- }
1725
- bool walkToDeclPre (Decl *D, CharSourceRange Range) {
1726
- if (finishedInnerIfButNotFinishedOuterIf ()) {
1727
- IfInfo.FoundNonCollapsibleItem = true ;
1728
- return false ;
1729
- }
1730
- return true ;
1731
- }
1732
- bool walkToExprPre (Expr *E) {
1733
- if (finishedInnerIfButNotFinishedOuterIf ()) {
1734
- IfInfo.FoundNonCollapsibleItem = true ;
1735
- return false ;
1736
- }
1737
- return true ;
1738
- }
1683
+ // The body must contain a sole inner 'if' statement.
1684
+ auto Body = dyn_cast_or_null<BraceStmt>(OuterIf->getThenStmt ());
1685
+ if (!Body || Body->getNumElements () != 1 )
1686
+ return {};
1687
+
1688
+ IfStmt *InnerIf =
1689
+ dyn_cast_or_null<IfStmt>(Body->getElement (0 ).dyn_cast <Stmt *>());
1690
+ if (!InnerIf)
1691
+ return {};
1739
1692
1740
- } Walker (CursorInfo.TrailingStmt ->getStartLoc ());
1741
- Walker.walk (CursorInfo.TrailingStmt );
1742
- return Walker.IfInfo ;
1693
+ // Inner 'if' statement also cannot have 'else' clause.
1694
+ if (InnerIf->getElseStmt ())
1695
+ return {};
1696
+
1697
+ return {OuterIf, InnerIf};
1743
1698
}
1744
1699
1745
- bool RefactoringActionCollapseNestedIfExpr ::
1746
- isApplicable (ResolvedCursorInfo Tok , DiagnosticEngine &Diag) {
1747
- return findCollapseNestedIfTarget (Tok). isValid () ;
1700
+ bool RefactoringActionCollapseNestedIfStmt ::
1701
+ isApplicable (ResolvedCursorInfo CursorInfo , DiagnosticEngine &Diag) {
1702
+ return findCollapseNestedIfTarget (CursorInfo). first ;
1748
1703
}
1749
1704
1750
- bool RefactoringActionCollapseNestedIfExpr ::performChange () {
1705
+ bool RefactoringActionCollapseNestedIfStmt ::performChange () {
1751
1706
auto Target = findCollapseNestedIfTarget (CursorInfo);
1752
- if (!Target.isValid () )
1707
+ if (!Target.first )
1753
1708
return true ;
1754
- auto OuterIfConds = Target.OuterIf -> getCond (). vec () ;
1755
- auto InnerIfConds = Target.InnerIf -> getCond (). vec () ;
1709
+ auto OuterIf = Target.first ;
1710
+ auto InnerIf = Target.second ;
1756
1711
1757
- EditorConsumerInsertStream OS (EditConsumer, SM,
1758
- Lexer::getCharSourceRangeFromSourceRange (
1759
- SM, Target.OuterIf ->getSourceRange ()));
1760
-
1761
- OS << tok::kw_if << " " ;
1762
- for (auto CI = OuterIfConds.begin (); CI != OuterIfConds.end (); ++CI) {
1763
- OS << (CI != OuterIfConds.begin () ? " , " : " " );
1764
- OS << Lexer::getCharSourceRangeFromSourceRange (
1765
- SM, CI->getSourceRange ()).str ();
1766
- }
1767
- for (auto CI = InnerIfConds.begin (); CI != InnerIfConds.end (); ++CI) {
1768
- OS << " , " << Lexer::getCharSourceRangeFromSourceRange (
1769
- SM, CI->getSourceRange ()).str ();
1770
- }
1771
- auto ThenStatementText = Lexer::getCharSourceRangeFromSourceRange (
1772
- SM, Target.InnerIf ->getThenStmt ()->getSourceRange ()).str ();
1773
- OS << " " << ThenStatementText;
1712
+ EditorConsumerInsertStream OS (
1713
+ EditConsumer, SM,
1714
+ Lexer::getCharSourceRangeFromSourceRange (SM, OuterIf->getSourceRange ()));
1715
+
1716
+ OS << tok::kw_if << " " ;
1717
+
1718
+ // Emit conditions.
1719
+ bool first = true ;
1720
+ for (auto &C : llvm::concat<StmtConditionElement>(OuterIf->getCond (),
1721
+ InnerIf->getCond ())) {
1722
+ if (first)
1723
+ first = false ;
1724
+ else
1725
+ OS << " , " ;
1726
+ OS << Lexer::getCharSourceRangeFromSourceRange (SM, C.getSourceRange ())
1727
+ .str ();
1728
+ }
1729
+
1730
+ // Emit body.
1731
+ OS << " " ;
1732
+ OS << Lexer::getCharSourceRangeFromSourceRange (
1733
+ SM, InnerIf->getThenStmt ()->getSourceRange ())
1734
+ .str ();
1774
1735
return false ;
1775
1736
}
1776
1737
0 commit comments