diff options
author | Manuel Klimek <klimek@google.com> | 2016-03-01 12:37:30 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2016-03-01 12:37:30 +0000 |
commit | b12e5a5ccd8e5ca71a3722a4b5103a794ca5515f (patch) | |
tree | 2be713f424b906e73a5320edca75855f6b37226e /clang/lib | |
parent | 109702ccb16f33a5b0305a1d1287413c9a88adca (diff) | |
download | bcm5719-llvm-b12e5a5ccd8e5ca71a3722a4b5103a794ca5515f.tar.gz bcm5719-llvm-b12e5a5ccd8e5ca71a3722a4b5103a794ca5515f.zip |
Add functions to apply replacements and reformat them.
This is a commonly useful feature to have, and we have implemented it
multiple times with different kinds of bugs. This implementation
centralizes the idea in a set of functions that we can then use from the various
tools.
Reverts r262234, which is a revert of r262232, and puts the functions
into FOrmat.h, as they are closely coupled to clang-format, and we
otherwise introduce a cyclic dependency between libFormat and
libTooling.
Patch by Eric Liu.
llvm-svn: 262323
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Format/Format.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Tooling/Core/Replacement.cpp | 17 |
2 files changed, 43 insertions, 2 deletions
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 85a0152e295..9d5c0bca335 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1884,6 +1884,34 @@ tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, return Replaces; } +tooling::Replacements formatReplacements(StringRef Code, + const tooling::Replacements &Replaces, + const FormatStyle &Style) { + if (Replaces.empty()) + return tooling::Replacements(); + + std::string NewCode = applyAllReplacements(Code, Replaces); + std::vector<tooling::Range> ChangedRanges = + tooling::calculateChangedRangesInFile(Replaces); + StringRef FileName = Replaces.begin()->getFilePath(); + tooling::Replacements FormatReplaces = + reformat(Style, NewCode, ChangedRanges, FileName); + + tooling::Replacements MergedReplacements = + mergeReplacements(Replaces, FormatReplaces); + return MergedReplacements; +} + +std::string applyAllReplacementsAndFormat(StringRef Code, + const tooling::Replacements &Replaces, + const FormatStyle &Style) { + tooling::Replacements NewReplacements = + formatReplacements(Code, Replaces, Style); + if (NewReplacements.empty()) + return Code; // Exit early to avoid overhead in `applyAllReplacements`. + return applyAllReplacements(Code, NewReplacements); +} + tooling::Replacements reformat(const FormatStyle &Style, SourceManager &SourceMgr, FileID ID, ArrayRef<CharSourceRange> Ranges, diff --git a/clang/lib/Tooling/Core/Replacement.cpp b/clang/lib/Tooling/Core/Replacement.cpp index 47bbdeb470e..6226cf285b2 100644 --- a/clang/lib/Tooling/Core/Replacement.cpp +++ b/clang/lib/Tooling/Core/Replacement.cpp @@ -11,6 +11,8 @@ // //===----------------------------------------------------------------------===// +#include "clang/Tooling/Core/Replacement.h" + #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/DiagnosticOptions.h" @@ -18,7 +20,6 @@ #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" #include "clang/Rewrite/Core/Rewriter.h" -#include "clang/Tooling/Core/Replacement.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_os_ostream.h" @@ -281,6 +282,18 @@ std::string applyAllReplacements(StringRef Code, const Replacements &Replaces) { return Result; } +std::vector<Range> calculateChangedRangesInFile(const Replacements &Replaces) { + std::vector<Range> ChangedRanges; + int Shift = 0; + for (const Replacement &R : Replaces) { + unsigned Offset = R.getOffset() + Shift; + unsigned Length = R.getReplacementText().size(); + Shift += Length - R.getLength(); + ChangedRanges.push_back(Range(Offset, Length)); + } + return ChangedRanges; +} + namespace { // Represents a merged replacement, i.e. a replacement consisting of multiple // overlapping replacements from 'First' and 'Second' in mergeReplacements. @@ -314,7 +327,7 @@ public: // Merges the next element 'R' into this merged element. As we always merge // from 'First' into 'Second' or vice versa, the MergedReplacement knows what - // set the next element is coming from. + // set the next element is coming from. void merge(const Replacement &R) { if (MergeSecond) { unsigned REnd = R.getOffset() + Delta + R.getLength(); |