[PATCH] D39663: [clang-diff] Split source ranges at points where nodes are inserted.

Johannes Altmanninger via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sun Nov 5 11:55:25 PST 2017


johannes created this revision.
Herald added a subscriber: klimek.

This enables inserting into empty CompoundStmt nodes, for example.
Previously the insertion would occur only after the closing parenthesis.


https://reviews.llvm.org/D39663

Files:
  lib/Tooling/ASTDiff/ASTPatch.cpp
  unittests/Tooling/ASTPatchTest.cpp


Index: unittests/Tooling/ASTPatchTest.cpp
===================================================================
--- unittests/Tooling/ASTPatchTest.cpp
+++ unittests/Tooling/ASTPatchTest.cpp
@@ -262,4 +262,8 @@
         R"(void f() { })",
         R"(void f() { { int x = 2; } })",
         R"(void f() {  })");
+  PATCH(R"(void f() {;;} namespace {})",
+        R"(namespace { void f() {;;} })",
+        R"(void g() {;;} namespace {})",
+        R"(namespace { void g() {;;} })");
 }
Index: lib/Tooling/ASTDiff/ASTPatch.cpp
===================================================================
--- lib/Tooling/ASTDiff/ASTPatch.cpp
+++ lib/Tooling/ASTDiff/ASTPatch.cpp
@@ -79,12 +79,19 @@
 
   void addInsertion(PatchedTreeNode &PatchedNode, SourceLocation InsertionLoc) {
     addChildAt(PatchedNode, InsertionLoc);
+    SplitAt.emplace_back(InsertionLoc);
   }
   void addChild(PatchedTreeNode &PatchedNode) {
     SourceLocation InsertionLoc = PatchedNode.getSourceRange().getBegin();
     addChildAt(PatchedNode, InsertionLoc);
   }
 
+  // This returns an array of source ranges identical to the input,
+  // except whenever a SourceRange contains any of the locations in
+  // SplitAt, it is split up in two ranges at that location.
+  SmallVector<CharSourceRange, 4>
+  splitSourceRanges(ArrayRef<CharSourceRange> SourceRanges);
+
 private:
   void addChildAt(PatchedTreeNode &PatchedNode, SourceLocation InsertionLoc) {
     auto Less = makeTolerantLess(getTree().getSourceManager());
@@ -94,6 +101,8 @@
     Children.insert(Children.begin() + Offset, &PatchedNode);
     ChildrenLocations.insert(It, InsertionLoc);
   }
+
+  SmallVector<SourceLocation, 2> SplitAt;
 };
 } // end anonymous namespace
 
@@ -501,7 +510,7 @@
   unsigned ChildIndex = 0;
   auto MySourceRanges = PatchedNode.getOwnedSourceRanges();
   BeforeThanCompare<SourceLocation> MyLess(Tree.getSourceManager());
-  for (auto &MySubRange : MySourceRanges) {
+  for (auto &MySubRange : PatchedNode.splitSourceRanges(MySourceRanges)) {
     SourceLocation ChildBegin;
     SourceLocation InsertionBegin;
     while (ChildIndex < NumChildren &&
@@ -555,6 +564,36 @@
   return {-1, true};
 }
 
+static bool onlyWhitespace(StringRef Str) {
+  return std::all_of(Str.begin(), Str.end(),
+                     [](char C) { return std::isspace(C); });
+}
+
+SmallVector<CharSourceRange, 4>
+PatchedTreeNode::splitSourceRanges(ArrayRef<CharSourceRange> SourceRanges) {
+  SourceManager &SM = getTree().getSourceManager();
+  const LangOptions &LangOpts = getTree().getLangOpts();
+  SmallVector<CharSourceRange, 4> Result;
+  BeforeThanCompare<SourceLocation> Less(SM);
+  std::sort(SplitAt.begin(), SplitAt.end(), Less);
+  for (auto &Range : SourceRanges) {
+    SourceLocation Begin = Range.getBegin(), End = Range.getEnd();
+    for (auto SplitPoint : SplitAt) {
+      if (SM.isPointWithin(SplitPoint, Begin, End)) {
+        auto SplitRange = CharSourceRange::getCharRange(Begin, SplitPoint);
+        StringRef Text = Lexer::getSourceText(SplitRange, SM, LangOpts);
+        if (onlyWhitespace(Text))
+          continue;
+        Result.emplace_back(SplitRange);
+        Begin = SplitPoint;
+      }
+    }
+    if (Less(Begin, End))
+      Result.emplace_back(CharSourceRange::getCharRange(Begin, End));
+  }
+  return Result;
+}
+
 Error patch(RefactoringTool &TargetTool, SyntaxTree &Src, SyntaxTree &Dst,
             const ComparisonOptions &Options, bool Debug) {
   std::vector<std::unique_ptr<ASTUnit>> TargetASTs;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D39663.121657.patch
Type: text/x-patch
Size: 3495 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171105/f0eed3a8/attachment.bin>


More information about the cfe-commits mailing list