[clang-tools-extra] r189671 - clang-replace: Re-org of file structure

Edwin Vane edwin.vane at intel.com
Fri Aug 30 07:33:56 PDT 2013


Author: revane
Date: Fri Aug 30 09:33:56 2013
New Revision: 189671

URL: http://llvm.org/viewvc/llvm-project?rev=189671&view=rev
Log:
clang-replace: Re-org of file structure

clang-replace is likely to move to clang proper one day soon. To facilitate
that move, renaming files and directory structure layout to ease transition for
users of clang-replace and libclangReplace.

For now, functionality still exists in clang::replace namespace. Header guards
and file comments updated.

Differential Revision: http://llvm-reviews.chandlerc.com/D1548


Added:
    clang-tools-extra/trunk/clang-replace/include/
    clang-tools-extra/trunk/clang-replace/include/clang-replace/
    clang-tools-extra/trunk/clang-replace/include/clang-replace/Tooling/
    clang-tools-extra/trunk/clang-replace/include/clang-replace/Tooling/ApplyReplacements.h
    clang-tools-extra/trunk/clang-replace/lib/
    clang-tools-extra/trunk/clang-replace/lib/Tooling/
    clang-tools-extra/trunk/clang-replace/lib/Tooling/ApplyReplacements.cpp
    clang-tools-extra/trunk/clang-replace/lib/Tooling/Makefile
Removed:
    clang-tools-extra/trunk/clang-replace/ApplyReplacements.cpp
    clang-tools-extra/trunk/clang-replace/ApplyReplacements.h
Modified:
    clang-tools-extra/trunk/clang-replace/CMakeLists.txt
    clang-tools-extra/trunk/clang-replace/Makefile
    clang-tools-extra/trunk/clang-replace/tool/ClangReplaceMain.cpp
    clang-tools-extra/trunk/clang-replace/tool/Makefile

