Summary:
If there are multiple <File, Replacements> pairs with the same file
path after removing dots, we only keep one pair (with path after dots being
removed) and discard the rest.
Reviewers: djasper
Subscribers: klimek, hokein, bkramer, cfe-commits
Differential Revision: https://reviews.llvm.org/D25565
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@284219
91177308-0d34-0410-b5e6-
96231b3b80d8
Replacements(const_iterator Begin, const_iterator End)
: Replaces(Begin, End) {}
- Replacements mergeReplacements(const ReplacementsImpl &Second) const;
-
// Returns `R` with new range that refers to code after `Replaces` being
// applied.
Replacement getReplacementInChangedCode(const Replacement &R) const;
calculateRangesAfterReplacements(const Replacements &Replaces,
const std::vector<Range> &Ranges);
-/// \brief Groups a random set of replacements by file path. Replacements
-/// related to the same file entry are put into the same vector.
-std::map<std::string, Replacements>
-groupReplacementsByFile(const Replacements &Replaces);
+/// \brief If there are multiple <File, Replacements> pairs with the same file
+/// path after removing dots, we only keep one pair (with path after dots being
+/// removed) and discard the rest.
+std::map<std::string, Replacements> groupReplacementsByFile(
+ const std::map<std::string, Replacements> &FileToReplaces);
template <typename Node>
Replacement::Replacement(const SourceManager &Sources,
/// \brief Apply all stored replacements to the given Rewriter.
///
+ /// FileToReplaces will be deduplicated with `groupReplacementsByFile` before
+ /// application.
+ ///
/// Replacement applications happen independently of the success of other
/// applications.
///
///
/// \pre Replacements must be conflict-free.
///
+/// FileToReplaces will be deduplicated with `groupReplacementsByFile` before
+/// application.
+///
/// Replacement applications happen independently of the success of other
/// applications.
///
#include "clang/Lex/Lexer.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_os_ostream.h"
namespace clang {
return Result;
}
-std::map<std::string, Replacements>
-groupReplacementsByFile(const Replacements &Replaces) {
- std::map<std::string, Replacements> FileToReplaces;
- for (const auto &Replace : Replaces)
- // We can ignore the Error here since \p Replaces is already conflict-free.
- FileToReplaces[Replace.getFilePath()].add(Replace);
- return FileToReplaces;
+std::map<std::string, Replacements> groupReplacementsByFile(
+ const std::map<std::string, Replacements> &FileToReplaces) {
+ std::map<std::string, Replacements> Result;
+ for (const auto &Entry : FileToReplaces) {
+ llvm::SmallString<256> CleanPath(Entry.first.data());
+ llvm::sys::path::remove_dots(CleanPath, /*remove_dot_dot=*/true);
+ Result[CleanPath.str()] = std::move(Entry.second);
+ }
+ return Result;
}
} // end namespace tooling
bool RefactoringTool::applyAllReplacements(Rewriter &Rewrite) {
bool Result = true;
- for (const auto &Entry : FileToReplaces)
+ for (const auto &Entry : groupReplacementsByFile(FileToReplaces))
Result = tooling::applyAllReplacements(Entry.second, Rewrite) && Result;
return Result;
}
FileManager &Files = SM.getFileManager();
bool Result = true;
- for (const auto &FileAndReplaces : FileToReplaces) {
+ for (const auto &FileAndReplaces : groupReplacementsByFile(FileToReplaces)) {
const std::string &FilePath = FileAndReplaces.first;
auto &CurReplaces = FileAndReplaces.second;
toReplacements({{"", 0, 3, "cc"}, {"", 3, 3, "dd"}}));
}
+TEST(DeduplicateByFileTest, LeaveLeadingDotDot) {
+ std::map<std::string, Replacements> FileToReplaces;
+ FileToReplaces["../../a/b/.././c.h"] = Replacements();
+ FileToReplaces["../../a/c.h"] = Replacements();
+ FileToReplaces = groupReplacementsByFile(FileToReplaces);
+ EXPECT_EQ(1u, FileToReplaces.size());
+ EXPECT_EQ("../../a/c.h", FileToReplaces.begin()->first);
+}
+
+TEST(DeduplicateByFileTest, RemoveDotSlash) {
+ std::map<std::string, Replacements> FileToReplaces;
+ FileToReplaces["./a/b/.././c.h"] = Replacements();
+ FileToReplaces["a/c.h"] = Replacements();
+ FileToReplaces = groupReplacementsByFile(FileToReplaces);
+ EXPECT_EQ(1u, FileToReplaces.size());
+ EXPECT_EQ("a/c.h", FileToReplaces.begin()->first);
+}
+
} // end namespace tooling
} // end namespace clang