[clang-tools-extra] r217440 - clang-apply-replacements: Deduplicate paths with FileManager.

Benjamin Kramer benny.kra at googlemail.com
Tue Sep 9 06:53:51 PDT 2014


Author: d0k
Date: Tue Sep  9 08:53:51 2014
New Revision: 217440

URL: http://llvm.org/viewvc/llvm-project?rev=217440&view=rev
Log:
clang-apply-replacements: Deduplicate paths with FileManager.

Bucket replacements by FileEntry instead of path. The same file with
different paths is very common, relative #include paths and symlinks can
easily create them. When that occurs we would apply the fix twice.

Modified:
    clang-tools-extra/trunk/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
    clang-tools-extra/trunk/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
    clang-tools-extra/trunk/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
    clang-tools-extra/trunk/test/clang-apply-replacements/Inputs/basic/file1.yaml

Modified: clang-tools-extra/trunk/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h?rev=217440&r1=217439&r2=217440&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h (original)
+++ clang-tools-extra/trunk/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h Tue Sep  9 08:53:51 2014
@@ -45,8 +45,9 @@ TUReplacements;
 typedef std::vector<std::string> TUReplacementFiles;
 
 /// \brief Map mapping file name to Replacements targeting that file.
-typedef llvm::StringMap<std::vector<clang::tooling::Replacement> >
-FileToReplacementsMap;
+typedef llvm::DenseMap<const clang::FileEntry *,
+                       std::vector<clang::tooling::Replacement>>
+    FileToReplacementsMap;
 
 /// \brief Recursively descends through a directory structure rooted at \p
 /// Directory and attempts to deserialize *.yaml files as