Removed: clang-tools-extra/trunk/clang-replace/ApplyReplacements.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-replace/ApplyReplacements.cpp?rev=189670&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-replace/ApplyReplacements.cpp (original)
+++ clang-tools-extra/trunk/clang-replace/ApplyReplacements.cpp (removed)
@@ -1,253 +0,0 @@
-//===-- Core/ApplyChangeDescriptions.cpp ----------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief This file provides the implementation for finding and applying change
-/// description files.
-///
-//===----------------------------------------------------------------------===//
-#include "ApplyReplacements.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/Tooling/ReplacementsYaml.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-using namespace clang;
-
-
-static void eatDiagnostics(const SMDiagnostic &, void *) {}
-
-namespace clang {
-namespace replace {
-
-llvm::error_code
-collectReplacementsFromDirectory(const llvm::StringRef Directory,
-                                 TUReplacements &TUs,
-                                 TUReplacementFiles & TURFiles,
-                                 clang::DiagnosticsEngine &Diagnostics) {
-  using namespace llvm::sys::fs;
-  using namespace llvm::sys::path;
-
-  error_code ErrorCode;
-
-  for (recursive_directory_iterator I(Directory, ErrorCode), E;
-       I != E && !ErrorCode; I.increment(ErrorCode)) {
-    if (filename(I->path())[0] == '.') {
-      // Indicate not to descend into directories beginning with '.'
-      I.no_push();
-      continue;
-    }
-
-    if (extension(I->path()) != ".yaml")
-      continue;
-
-    TURFiles.push_back(I->path());
-
-    OwningPtr<MemoryBuffer> Out;
-    error_code BufferError = MemoryBuffer::getFile(I->path(), Out);
-    if (BufferError) {
-      errs() << "Error reading " << I->path() << ": " << BufferError.message()
-             << "\n";
-      continue;
-    }
-
-    yaml::Input YIn(Out->getBuffer());
-    YIn.setDiagHandler(&eatDiagnostics);
-    tooling::TranslationUnitReplacements TU;
-    YIn >> TU;
-    if (YIn.error()) {
-      // File doesn't appear to be a header change description. Ignore it.
-      continue;
-    }
-
-    // Only keep files that properly parse.
-    TUs.push_back(TU);
-  }
-
-  return ErrorCode;
-}
-
-/// \brief Dumps information for a sequence of conflicting Replacements.
-///
-/// \param[in] File FileEntry for the file the conflicting Replacements are
-/// for.
-/// \param[in] ConflictingReplacements List of conflicting Replacements.
-/// \param[in] SM SourceManager used for reporting.
-static void reportConflict(
-    const FileEntry *File,
-    const llvm::ArrayRef<clang::tooling::Replacement> ConflictingReplacements,
-    SourceManager &SM) {
-  FileID FID = SM.translateFile(File);
-  if (FID.isInvalid())
-    FID = SM.createFileID(File, SourceLocation(), SrcMgr::C_User);
-
-  // FIXME: Output something a little more user-friendly (e.g. unified diff?)
-  errs() << "The following changes conflict:\n";
-  for (const tooling::Replacement *I = ConflictingReplacements.begin(),
-                                  *E = ConflictingReplacements.end();
-       I != E; ++I) {
-    if (I->getLength() == 0) {
-      errs() << "  Insert at " << SM.getLineNumber(FID, I->getOffset()) << ":"
-             << SM.getColumnNumber(FID, I->getOffset()) << " "
-             << I->getReplacementText() << "\n";
-    } else {
-      if (I->getReplacementText().empty())
-        errs() << "  Remove ";
-      else
-        errs() << "  Replace ";
-
-      errs() << SM.getLineNumber(FID, I->getOffset()) << ":"
-             << SM.getColumnNumber(FID, I->getOffset()) << "-"
-             << SM.getLineNumber(FID, I->getOffset() + I->getLength() - 1)
-             << ":"
-             << SM.getColumnNumber(FID, I->getOffset() + I->getLength() - 1);
-
-      if (I->getReplacementText().empty())
-        errs() << "\n";
-      else
-        errs() << " with \"" << I->getReplacementText() << "\"\n";
-    }
-  }
-}
-
-/// \brief Deduplicates and tests for conflicts among the replacements for each
-/// file in \c Replacements. Any conflicts found are reported.
-///
-/// \param[in,out] Replacements Container of all replacements grouped by file
-/// to be deduplicated and checked for conflicts.
-/// \param[in] SM SourceManager required for conflict reporting.
-///
-/// \returns \li true if conflicts were detected
-///          \li false if no conflicts were detected
-static bool deduplicateAndDetectConflicts(FileToReplacementsMap &Replacements,
-                                          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;
-    }
-
-    std::vector<tooling::Range> Conflicts;
-    tooling::deduplicate(I->getValue(), Conflicts);
-
-    if (Conflicts.empty())
-      continue;
-
-    conflictsFound = true;
-
-    errs() << "There are conflicting changes to " << I->getKey() << ":\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());
-      reportConflict(Entry, ConflictingReplacements, SM);
-    }
-  }
-
-  return conflictsFound;
-}
-
-bool mergeAndDeduplicate(const TUReplacements &TUs,
-                         FileToReplacementsMap &GroupedReplacements,
-                         clang::SourceManager &SM) {
-
-  // FIXME: Use Diagnostics for output
-
-  // 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);
-
-
-  // Ask clang to deduplicate and report conflicts.
-  if (deduplicateAndDetectConflicts(GroupedReplacements, SM))
-    return false;
-
-  return true;
-}
-
-bool applyReplacements(const FileToReplacementsMap &GroupedReplacements,
-                       clang::Rewriter &Rewrites) {
-
-  // Apply all changes
-  //
-  // FIXME: No longer certain GroupedReplacements is really the best kind of
-  // 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))
-      return false;
-  }
-
-  return true;
-}
-
-bool writeFiles(const clang::Rewriter &Rewrites) {
-
-  for (Rewriter::const_buffer_iterator BufferI = Rewrites.buffer_begin(),
-                                       BufferE = Rewrites.buffer_end();
-       BufferI != BufferE; ++BufferI) {
-    const char *FileName =
-        Rewrites.getSourceMgr().getFileEntryForID(BufferI->first)->getName();
-
-    std::string ErrorInfo;
-
-    llvm::raw_fd_ostream FileStream(FileName, ErrorInfo);
-    if (!ErrorInfo.empty()) {
-      errs() << "Warning: Could not write to " << FileName << "\n";
-      continue;
-    }
-    BufferI->second.write(FileStream);
-  }
-
-  return true;
-}
-
-bool deleteReplacementFiles(const TUReplacementFiles &Files,
-                            clang::DiagnosticsEngine &Diagnostics) {
-  bool Success = true;
-  for (TUReplacementFiles::const_iterator I = Files.begin(), E = Files.end();
-       I != E; ++I) {
-    error_code Error = llvm::sys::fs::remove(*I);
-    if (Error) {
-      Success = false;
-      // FIXME: Use Diagnostics for outputting errors.
-      errs() << "Error deleting file: " << *I << "\n";
-      errs() << Error.message() << "\n";
-      errs() << "Please delete the file manually\n";
-    }
-  }
-  return Success;
-}
-
-} // end namespace replace
-} // end namespace clang

