[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