Modified: clang-tools-extra/trunk/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp?rev=217440&r1=217439&r2=217440&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp (original)
+++ clang-tools-extra/trunk/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp Tue Sep  9 08:53:51 2014
@@ -140,33 +140,24 @@ static bool deduplicateAndDetectConflict
                                           SourceManager &SM) {
   bool conflictsFound = false;
 
-  for (FileToReplacementsMap::iterator I = Replacements.begin(),
-                                       E = Replacements.end();
-       I != E; ++I) {
-
-    const FileEntry *Entry = SM.getFileManager().getFile(I->getKey());
-    if (!Entry) {
-      errs() << "Described file '" << I->getKey()
-             << "' doesn't exist. Ignoring...\n";
-      continue;
-    }
+  for (auto &FileAndReplacements : Replacements) {
+    const FileEntry *Entry = FileAndReplacements.first;
+    auto &Replacements = FileAndReplacements.second;
+    assert(Entry != nullptr && "No file entry!");
 
     std::vector<tooling::Range> Conflicts;
-    tooling::deduplicate(I->getValue(), Conflicts);
+    tooling::deduplicate(FileAndReplacements.second, Conflicts);
 
     if (Conflicts.empty())
       continue;
 
     conflictsFound = true;
 
-    errs() << "There are conflicting changes to " << I->getKey() << ":\n";
+    errs() << "There are conflicting changes to " << Entry->getName() << ":\n";
 
-    for (std::vector<tooling::Range>::const_iterator
-             ConflictI = Conflicts.begin(),
-             ConflictE = Conflicts.end();
-         ConflictI != ConflictE; ++ConflictI) {
-      ArrayRef<tooling::Replacement> ConflictingReplacements(
-          &I->getValue()[ConflictI->getOffset()], ConflictI->getLength());
+    for (const tooling::Range &Conflict : Conflicts) {
+      auto ConflictingReplacements = llvm::makeArrayRef(
+          &Replacements[Conflict.getOffset()], Conflict.getLength());
       reportConflict(Entry, ConflictingReplacements, SM);
     }
   }
@@ -179,14 +170,20 @@ bool mergeAndDeduplicate(const TUReplace
                          clang::SourceManager &SM) {
 
   // Group all replacements by target file.
-  for (TUReplacements::const_iterator TUI = TUs.begin(), TUE = TUs.end();
-       TUI != TUE; ++TUI)
-    for (std::vector<tooling::Replacement>::const_iterator
-             RI = TUI->Replacements.begin(),
-             RE = TUI->Replacements.end();
-         RI != RE; ++RI)
-      GroupedReplacements[RI->getFilePath()].push_back(*RI);
-
+  std::set<StringRef> Warned;
+  for (const auto &TU : TUs) {
+    for (const tooling::Replacement &R : TU.Replacements) {
+      // Use the file manager to deduplicate paths. FileEntries are
+      // automatically canonicalized.
+      const FileEntry *Entry = SM.getFileManager().getFile(R.getFilePath());
+      if (!Entry && Warned.insert(R.getFilePath()).second) {
+        errs() << "Described file '" << R.getFilePath()
+               << "' doesn't exist. Ignoring...\n";
+        continue;
+      }
+      GroupedReplacements[Entry].push_back(R);
+    }
+  }
 
   // Ask clang to deduplicate and report conflicts.
   if (deduplicateAndDetectConflicts(GroupedReplacements, SM))
@@ -204,10 +201,8 @@ bool applyReplacements(const FileToRepla
   // data structure for applying replacements. Rewriter certainly doesn't care.
   // However, until we nail down the design of ReplacementGroups, might as well
   // leave this as is.
-  for (FileToReplacementsMap::const_iterator I = GroupedReplacements.begin(),
-                                             E = GroupedReplacements.end();
-       I != E; ++I) {
-    if (!tooling::applyAllReplacements(I->getValue(), Rewrites))
+  for (const auto &FileAndReplacements : GroupedReplacements) {
+    if (!tooling::applyAllReplacements(FileAndReplacements.second, Rewrites))
       return false;
   }
 

Modified: clang-tools-extra/trunk/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp?rev=217440&r1=217439&r2=217440&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp (original)
+++ clang-tools-extra/trunk/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp Tue Sep  9 08:53:51 2014
@@ -246,35 +246,34 @@ int main(int argc, char **argv) {
 
   Rewriter ReplacementsRewriter(SM, LangOptions());
 
-  for (FileToReplacementsMap::const_iterator I = GroupedReplacements.begin(),
-                                             E = GroupedReplacements.end();
-       I != E; ++I) {
-
-    std::string NewFileData;
-
+  for (const auto &FileAndReplacements : GroupedReplacements) {
     // This shouldn't happen but if a file somehow has no replacements skip to
     // next file.
-    if (I->getValue().empty())
+    if (FileAndReplacements.second.empty())
       continue;
 
-    if (!applyReplacements(I->getValue(), NewFileData, Diagnostics)) {
-      errs() << "Failed to apply replacements to " << I->getKey() << "\n";
+    std::string NewFileData;
+    const char *FileName = FileAndReplacements.first->getName();
+    if (!applyReplacements(FileAndReplacements.second, NewFileData,
+                           Diagnostics)) {
+      errs() << "Failed to apply replacements to " << FileName << "\n";
       continue;
     }
 
     // Apply formatting if requested.
-    if (DoFormat && !applyFormatting(I->getValue(), NewFileData, NewFileData,
-                                     FormatStyle, Diagnostics)) {
-      errs() << "Failed to apply reformatting replacements for " << I->getKey()
+    if (DoFormat &&
+        !applyFormatting(FileAndReplacements.second, NewFileData, NewFileData,
+                         FormatStyle, Diagnostics)) {
+      errs() << "Failed to apply reformatting replacements for " << FileName
              << "\n";
       continue;
     }
 
     // Write new file to disk
     std::error_code EC;
-    llvm::raw_fd_ostream FileStream(I->getKey(), EC, llvm::sys::fs::F_Text);
+    llvm::raw_fd_ostream FileStream(FileName, EC, llvm::sys::fs::F_Text);
     if (EC) {
-      llvm::errs() << "Could not open " << I->getKey() << " for writing\n";
+      llvm::errs() << "Could not open " << FileName << " for writing\n";
       continue;
     }
 

Modified: clang-tools-extra/trunk/test/clang-apply-replacements/Inputs/basic/file1.yaml
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-apply-replacements/Inputs/basic/file1.yaml?rev=217440&r1=217439&r2=217440&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-apply-replacements/Inputs/basic/file1.yaml (original)
+++ clang-tools-extra/trunk/test/clang-apply-replacements/Inputs/basic/file1.yaml Tue Sep  9 08:53:51 2014
@@ -13,4 +13,8 @@ Replacements:
     Offset:          298
     Length:          1
     ReplacementText: elem
+  - FilePath:        $(path)/../basic/basic.h
+    Offset:          148
+    Length:          0
+    ReplacementText: 'override '
 ...





More information about the cfe-commits mailing list