Removed: clang-tools-extra/trunk/clang-replace/ApplyReplacements.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-replace/ApplyReplacements.h?rev=189670&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-replace/ApplyReplacements.h (original)
+++ clang-tools-extra/trunk/clang-replace/ApplyReplacements.h (removed)
@@ -1,114 +0,0 @@
-//===-- Core/ApplyChangeDescriptions.h --------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief This file provides the interface for finding and applying change
-/// description files.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef CPP11_MIGRATE_APPLYCHANGEDESCRIPTIONS_H
-#define CPP11_MIGRATE_APPLYCHANGEDESCRIPTIONS_H
-
-#include "clang/Tooling/Refactoring.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/system_error.h"
-#include <vector>
-#include <string>
-
-namespace clang {
-
-class DiagnosticsEngine;
-class Rewriter;
-
-namespace replace {
-
-/// \brief Collection of TranslationUnitReplacements.
-typedef std::vector<clang::tooling::TranslationUnitReplacements>
-TUReplacements;
-
-/// \brief Collection of TranslationUnitReplacement files.
-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;
-
-/// \brief Recursively descends through a directory structure rooted at \p
-/// Directory and attempts to deserialize *.yaml files as
-/// TranslationUnitReplacements. All docs that successfully deserialize are
-/// added to \p TUs.
-///
-/// Directories starting with '.' are ignored during traversal.
-///
-/// \param[in] Directory Directory to begin search for serialized
-/// TranslationUnitReplacements.
-/// \param[out] TUs Collection of all found and deserialized
-/// TranslationUnitReplacements.
-/// \param[out] TURFiles Collection of all TranslationUnitReplacement files
-/// found in \c Directory.
-/// \param[in] Diagnostics DiagnosticsEngine used for error output.
-///
-/// \returns An error_code indicating success or failure in navigating the
-/// directory structure.
-llvm::error_code
-collectReplacementsFromDirectory(const llvm::StringRef Directory,
-                                 TUReplacements &TUs,
-                                 TUReplacementFiles &TURFiles,
-                                 clang::DiagnosticsEngine &Diagnostics);
-
-/// \brief Deduplicate, check for conflicts, and apply all Replacements stored
-/// in \c TUs. If conflicts occur, no Replacements are applied.
-///
-/// \param[in] TUs Collection of TranslationUnitReplacements to merge,
-/// deduplicate, and test for conflicts.
-/// \param[out] GroupedReplacements Container grouping all Replacements by the
-/// file they target.
-/// \param[in] SM SourceManager required for conflict reporting.
-///
-/// \returns \li true If all changes were applied successfully.
-///          \li false If there were conflicts.
-bool mergeAndDeduplicate(const TUReplacements &TUs,
-                         FileToReplacementsMap &GroupedReplacements,
-                         clang::SourceManager &SM);
-
-/// \brief Apply all replacements in \c GroupedReplacements.
-///
-/// \param[in] GroupedReplacements Deduplicated and conflict free Replacements
-/// to apply.
-/// \param[out] Rewrites The results of applying replacements will be applied
-/// to this Rewriter.
-///
-/// \returns \li true If all changes were applied successfully.
-///          \li false If a replacement failed to apply.
-bool applyReplacements(const FileToReplacementsMap &GroupedReplacements,
-                       clang::Rewriter &Rewrites);
-
-/// \brief Write the contents of \c FileContents to disk. Keys of the map are
-/// filenames and values are the new contents for those files.
-///
-/// \param[in] Rewrites Rewriter containing written files to write to disk.
-bool writeFiles(const clang::Rewriter &Rewrites);
-
-/// \brief Delete the replacement files.
-///
-/// \param[in] Files Replacement files to delete.
-/// \param[in] Diagnostics DiagnosticsEngine used for error output.
-///
-/// \returns \li true If all files have been deleted successfully.
-///          \li false If at least one or more failures occur when deleting
-/// files.
-bool deleteReplacementFiles(const TUReplacementFiles &Files,
-                            clang::DiagnosticsEngine &Diagnostics);
-
-} // end namespace replace
-} // end namespace clang
-
-#endif // CPP11_MIGRATE_APPLYCHANGEDESCRIPTIONS_H

