#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_os_ostream.h"
}
std::map<std::string, Replacements> groupReplacementsByFile(
+ FileManager &FileMgr,
const std::map<std::string, Replacements> &FileToReplaces) {
std::map<std::string, Replacements> Result;
+ llvm::SmallPtrSet<const FileEntry *, 16> ProcessedFileEntries;
for (const auto &Entry : FileToReplaces) {
- llvm::SmallString<256> CleanPath(Entry.first);
- llvm::sys::path::remove_dots(CleanPath, /*remove_dot_dot=*/true);
- Result[CleanPath.str()] = std::move(Entry.second);
+ const FileEntry *FE = FileMgr.getFile(Entry.first);
+ if (!FE)
+ llvm::errs() << "File path " << Entry.first << " is invalid.\n";
+ else if (ProcessedFileEntries.insert(FE).second)
+ Result[Entry.first] = std::move(Entry.second);
}
return Result;
}
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
toReplacements({{"", 0, 3, "cc"}, {"", 3, 3, "dd"}}));
}
-TEST(DeduplicateByFileTest, LeaveLeadingDotDot) {
+TEST(DeduplicateByFileTest, PathsWithDots) {
std::map<std::string, Replacements> FileToReplaces;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
+ new vfs::InMemoryFileSystem());
+ FileManager *FileMgr = new FileManager(FileSystemOptions(), VFS);
#if !defined(LLVM_ON_WIN32)
- FileToReplaces["../../a/b/.././c.h"] = Replacements();
- FileToReplaces["../../a/c.h"] = Replacements();
+ StringRef Path1 = "a/b/.././c.h";
+ StringRef Path2 = "a/c.h";
#else
- FileToReplaces["..\\..\\a\\b\\..\\.\\c.h"] = Replacements();
- FileToReplaces["..\\..\\a\\c.h"] = Replacements();
+ StringRef Path1 = "a\\b\\..\\.\\c.h";
+ StringRef Path2 = "a\\c.h";
#endif
- FileToReplaces = groupReplacementsByFile(FileToReplaces);
+ EXPECT_TRUE(VFS->addFile(Path1, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ EXPECT_TRUE(VFS->addFile(Path2, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ FileToReplaces[Path1] = Replacements();
+ FileToReplaces[Path2] = Replacements();
+ FileToReplaces = groupReplacementsByFile(*FileMgr, FileToReplaces);
EXPECT_EQ(1u, FileToReplaces.size());
-#if !defined(LLVM_ON_WIN32)
- EXPECT_EQ("../../a/c.h", FileToReplaces.begin()->first);
-#else
- EXPECT_EQ("..\\..\\a\\c.h", FileToReplaces.begin()->first);
-#endif
+ EXPECT_EQ(Path1, FileToReplaces.begin()->first);
}
-TEST(DeduplicateByFileTest, RemoveDotSlash) {
+TEST(DeduplicateByFileTest, PathWithDotSlash) {
std::map<std::string, Replacements> FileToReplaces;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
+ new vfs::InMemoryFileSystem());
+ FileManager *FileMgr = new FileManager(FileSystemOptions(), VFS);
#if !defined(LLVM_ON_WIN32)
- FileToReplaces["./a/b/.././c.h"] = Replacements();
- FileToReplaces["a/c.h"] = Replacements();
+ StringRef Path1 = "./a/b/c.h";
+ StringRef Path2 = "a/b/c.h";
#else
- FileToReplaces[".\\a\\b\\..\\.\\c.h"] = Replacements();
- FileToReplaces["a\\c.h"] = Replacements();
+ StringRef Path1 = ".\\a\\b\\c.h";
+ StringRef Path2 = "a\\b\\c.h";
#endif
- FileToReplaces = groupReplacementsByFile(FileToReplaces);
+ EXPECT_TRUE(VFS->addFile(Path1, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ EXPECT_TRUE(VFS->addFile(Path2, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ FileToReplaces[Path1] = Replacements();
+ FileToReplaces[Path2] = Replacements();
+ FileToReplaces = groupReplacementsByFile(*FileMgr, FileToReplaces);
EXPECT_EQ(1u, FileToReplaces.size());
+ EXPECT_EQ(Path1, FileToReplaces.begin()->first);
+}
+
+TEST(DeduplicateByFileTest, NonExistingFilePath) {
+ std::map<std::string, Replacements> FileToReplaces;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
+ new vfs::InMemoryFileSystem());
+ FileManager *FileMgr = new FileManager(FileSystemOptions(), VFS);
#if !defined(LLVM_ON_WIN32)
- EXPECT_EQ("a/c.h", FileToReplaces.begin()->first);
+ StringRef Path1 = "./a/b/c.h";
+ StringRef Path2 = "a/b/c.h";
#else
- EXPECT_EQ("a\\c.h", FileToReplaces.begin()->first);
+ StringRef Path1 = ".\\a\\b\\c.h";
+ StringRef Path2 = "a\\b\\c.h";
#endif
+ FileToReplaces[Path1] = Replacements();
+ FileToReplaces[Path2] = Replacements();
+ FileToReplaces = groupReplacementsByFile(*FileMgr, FileToReplaces);
+ EXPECT_TRUE(FileToReplaces.empty());
}
} // end namespace tooling