r372410 - [libTooling] Add `ifBound`, `elseBranch` RangeSelector combinators.

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 20 10:11:03 PDT 2019


Author: ymandel
Date: Fri Sep 20 10:11:03 2019
New Revision: 372410

URL: http://llvm.org/viewvc/llvm-project?rev=372410&view=rev
Log:
[libTooling] Add `ifBound`, `elseBranch` RangeSelector combinators.

Summary:
Adds two new combinators and corresponding tests to the RangeSelector library.
* `ifBound` -- conditional evaluation of range-selectors, based on whether a
   given node id is bound in the match.
* `elseBranch` -- selects the source range of the else and its statement.

Reviewers: gribozavr

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D67621

Modified:
    cfe/trunk/include/clang/Tooling/Refactoring/RangeSelector.h
    cfe/trunk/lib/Tooling/Refactoring/RangeSelector.cpp
    cfe/trunk/unittests/Tooling/RangeSelectorTest.cpp

Modified: cfe/trunk/include/clang/Tooling/Refactoring/RangeSelector.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/RangeSelector.h?rev=372410&r1=372409&r2=372410&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring/RangeSelector.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring/RangeSelector.h Fri Sep 20 10:11:03 2019
@@ -79,10 +79,19 @@ RangeSelector statements(std::string ID)
 // (all source between the braces).
 RangeSelector initListElements(std::string ID);
 
+/// Given an \IfStmt (bound to \p ID), selects the range of the else branch,
+/// starting from the \c else keyword.
+RangeSelector elseBranch(std::string ID);
+
 /// Selects the range from which `S` was expanded (possibly along with other
 /// source), if `S` is an expansion, and `S` itself, otherwise.  Corresponds to
 /// `SourceManager::getExpansionRange`.
 RangeSelector expansion(RangeSelector S);
+
+/// Chooses between the two selectors, based on whether \p ID is bound in the
+/// match.
+RangeSelector ifBound(std::string ID, RangeSelector TrueSelector,
+                      RangeSelector FalseSelector);
 } // namespace tooling
 } // namespace clang
 

Modified: cfe/trunk/lib/Tooling/Refactoring/RangeSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/RangeSelector.cpp?rev=372410&r1=372409&r2=372410&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring/RangeSelector.cpp (original)
+++ cfe/trunk/lib/Tooling/Refactoring/RangeSelector.cpp Fri Sep 20 10:11:03 2019
@@ -219,6 +219,9 @@ RangeSelector tooling::name(std::string
 }
 
 namespace {
+// FIXME: make this available in the public API for users to easily create their
+// own selectors.
+
 // Creates a selector from a range-selection function \p Func, which selects a
 // range that is relative to a bound node id.  \c T is the node type expected by
 // \p Func.
@@ -286,6 +289,19 @@ RangeSelector tooling::initListElements(
   return RelativeSelector<InitListExpr, getElementsRange>(std::move(ID));
 }
 
+namespace {
+// Returns the range of the else branch, including the `else` keyword.
+CharSourceRange getElseRange(const MatchResult &Result, const IfStmt &S) {
+  return maybeExtendRange(
+      CharSourceRange::getTokenRange(S.getElseLoc(), S.getEndLoc()),
+      tok::TokenKind::semi, *Result.Context);
+}
+} // namespace
+
+RangeSelector tooling::elseBranch(std::string ID) {
+  return RelativeSelector<IfStmt, getElseRange>(std::move(ID));
+}
+
 RangeSelector tooling::expansion(RangeSelector S) {
   return [S](const MatchResult &Result) -> Expected<CharSourceRange> {
     Expected<CharSourceRange> SRange = S(Result);
@@ -294,3 +310,11 @@ RangeSelector tooling::expansion(RangeSe
     return Result.SourceManager->getExpansionRange(*SRange);
   };
 }
+
+RangeSelector tooling::ifBound(std::string ID, RangeSelector TrueSelector,
+                               RangeSelector FalseSelector) {
+  return [=](const MatchResult &Result) {
+    auto &Map = Result.Nodes.getMap();
+    return (Map.find(ID) != Map.end() ? TrueSelector : FalseSelector)(Result);
+  };
+}

Modified: cfe/trunk/unittests/Tooling/RangeSelectorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RangeSelectorTest.cpp?rev=372410&r1=372409&r2=372410&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/RangeSelectorTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/RangeSelectorTest.cpp Fri Sep 20 10:11:03 2019
@@ -520,6 +520,35 @@ TEST(RangeSelectorTest, ElementsOpErrors
                        Failed<StringError>(withTypeErrorMessage("stmt")));
 }
 
+TEST(RangeSelectorTest, ElseBranchOpSingleStatement) {
+  StringRef Code = R"cc(
+    int f() {
+      int x = 0;
+      if (true) x = 3;
+      else x = 4;
+      return x + 5;
+    }
+  )cc";
+  StringRef ID = "id";
+  TestMatch Match = matchCode(Code, ifStmt().bind(ID));
+  EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match), HasValue("else x = 4;"));
+}
+
+TEST(RangeSelectorTest, ElseBranchOpCompoundStatement) {
+  StringRef Code = R"cc(
+    int f() {
+      int x = 0;
+      if (true) x = 3;
+      else { x = 4; }
+      return x + 5;
+    }
+  )cc";
+  StringRef ID = "id";
+  TestMatch Match = matchCode(Code, ifStmt().bind(ID));
+  EXPECT_THAT_EXPECTED(select(elseBranch(ID), Match),
+                       HasValue("else { x = 4; }"));
+}
+
 // Tests case where the matched node is the complete expanded text.
 TEST(RangeSelectorTest, ExpansionOp) {
   StringRef Code = R"cc(
@@ -546,4 +575,29 @@ TEST(RangeSelectorTest, ExpansionOpParti
                        HasValue("BADDECL(x * x)"));
 }
 
+TEST(RangeSelectorTest, IfBoundOpBound) {
+  StringRef Code = R"cc(
+    int f() {
+      return 3 + 5;
+    }
+  )cc";
+  StringRef ID = "id", Op = "op";
+  TestMatch Match =
+      matchCode(Code, binaryOperator(hasLHS(expr().bind(ID))).bind(Op));
+  EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
+                       HasValue("3"));
+}
+
+TEST(RangeSelectorTest, IfBoundOpUnbound) {
+  StringRef Code = R"cc(
+    int f() {
+      return 3 + 5;
+    }
+  )cc";
+  StringRef ID = "id", Op = "op";
+  TestMatch Match = matchCode(Code, binaryOperator().bind(Op));
+  EXPECT_THAT_EXPECTED(select(ifBound(ID, node(ID), node(Op)), Match),
+                       HasValue("3 + 5"));
+}
+
 } // namespace




More information about the cfe-commits mailing list