Modified: clang-tools-extra/trunk/clang-replace/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-replace/CMakeLists.txt?rev=189671&r1=189670&r2=189671&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-replace/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-replace/CMakeLists.txt Fri Aug 30 09:33:56 2013
@@ -7,7 +7,7 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_clang_library(clangReplace
-  ApplyReplacements.cpp
+  lib/Tooling/ApplyReplacements.cpp
   )
 target_link_libraries(clangReplace
   clangTooling
@@ -15,5 +15,8 @@ target_link_libraries(clangReplace
   clangRewriteFrontend
   )
 
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  include
+  )
 add_subdirectory(tool)

Modified: clang-tools-extra/trunk/clang-replace/Makefile
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-replace/Makefile?rev=189671&r1=189670&r2=189671&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-replace/Makefile (original)
+++ clang-tools-extra/trunk/clang-replace/Makefile Fri Aug 30 09:33:56 2013
@@ -8,9 +8,8 @@
 ##===----------------------------------------------------------------------===##
 
 CLANG_LEVEL := ../../..
-LIBRARYNAME := clangReplace
 include $(CLANG_LEVEL)/../../Makefile.config
 
-DIRS = tool
+DIRS = lib/Replace tool
 
 include $(CLANG_LEVEL)/Makefile

Added: clang-tools-extra/trunk/clang-replace/include/clang-replace/Tooling/ApplyReplacements.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-replace/include/clang-replace/Tooling/ApplyReplacements.h?rev=189671&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-replace/include/clang-replace/Tooling/ApplyReplacements.h (added)
+++ clang-tools-extra/trunk/clang-replace/include/clang-replace/Tooling/ApplyReplacements.h Fri Aug 30 09:33:56 2013
@@ -0,0 +1,114 @@
+//===-- ApplyReplacements.h - Deduplicate and apply replacements -- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides the interface for deduplicating, detecting
+/// conflicts in, and applying collections of Replacements.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_APPLYREPLACEMENTS_H
+#define LLVM_CLANG_APPLYREPLACEMENTS_H
+
+#include "clang/Tooling/Refactoring.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/system_error.h"
+#include <vector>
+#include <string>
+
+namespace clang {
+
+class DiagnosticsEngine;
+class Rewriter;
+
+namespace replace {
+
+/// \brief Collection of TranslationUnitReplacements.
+typedef std::vector<clang::tooling::TranslationUnitReplacements>
+TUReplacements;
+
+/// \brief Collection of TranslationUnitReplacement files.
+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;
+
+/// \brief Recursively descends through a directory structure rooted at \p
+/// Directory and attempts to deserialize *.yaml files as
+/// TranslationUnitReplacements. All docs that successfully deserialize are
+/// added to \p TUs.
+///
+/// Directories starting with '.' are ignored during traversal.
+///
+/// \param[in] Directory Directory to begin search for serialized
+/// TranslationUnitReplacements.
+/// \param[out] TUs Collection of all found and deserialized
+/// TranslationUnitReplacements.
+/// \param[out] TURFiles Collection of all TranslationUnitReplacement files
+/// found in \c Directory.
+/// \param[in] Diagnostics DiagnosticsEngine used for error output.
+///
+/// \returns An error_code indicating success or failure in navigating the
+/// directory structure.
+llvm::error_code
+collectReplacementsFromDirectory(const llvm::StringRef Directory,
+                                 TUReplacements &TUs,
+                                 TUReplacementFiles &TURFiles,
+                                 clang::DiagnosticsEngine &Diagnostics);
+
+/// \brief Deduplicate, check for conflicts, and apply all Replacements stored
+/// in \c TUs. If conflicts occur, no Replacements are applied.
+///
+/// \param[in] TUs Collection of TranslationUnitReplacements to merge,
+/// deduplicate, and test for conflicts.
+/// \param[out] GroupedReplacements Container grouping all Replacements by the
+/// file they target.
+/// \param[in] SM SourceManager required for conflict reporting.
+///
+/// \returns \li true If all changes were applied successfully.
+///          \li false If there were conflicts.
+bool mergeAndDeduplicate(const TUReplacements &TUs,
+                         FileToReplacementsMap &GroupedReplacements,
+                         clang::SourceManager &SM);
+
+/// \brief Apply all replacements in \c GroupedReplacements.
+///
+/// \param[in] GroupedReplacements Deduplicated and conflict free Replacements
+/// to apply.
+/// \param[out] Rewrites The results of applying replacements will be applied
+/// to this Rewriter.
+///
+/// \returns \li true If all changes were applied successfully.
+///          \li false If a replacement failed to apply.
+bool applyReplacements(const FileToReplacementsMap &GroupedReplacements,
+                       clang::Rewriter &Rewrites);
+
+/// \brief Write the contents of \c FileContents to disk. Keys of the map are
+/// filenames and values are the new contents for those files.
+///
+/// \param[in] Rewrites Rewriter containing written files to write to disk.
+bool writeFiles(const clang::Rewriter &Rewrites);
+
+/// \brief Delete the replacement files.
+///
+/// \param[in] Files Replacement files to delete.
+/// \param[in] Diagnostics DiagnosticsEngine used for error output.
+///
+/// \returns \li true If all files have been deleted successfully.
+///          \li false If at least one or more failures occur when deleting
+/// files.
+bool deleteReplacementFiles(const TUReplacementFiles &Files,
+                            clang::DiagnosticsEngine &Diagnostics);
+
+} // end namespace replace
+} // end namespace clang
+
+#endif // LLVM_CLANG_APPLYREPLACEMENTS_H

Added: clang-tools-extra/trunk/clang-replace/lib/Tooling/ApplyReplacements.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-replace/lib/Tooling/ApplyReplacements.cpp?rev=189671&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-replace/lib/Tooling/ApplyReplacements.cpp (added)
+++ clang-tools-extra/trunk/clang-replace/lib/Tooling/ApplyReplacements.cpp Fri Aug 30 09:33:56 2013
@@ -0,0 +1,254 @@
+//===-- ApplyReplacements.cpp - Apply and deduplicate replacements --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides the implementation for deduplicating, detecting
+/// conflicts in, and applying collections of Replacements.
+///
+/// FIXME: Use Diagnostics for output instead of llvm::errs().
+///
+//===----------------------------------------------------------------------===//
+#include "clang-replace/Tooling/ApplyReplacements.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/ReplacementsYaml.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace clang;
+
+
+static void eatDiagnostics(const SMDiagnostic &, void *) {}
+
+namespace clang {
+namespace replace {
+
+
+llvm::error_code
+collectReplacementsFromDirectory(const llvm::StringRef Directory,
+                                 TUReplacements &TUs,
+                                 TUReplacementFiles & TURFiles,
+                                 clang::DiagnosticsEngine &Diagnostics) {
+  using namespace llvm::sys::fs;
+  using namespace llvm::sys::path;
+
+  error_code ErrorCode;
+
+  for (recursive_directory_iterator I(Directory, ErrorCode), E;
+       I != E && !ErrorCode; I.increment(ErrorCode)) {
+    if (filename(I->path())[0] == '.') {
+      // Indicate not to descend into directories beginning with '.'
+      I.no_push();
+      continue;
+    }
+
+    if (extension(I->path()) != ".yaml")
+      continue;
+
+    TURFiles.push_back(I->path());
+
+    OwningPtr<MemoryBuffer> Out;
+    error_code BufferError = MemoryBuffer::getFile(I->path(), Out);
+    if (BufferError) {
+      errs() << "Error reading " << I->path() << ": " << BufferError.message()
+             << "\n";
+      continue;
+    }
+
+    yaml::Input YIn(Out->getBuffer());
+    YIn.setDiagHandler(&eatDiagnostics);
+    tooling::TranslationUnitReplacements TU;
+    YIn >> TU;
+    if (YIn.error()) {
+      // File doesn't appear to be a header change description. Ignore it.
+      continue;
+    }
+
+    // Only keep files that properly parse.
+    TUs.push_back(TU);
+  }
+
+  return ErrorCode;
+}
+
+/// \brief Dumps information for a sequence of conflicting Replacements.
+///
+/// \param[in] File FileEntry for the file the conflicting Replacements are
+/// for.
+/// \param[in] ConflictingReplacements List of conflicting Replacements.
+/// \param[in] SM SourceManager used for reporting.
+static void reportConflict(
+    const FileEntry *File,
+    const llvm::ArrayRef<clang::tooling::Replacement> ConflictingReplacements,
+    SourceManager &SM) {
+  FileID FID = SM.translateFile(File);
+  if (FID.isInvalid())
+    FID = SM.createFileID(File, SourceLocation(), SrcMgr::C_User);
+
+  // FIXME: Output something a little more user-friendly (e.g. unified diff?)
+  errs() << "The following changes conflict:\n";
+  for (const tooling::Replacement *I = ConflictingReplacements.begin(),
+                                  *E = ConflictingReplacements.end();
+       I != E; ++I) {
+    if (I->getLength() == 0) {
+      errs() << "  Insert at " << SM.getLineNumber(FID, I->getOffset()) << ":"
+             << SM.getColumnNumber(FID, I->getOffset()) << " "
+             << I->getReplacementText() << "\n";
+    } else {
+      if (I->getReplacementText().empty())
+        errs() << "  Remove ";
+      else
+        errs() << "  Replace ";
+
+      errs() << SM.getLineNumber(FID, I->getOffset()) << ":"
+             << SM.getColumnNumber(FID, I->getOffset()) << "-"
+             << SM.getLineNumber(FID, I->getOffset() + I->getLength() - 1)
+             << ":"
+             << SM.getColumnNumber(FID, I->getOffset() + I->getLength() - 1);
+
+      if (I->getReplacementText().empty())
+        errs() << "\n";
+      else
+        errs() << " with \"" << I->getReplacementText() << "\"\n";
+    }
+  }
+}
+
+/// \brief Deduplicates and tests for conflicts among the replacements for each
+/// file in \c Replacements. Any conflicts found are reported.
+///
+/// \param[in,out] Replacements Container of all replacements grouped by file
+/// to be deduplicated and checked for conflicts.
+/// \param[in] SM SourceManager required for conflict reporting.
+///
+/// \returns \li true if conflicts were detected
+///          \li false if no conflicts were detected
+static bool deduplicateAndDetectConflicts(FileToReplacementsMap &Replacements,
+                                          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;
+    }
+
+    std::vector<tooling::Range> Conflicts;
+    tooling::deduplicate(I->getValue(), Conflicts);
+
+    if (Conflicts.empty())
+      continue;
+
+    conflictsFound = true;
+
+    errs() << "There are conflicting changes to " << I->getKey() << ":\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());
+      reportConflict(Entry, ConflictingReplacements, SM);
+    }
+  }
+
+  return conflictsFound;
+}
+
+bool mergeAndDeduplicate(const TUReplacements &TUs,
+                         FileToReplacementsMap &GroupedReplacements,
+                         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);
+
+
+  // Ask clang to deduplicate and report conflicts.
+  if (deduplicateAndDetectConflicts(GroupedReplacements, SM))
+    return false;
+
+  return true;
+}
+
+bool applyReplacements(const FileToReplacementsMap &GroupedReplacements,
+                       clang::Rewriter &Rewrites) {
+
+  // Apply all changes
+  //
+  // FIXME: No longer certain GroupedReplacements is really the best kind of
+  // 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))
+      return false;
+  }
+
+  return true;
+}
+
+bool writeFiles(const clang::Rewriter &Rewrites) {
+
+  for (Rewriter::const_buffer_iterator BufferI = Rewrites.buffer_begin(),
+                                       BufferE = Rewrites.buffer_end();
+       BufferI != BufferE; ++BufferI) {
+    const char *FileName =
+        Rewrites.getSourceMgr().getFileEntryForID(BufferI->first)->getName();
+
+    std::string ErrorInfo;
+
+    llvm::raw_fd_ostream FileStream(FileName, ErrorInfo);
+    if (!ErrorInfo.empty()) {
+      errs() << "Warning: Could not write to " << FileName << "\n";
+      continue;
+    }
+    BufferI->second.write(FileStream);
+  }
+
+  return true;
+}
+
+bool deleteReplacementFiles(const TUReplacementFiles &Files,
+                            clang::DiagnosticsEngine &Diagnostics) {
+  bool Success = true;
+  for (TUReplacementFiles::const_iterator I = Files.begin(), E = Files.end();
+       I != E; ++I) {
+    error_code Error = llvm::sys::fs::remove(*I);
+    if (Error) {
+      Success = false;
+      // FIXME: Use Diagnostics for outputting errors.
+      errs() << "Error deleting file: " << *I << "\n";
+      errs() << Error.message() << "\n";
+      errs() << "Please delete the file manually\n";
+    }
+  }
+  return Success;
+}
+
+} // end namespace replace
+} // end namespace clang

Added: clang-tools-extra/trunk/clang-replace/lib/Tooling/Makefile
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-replace/lib/Tooling/Makefile?rev=189671&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-replace/lib/Tooling/Makefile (added)
+++ clang-tools-extra/trunk/clang-replace/lib/Tooling/Makefile Fri Aug 30 09:33:56 2013
@@ -0,0 +1,15 @@
+
+##===- clang-replace/Makefile ------------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../../../../..
+LIBRARYNAME := clangReplace
+include $(CLANG_LEVEL)/../../Makefile.config
+include $(CLANG_LEVEL)/Makefile
+CPP.Flags += -I$(PROJ_SRC_DIR)/../../include

Modified: clang-tools-extra/trunk/clang-replace/tool/ClangReplaceMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-replace/tool/ClangReplaceMain.cpp?rev=189671&r1=189670&r2=189671&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-replace/tool/ClangReplaceMain.cpp (original)
+++ clang-tools-extra/trunk/clang-replace/tool/ClangReplaceMain.cpp Fri Aug 30 09:33:56 2013
@@ -12,7 +12,7 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#include "ApplyReplacements.h"
+#include "clang-replace/Tooling/ApplyReplacements.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/SourceManager.h"

Modified: clang-tools-extra/trunk/clang-replace/tool/Makefile
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-replace/tool/Makefile?rev=189671&r1=189670&r2=189671&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-replace/tool/Makefile (original)
+++ clang-tools-extra/trunk/clang-replace/tool/Makefile Fri Aug 30 09:33:56 2013
@@ -25,4 +25,4 @@ USEDLIBS = clangReplace.a clangFormat.a
 
 include $(CLANG_LEVEL)/Makefile
 
-CPP.Flags += -I$(PROJ_SRC_DIR)/..
+CPP.Flags += -I$(PROJ_SRC_DIR)/../include





More information about the cfe-commits mailing list