forked from OSchip/llvm-project
				
			clang-modernize: Apply replacements using clang-apply-replacements
Summary: The clang-apply-replacements process is now invoked to apply replacements between applying transforms. This resulted in a massive simplification of the tool: - FileOverrides class no longer needed. - Change tracking and code formatting no longer needed. - No more dependency on libclangApplyReplacements. - Final syntax check is easier to do directly now than with a separate header/source pair. Replacement handling stuff abstracted into a new header/source pair to de-clutter ClangModernize.cpp somewhat. Tests updated. Differential Revision: http://llvm-reviews.chandlerc.com/D1836 llvm-svn: 192032
This commit is contained in:
		
							parent
							
								
									c83946f7f5
								
							
						
					
					
						commit
						c0f00b79f7
					
				| 
						 | 
				
			
			@ -228,7 +228,7 @@ int main(int argc, char **argv) {
 | 
			
		|||
  if (ErrorCode) {
 | 
			
		||||
    errs() << "Trouble iterating over directory '" << Directory
 | 
			
		||||
           << "': " << ErrorCode.message() << "\n";
 | 
			
		||||
    return false;
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Remove the TUReplacementFiles (triggered by "remove-change-desc-files"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,8 +29,7 @@ static cl::opt<bool> DetectMacros(
 | 
			
		|||
    cl::desc("Detect and use macros that expand to the 'override' keyword."),
 | 
			
		||||
    cl::cat(TransformsOptionsCategory));
 | 
			
		||||
 | 
			
		||||
int AddOverrideTransform::apply(const FileOverrides &InputStates,
 | 
			
		||||
                                const CompilationDatabase &Database,
 | 
			
		||||
int AddOverrideTransform::apply(const CompilationDatabase &Database,
 | 
			
		||||
                                const std::vector<std::string> &SourcePaths) {
 | 
			
		||||
  ClangTool AddOverrideTool(Database, SourcePaths);
 | 
			
		||||
  unsigned AcceptedChanges = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,8 +41,6 @@ int AddOverrideTransform::apply(const FileOverrides &InputStates,
 | 
			
		|||
  // Make Fixer available to handleBeginSource().
 | 
			
		||||
  this->Fixer = &Fixer;
 | 
			
		||||
 | 
			
		||||
  setOverrides(InputStates);
 | 
			
		||||
 | 
			
		||||
  if (int result = AddOverrideTool.run(createActionFactory(Finder))) {
 | 
			
		||||
    llvm::errs() << "Error encountered during translation.\n";
 | 
			
		||||
    return result;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,8 +31,7 @@ public:
 | 
			
		|||
      : Transform("AddOverride", Options) {}
 | 
			
		||||
 | 
			
		||||
  /// \see Transform::run().
 | 
			
		||||
  virtual int apply(const FileOverrides &InputStates,
 | 
			
		||||
                    const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
  virtual int apply(const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
                    const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
 | 
			
		||||
 | 
			
		||||
  virtual bool handleBeginSource(clang::CompilerInstance &CI,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,3 @@
 | 
			
		|||
get_filename_component(ClangReplaceLocation
 | 
			
		||||
  "${CMAKE_CURRENT_SOURCE_DIR}/../clang-apply-replacements/include" ABSOLUTE)
 | 
			
		||||
 | 
			
		||||
include_directories(
 | 
			
		||||
  ${CMAKE_CURRENT_SOURCE_DIR}
 | 
			
		||||
  ${ClangReplaceLocation}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,11 @@
 | 
			
		|||
set(LLVM_LINK_COMPONENTS support)
 | 
			
		||||
 | 
			
		||||
add_clang_library(modernizeCore
 | 
			
		||||
  FileOverrides.cpp
 | 
			
		||||
  SyntaxCheck.cpp
 | 
			
		||||
  ReplacementHandling.cpp
 | 
			
		||||
  Transforms.cpp
 | 
			
		||||
  Transform.cpp
 | 
			
		||||
  IncludeExcludeInfo.cpp
 | 
			
		||||
  PerfSupport.cpp
 | 
			
		||||
  Reformatting.cpp
 | 
			
		||||
  IncludeDirectives.cpp
 | 
			
		||||
  )
 | 
			
		||||
target_link_libraries(modernizeCore
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,198 +0,0 @@
 | 
			
		|||
//===-- Core/FileOverrides.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 types and functionality for dealing with source
 | 
			
		||||
/// and header file content overrides.
 | 
			
		||||
///
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#include "Core/FileOverrides.h"
 | 
			
		||||
#include "clang/Basic/Diagnostic.h"
 | 
			
		||||
#include "clang/Basic/DiagnosticOptions.h"
 | 
			
		||||
#include "clang/Basic/SourceManager.h"
 | 
			
		||||
#include "clang/Rewrite/Core/Rewriter.h"
 | 
			
		||||
#include "clang/Tooling/Tooling.h"
 | 
			
		||||
#include "clang/Tooling/ReplacementsYaml.h"
 | 
			
		||||
#include "llvm/Support/FileSystem.h"
 | 
			
		||||
#include "llvm/Support/Path.h"
 | 
			
		||||
#include "llvm/Support/raw_ostream.h"
 | 
			
		||||
#include "llvm/Support/system_error.h"
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
using namespace clang;
 | 
			
		||||
using namespace clang::tooling;
 | 
			
		||||
 | 
			
		||||
bool generateReplacementsFileName(const llvm::StringRef MainSourceFile,
 | 
			
		||||
                                  llvm::SmallVectorImpl<char> &Result,
 | 
			
		||||
                                  llvm::SmallVectorImpl<char> &Error) {
 | 
			
		||||
  using namespace llvm::sys;
 | 
			
		||||
 | 
			
		||||
  Error.clear();
 | 
			
		||||
  if (llvm::error_code EC = fs::createUniqueFile(
 | 
			
		||||
          MainSourceFile + "_%%_%%_%%_%%_%%_%%.yaml", Result)) {
 | 
			
		||||
    Error.append(EC.message().begin(), EC.message().end());
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
/// \brief Comparator to be able to order tooling::Range based on their offset.
 | 
			
		||||
bool rangeLess(clang::tooling::Range A, clang::tooling::Range B) {
 | 
			
		||||
  if (A.getOffset() == B.getOffset())
 | 
			
		||||
    return A.getLength() < B.getLength();
 | 
			
		||||
  return A.getOffset() < B.getOffset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// \brief Functor that returns the given range without its overlaps with the
 | 
			
		||||
/// replacement given in the constructor.
 | 
			
		||||
struct RangeReplacedAdjuster {
 | 
			
		||||
  RangeReplacedAdjuster(const tooling::Replacement &Replace)
 | 
			
		||||
      : Replace(Replace.getOffset(), Replace.getLength()),
 | 
			
		||||
        ReplaceNewSize(Replace.getReplacementText().size()) {}
 | 
			
		||||
 | 
			
		||||
  tooling::Range operator()(clang::tooling::Range Range) const {
 | 
			
		||||
    if (!Range.overlapsWith(Replace))
 | 
			
		||||
      return Range;
 | 
			
		||||
    // range inside replacement -> make the range length null
 | 
			
		||||
    if (Replace.contains(Range))
 | 
			
		||||
      return tooling::Range(Range.getOffset(), 0);
 | 
			
		||||
    // replacement inside range -> resize the range
 | 
			
		||||
    if (Range.contains(Replace)) {
 | 
			
		||||
      int Difference = ReplaceNewSize - Replace.getLength();
 | 
			
		||||
      return tooling::Range(Range.getOffset(), Range.getLength() + Difference);
 | 
			
		||||
    }
 | 
			
		||||
    // beginning of the range replaced -> truncate range beginning
 | 
			
		||||
    if (Range.getOffset() > Replace.getOffset()) {
 | 
			
		||||
      unsigned ReplaceEnd = Replace.getOffset() + Replace.getLength();
 | 
			
		||||
      unsigned RangeEnd = Range.getOffset() + Range.getLength();
 | 
			
		||||
      return tooling::Range(ReplaceEnd, RangeEnd - ReplaceEnd);
 | 
			
		||||
    }
 | 
			
		||||
    // end of the range replaced -> truncate range end
 | 
			
		||||
    if (Range.getOffset() < Replace.getOffset())
 | 
			
		||||
      return tooling::Range(Range.getOffset(),
 | 
			
		||||
                            Replace.getOffset() - Range.getOffset());
 | 
			
		||||
    llvm_unreachable("conditions not handled properly");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const tooling::Range Replace;
 | 
			
		||||
  const unsigned ReplaceNewSize;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // end anonymous namespace
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ChangedRanges::adjustChangedRanges(const tooling::ReplacementsVec &Replaces) {
 | 
			
		||||
  // first adjust existing ranges in case they overlap with the replacements
 | 
			
		||||
  for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end();
 | 
			
		||||
       I != E; ++I) {
 | 
			
		||||
    const tooling::Replacement &Replace = *I;
 | 
			
		||||
 | 
			
		||||
    std::transform(Ranges.begin(), Ranges.end(), Ranges.begin(),
 | 
			
		||||
                   RangeReplacedAdjuster(Replace));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // then shift existing ranges to reflect the new positions
 | 
			
		||||
  for (RangeVec::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
 | 
			
		||||
    unsigned ShiftedOffset =
 | 
			
		||||
        tooling::shiftedCodePosition(Replaces, I->getOffset());
 | 
			
		||||
    *I = tooling::Range(ShiftedOffset, I->getLength());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // then generate the new ranges from the replacements
 | 
			
		||||
  for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end();
 | 
			
		||||
       I != E; ++I) {
 | 
			
		||||
    const tooling::Replacement &R = *I;
 | 
			
		||||
    unsigned Offset = tooling::shiftedCodePosition(Replaces, R.getOffset());
 | 
			
		||||
    unsigned Length = R.getReplacementText().size();
 | 
			
		||||
 | 
			
		||||
    Ranges.push_back(tooling::Range(Offset, Length));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // cleanups unecessary ranges to finish
 | 
			
		||||
  coalesceRanges();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ChangedRanges::coalesceRanges() {
 | 
			
		||||
  // sort the ranges by offset and then for each group of adjacent/overlapping
 | 
			
		||||
  // ranges the first one in the group is extended to cover the whole group.
 | 
			
		||||
  std::sort(Ranges.begin(), Ranges.end(), &rangeLess);
 | 
			
		||||
  RangeVec::iterator FirstInGroup = Ranges.begin();
 | 
			
		||||
  assert(!Ranges.empty() && "unexpected empty vector");
 | 
			
		||||
  for (RangeVec::iterator I = Ranges.begin() + 1, E = Ranges.end(); I != E;
 | 
			
		||||
       ++I) {
 | 
			
		||||
    unsigned GroupEnd = FirstInGroup->getOffset() + FirstInGroup->getLength();
 | 
			
		||||
 | 
			
		||||
    // no contact
 | 
			
		||||
    if (I->getOffset() > GroupEnd)
 | 
			
		||||
      FirstInGroup = I;
 | 
			
		||||
    else {
 | 
			
		||||
      unsigned GrpBegin = FirstInGroup->getOffset();
 | 
			
		||||
      unsigned GrpEnd = std::max(GroupEnd, I->getOffset() + I->getLength());
 | 
			
		||||
      *FirstInGroup = tooling::Range(GrpBegin, GrpEnd - GrpBegin);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // remove the ranges that are covered by the first member of the group
 | 
			
		||||
  Ranges.erase(std::unique(Ranges.begin(), Ranges.end(),
 | 
			
		||||
                           std::mem_fun_ref(&Range::contains)),
 | 
			
		||||
               Ranges.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileOverrides::applyOverrides(clang::SourceManager &SM) const {
 | 
			
		||||
  FileManager &FM = SM.getFileManager();
 | 
			
		||||
 | 
			
		||||
  for (FileStateMap::const_iterator I = FileStates.begin(),
 | 
			
		||||
                                    E = FileStates.end();
 | 
			
		||||
       I != E; ++I) {
 | 
			
		||||
    SM.overrideFileContents(FM.getFile(I->getKey()),
 | 
			
		||||
                            llvm::MemoryBuffer::getMemBuffer(I->getValue()));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileOverrides::adjustChangedRanges(
 | 
			
		||||
    const clang::replace::FileToReplacementsMap &Replaces) {
 | 
			
		||||
 | 
			
		||||
  for (replace::FileToReplacementsMap::const_iterator I = Replaces.begin(),
 | 
			
		||||
       E = Replaces.end(); I != E; ++I) {
 | 
			
		||||
    ChangeTracking[I->getKey()].adjustChangedRanges(I->getValue());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileOverrides::updateState(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();
 | 
			
		||||
    const RewriteBuffer &RewriteBuf = BufferI->second;
 | 
			
		||||
    FileStates[FileName].assign(RewriteBuf.begin(), RewriteBuf.end());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FileOverrides::writeToDisk(DiagnosticsEngine &Diagnostics) const {
 | 
			
		||||
  bool Errors = false;
 | 
			
		||||
  for (FileStateMap::const_iterator I = FileStates.begin(),
 | 
			
		||||
                                    E = FileStates.end();
 | 
			
		||||
       I != E; ++I) {
 | 
			
		||||
    std::string ErrorInfo;
 | 
			
		||||
    // The extra transform through std::string is to ensure null-termination
 | 
			
		||||
    // of the filename stored as the key of the StringMap.
 | 
			
		||||
    llvm::raw_fd_ostream FileStream(I->getKey().str().c_str(), ErrorInfo);
 | 
			
		||||
    if (!ErrorInfo.empty()) {
 | 
			
		||||
      llvm::errs() << "Failed to write new state for " << I->getKey() << ".\n";
 | 
			
		||||
      Errors = true;
 | 
			
		||||
    }
 | 
			
		||||
    FileStream << I->getValue();
 | 
			
		||||
  }
 | 
			
		||||
  return !Errors;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,129 +0,0 @@
 | 
			
		|||
//===-- Core/FileOverrides.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 types and functionality for dealing with source
 | 
			
		||||
/// and header file content overrides.
 | 
			
		||||
///
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#ifndef CLANG_MODERNIZE_FILE_OVERRIDES_H
 | 
			
		||||
#define CLANG_MODERNIZE_FILE_OVERRIDES_H
 | 
			
		||||
 | 
			
		||||
#include "Core/Refactoring.h"
 | 
			
		||||
#include "clang-apply-replacements/Tooling/ApplyReplacements.h"
 | 
			
		||||
#include "clang/Tooling/ReplacementsYaml.h"
 | 
			
		||||
#include "llvm/ADT/StringMap.h"
 | 
			
		||||
 | 
			
		||||
// Forward Declarations
 | 
			
		||||
namespace llvm {
 | 
			
		||||
template <typename T>
 | 
			
		||||
class SmallVectorImpl;
 | 
			
		||||
} // namespace llvm
 | 
			
		||||
namespace clang {
 | 
			
		||||
class SourceManager;
 | 
			
		||||
class Rewriter;
 | 
			
		||||
} // namespace clang
 | 
			
		||||
 | 
			
		||||
/// \brief Class encapsulating a list of \c tooling::Range with some
 | 
			
		||||
/// convenience methods.
 | 
			
		||||
///
 | 
			
		||||
/// The ranges stored are used to keep track of the overriden parts of a file.
 | 
			
		||||
class ChangedRanges {
 | 
			
		||||
  typedef std::vector<clang::tooling::Range> RangeVec;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  typedef RangeVec::const_iterator const_iterator;
 | 
			
		||||
 | 
			
		||||
  /// \brief Create new ranges from the replacements and adjust existing one
 | 
			
		||||
  /// to remove replaced parts.
 | 
			
		||||
  ///
 | 
			
		||||
  /// Note that all replacements should come from the same file.
 | 
			
		||||
  void adjustChangedRanges(const clang::tooling::ReplacementsVec &Replaces);
 | 
			
		||||
 | 
			
		||||
  /// \brief Iterators.
 | 
			
		||||
  /// \{
 | 
			
		||||
  const_iterator begin() const { return Ranges.begin(); }
 | 
			
		||||
  const_iterator end() const { return Ranges.end(); }
 | 
			
		||||
  /// \}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  void coalesceRanges();
 | 
			
		||||
 | 
			
		||||
  RangeVec Ranges;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// \brief Maintains current state of transformed files and tracks source ranges
 | 
			
		||||
/// where changes have been made.
 | 
			
		||||
class FileOverrides {
 | 
			
		||||
public:
 | 
			
		||||
  /// \brief Maps file names to file contents.
 | 
			
		||||
  typedef llvm::StringMap<std::string> FileStateMap;
 | 
			
		||||
 | 
			
		||||
  /// \brief Maps file names to change tracking info for a file.
 | 
			
		||||
  typedef llvm::StringMap<ChangedRanges> ChangeMap;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /// \brief Override file contents seen by \c SM for all files stored by this
 | 
			
		||||
  /// object.
 | 
			
		||||
  void applyOverrides(clang::SourceManager &SM) const;
 | 
			
		||||
 | 
			
		||||
  /// \brief Update change tracking information based on replacements stored in
 | 
			
		||||
  /// \c Replaces.
 | 
			
		||||
  void
 | 
			
		||||
  adjustChangedRanges(const clang::replace::FileToReplacementsMap &Replaces);
 | 
			
		||||
 | 
			
		||||
  /// \brief Accessor for change tracking information.
 | 
			
		||||
  const ChangeMap &getChangedRanges() const {
 | 
			
		||||
    return ChangeTracking;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// \brief Coalesce changes stored in \c Rewrites and replace file contents 
 | 
			
		||||
  /// overrides stored in this object.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \param Rewrites Rewriter containing changes to files.
 | 
			
		||||
  void updateState(const clang::Rewriter &Rewrites);
 | 
			
		||||
 | 
			
		||||
  /// \brief Accessor for current file state.
 | 
			
		||||
  const FileStateMap &getState() const { return FileStates; }
 | 
			
		||||
 | 
			
		||||
  /// \brief Write all file contents overrides to disk.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \param Diagnostics DiagnosticsEngine for error output.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \returns \li true if all files with overridden file contents were written
 | 
			
		||||
  ///              to disk successfully.
 | 
			
		||||
  ///          \li false if any failure occurred.
 | 
			
		||||
  bool writeToDisk(clang::DiagnosticsEngine &Diagnostics) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  FileStateMap FileStates;
 | 
			
		||||
  ChangeMap ChangeTracking;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// \brief Generate a unique filename to store the replacements.
 | 
			
		||||
///
 | 
			
		||||
/// Generates a unique filename in the same directory as \c MainSourceFile. The
 | 
			
		||||
/// filename is generated following this pattern:
 | 
			
		||||
///
 | 
			
		||||
/// MainSourceFile_%%_%%_%%_%%_%%_%%.yaml
 | 
			
		||||
///
 | 
			
		||||
/// where all '%' will be replaced by a randomly chosen hex number.
 | 
			
		||||
///
 | 
			
		||||
/// \param[in] MainSourceFile Full path to the source file.
 | 
			
		||||
/// \param[out] Result The resulting unique filename in the same directory as
 | 
			
		||||
///             the \c MainSourceFile.
 | 
			
		||||
/// \param[out] Error If an error occurs a description of that error is
 | 
			
		||||
///             placed in this string.
 | 
			
		||||
/// \returns true on success, false if a unique file name could not be created.
 | 
			
		||||
bool generateReplacementsFileName(const llvm::StringRef MainSourceFile,
 | 
			
		||||
                                  llvm::SmallVectorImpl<char> &Result,
 | 
			
		||||
                                  llvm::SmallVectorImpl<char> &Error);
 | 
			
		||||
 | 
			
		||||
#endif // CLANG_MODERNIZE_FILE_OVERRIDES_H
 | 
			
		||||
| 
						 | 
				
			
			@ -1,62 +0,0 @@
 | 
			
		|||
//===-- Core/Reformatting.cpp - LibFormat integration ---------------------===//
 | 
			
		||||
//
 | 
			
		||||
//                     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 LibFormat integration used to reformat
 | 
			
		||||
/// migrated code.
 | 
			
		||||
///
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#include "Core/Reformatting.h"
 | 
			
		||||
#include "Core/FileOverrides.h"
 | 
			
		||||
#include "clang/Basic/Diagnostic.h"
 | 
			
		||||
#include "clang/Basic/DiagnosticOptions.h"
 | 
			
		||||
#include "clang/Basic/SourceManager.h"
 | 
			
		||||
#include "clang/Lex/Lexer.h"
 | 
			
		||||
 | 
			
		||||
using namespace clang;
 | 
			
		||||
 | 
			
		||||
void Reformatter::reformatChanges(const FileOverrides &FileStates,
 | 
			
		||||
                                  clang::SourceManager &SM,
 | 
			
		||||
                                  clang::tooling::ReplacementsVec &Replaces) {
 | 
			
		||||
  FileStates.applyOverrides(SM);
 | 
			
		||||
 | 
			
		||||
  for (FileOverrides::ChangeMap::const_iterator
 | 
			
		||||
           I = FileStates.getChangedRanges().begin(),
 | 
			
		||||
           E = FileStates.getChangedRanges().end();
 | 
			
		||||
       I != E; ++I) {
 | 
			
		||||
    reformatSingleFile(I->getKey(), I->getValue(), SM, Replaces);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Reformatter::reformatSingleFile(
 | 
			
		||||
    const llvm::StringRef FileName, const ChangedRanges &Changes,
 | 
			
		||||
    SourceManager &SM, clang::tooling::ReplacementsVec &FormatReplacements) {
 | 
			
		||||
 | 
			
		||||
  const clang::FileEntry *Entry = SM.getFileManager().getFile(FileName);
 | 
			
		||||
  assert(Entry && "expected an existing file");
 | 
			
		||||
 | 
			
		||||
  FileID ID = SM.translateFile(Entry);
 | 
			
		||||
  if (ID.isInvalid())
 | 
			
		||||
    ID = SM.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User);
 | 
			
		||||
 | 
			
		||||
  std::vector<CharSourceRange> ReformatRanges;
 | 
			
		||||
  SourceLocation StartOfFile = SM.getLocForStartOfFile(ID);
 | 
			
		||||
  for (ChangedRanges::const_iterator I = Changes.begin(), E = Changes.end();
 | 
			
		||||
       I != E; ++I) {
 | 
			
		||||
    SourceLocation Start = StartOfFile.getLocWithOffset(I->getOffset());
 | 
			
		||||
    SourceLocation End = Start.getLocWithOffset(I->getLength());
 | 
			
		||||
    ReformatRanges.push_back(CharSourceRange::getCharRange(Start, End));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Lexer Lex(ID, SM.getBuffer(ID), SM, getFormattingLangOpts(Style.Standard));
 | 
			
		||||
  const tooling::Replacements &R =
 | 
			
		||||
      format::reformat(Style, Lex, SM, ReformatRanges);
 | 
			
		||||
  std::copy(R.begin(), R.end(), std::back_inserter(FormatReplacements));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,60 +0,0 @@
 | 
			
		|||
//===-- Core/Reformatting.h - LibFormat integration -------------*- 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 LibFormat integration used to reformat
 | 
			
		||||
/// migrated code.
 | 
			
		||||
///
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#ifndef CLANG_MODERNIZE_REFORMATTING_H
 | 
			
		||||
#define CLANG_MODERNIZE_REFORMATTING_H
 | 
			
		||||
 | 
			
		||||
#include "Core/Refactoring.h"
 | 
			
		||||
#include "clang/Format/Format.h"
 | 
			
		||||
 | 
			
		||||
class FileOverrides;
 | 
			
		||||
class ChangedRanges;
 | 
			
		||||
 | 
			
		||||
class Reformatter {
 | 
			
		||||
public:
 | 
			
		||||
  Reformatter(const clang::format::FormatStyle &Style) : Style(Style) {}
 | 
			
		||||
 | 
			
		||||
  /// \brief Reformat the changes made to the file overrides.
 | 
			
		||||
  ///
 | 
			
		||||
  /// This function will apply the state of files stored in \c FileState to \c
 | 
			
		||||
  /// SM.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \param[in] FileState Files to reformat.
 | 
			
		||||
  /// \param[in] SM SourceManager for access to source files.
 | 
			
		||||
  /// \param[out] Replaces Container to store all reformatting replacements.
 | 
			
		||||
  void reformatChanges(const FileOverrides &FileState, clang::SourceManager &SM,
 | 
			
		||||
                       clang::tooling::ReplacementsVec &Replaces);
 | 
			
		||||
 | 
			
		||||
  /// \brief Produce a list of replacements to apply on \p FileName, only the
 | 
			
		||||
  /// ranges in \p Changes are replaced.
 | 
			
		||||
  ///
 | 
			
		||||
  /// Since this routine use \c clang::format::reformat() the rules that
 | 
			
		||||
  /// function applies to ranges also apply here.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \param[in] FileName Name of file to reformat.
 | 
			
		||||
  /// \param[in] Changes Description of where changes were made to the file.
 | 
			
		||||
  /// \param[in] SM SourceManager required to create replacements.
 | 
			
		||||
  /// \param[out] FormatReplacements New reformatting replacements are appended
 | 
			
		||||
  /// to this container.
 | 
			
		||||
  void reformatSingleFile(const llvm::StringRef FileName,
 | 
			
		||||
                          const ChangedRanges &Changes,
 | 
			
		||||
                          clang::SourceManager &SM,
 | 
			
		||||
                          clang::tooling::ReplacementsVec &FormatReplacements);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  clang::format::FormatStyle Style;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // CLANG_MODERNIZE_REFORMATTING_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,155 @@
 | 
			
		|||
//===-- Core/ReplacementHandling.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 implementations for the ReplacementHandling class.
 | 
			
		||||
///
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#include "Core/ReplacementHandling.h"
 | 
			
		||||
#include "clang/Tooling/ReplacementsYaml.h"
 | 
			
		||||
#include "llvm/ADT/SmallString.h"
 | 
			
		||||
#include "llvm/Support/FileSystem.h"
 | 
			
		||||
#include "llvm/Support/Path.h"
 | 
			
		||||
#include "llvm/Support/Program.h"
 | 
			
		||||
#include "llvm/Support/system_error.h"
 | 
			
		||||
 | 
			
		||||
using namespace llvm;
 | 
			
		||||
using namespace llvm::sys;
 | 
			
		||||
using namespace clang::tooling;
 | 
			
		||||
 | 
			
		||||
bool ReplacementHandling::findClangApplyReplacements(const char *Argv0) {
 | 
			
		||||
  CARPath = FindProgramByName("clang-apply-replacements");
 | 
			
		||||
 | 
			
		||||
  if (!CARPath.empty())
 | 
			
		||||
    return true;
 | 
			
		||||
 | 
			
		||||
  static int StaticSymbol;
 | 
			
		||||
  CARPath = fs::getMainExecutable(Argv0, &StaticSymbol);
 | 
			
		||||
  SmallString<128> TestPath = path::parent_path(CARPath);
 | 
			
		||||
  path::append(TestPath, "clang-apply-replacements");
 | 
			
		||||
  if (fs::can_execute(Twine(TestPath)))
 | 
			
		||||
    CARPath = TestPath.str();
 | 
			
		||||
 | 
			
		||||
  return !CARPath.empty();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
StringRef ReplacementHandling::useTempDestinationDir() {
 | 
			
		||||
  DestinationDir = generateTempDir();
 | 
			
		||||
  return DestinationDir;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ReplacementHandling::enableFormatting(StringRef Style,
 | 
			
		||||
                                           StringRef StyleConfigDir) {
 | 
			
		||||
  DoFormat = true;
 | 
			
		||||
  FormatStyle = Style;
 | 
			
		||||
  this->StyleConfigDir = StyleConfigDir;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ReplacementHandling::serializeReplacements(
 | 
			
		||||
    const TUReplacementsMap &Replacements) {
 | 
			
		||||
  assert(!DestinationDir.empty() && "Destination directory not set");
 | 
			
		||||
 | 
			
		||||
  bool Errors = false;
 | 
			
		||||
 | 
			
		||||
  for (TUReplacementsMap::const_iterator I = Replacements.begin(),
 | 
			
		||||
                                         E = Replacements.end();
 | 
			
		||||
       I != E; ++I) {
 | 
			
		||||
    SmallString<128> ReplacementsFileName;
 | 
			
		||||
    SmallString<64> Error;
 | 
			
		||||
    bool Result = generateReplacementsFileName(DestinationDir,
 | 
			
		||||
                                               I->getValue().MainSourceFile,
 | 
			
		||||
                                               ReplacementsFileName, Error);
 | 
			
		||||
    if (!Result) {
 | 
			
		||||
      errs() << "Failed to generate replacements filename:" << Error << "\n";
 | 
			
		||||
      Errors = true;
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string ErrorInfo;
 | 
			
		||||
    raw_fd_ostream ReplacementsFile(ReplacementsFileName.c_str(), ErrorInfo,
 | 
			
		||||
                                    fs::F_Binary);
 | 
			
		||||
    if (!ErrorInfo.empty()) {
 | 
			
		||||
      errs() << "Error opening file: " << ErrorInfo << "\n";
 | 
			
		||||
      Errors = true;
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    yaml::Output YAML(ReplacementsFile);
 | 
			
		||||
    YAML << const_cast<TranslationUnitReplacements &>(I->getValue());
 | 
			
		||||
  }
 | 
			
		||||
  return !Errors;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ReplacementHandling::applyReplacements() {
 | 
			
		||||
  SmallVector<const char *, 8> Argv;
 | 
			
		||||
  Argv.push_back(CARPath.c_str());
 | 
			
		||||
  std::string Style = "--style=" + FormatStyle;
 | 
			
		||||
  std::string StyleConfig = "--style-config=" + StyleConfigDir;
 | 
			
		||||
  if (DoFormat) {
 | 
			
		||||
    Argv.push_back("--format");
 | 
			
		||||
    Argv.push_back(Style.c_str());
 | 
			
		||||
    if (!StyleConfigDir.empty())
 | 
			
		||||
      Argv.push_back(StyleConfig.c_str());
 | 
			
		||||
  }
 | 
			
		||||
  Argv.push_back("--remove-change-desc-files");
 | 
			
		||||
  Argv.push_back(DestinationDir.c_str());
 | 
			
		||||
 | 
			
		||||
  // Argv array needs to be null terminated.
 | 
			
		||||
  Argv.push_back(0);
 | 
			
		||||
 | 
			
		||||
  std::string ErrorMsg;
 | 
			
		||||
  bool ExecutionFailed = false;
 | 
			
		||||
  int ReturnCode = ExecuteAndWait(CARPath.c_str(), Argv.data(), /* env */ 0,
 | 
			
		||||
                                  /* redirects */ 0,
 | 
			
		||||
                                  /* secondsToWait */ 0, /* memoryLimit */ 0,
 | 
			
		||||
                                  &ErrorMsg, &ExecutionFailed);
 | 
			
		||||
  if (ExecutionFailed || !ErrorMsg.empty()) {
 | 
			
		||||
    errs() << "Failed to launch clang-apply-replacements: " << ErrorMsg << "\n";
 | 
			
		||||
    errs() << "Command Line:\n";
 | 
			
		||||
    for (const char **I = Argv.begin(), **E = Argv.end(); I != E; ++I) {
 | 
			
		||||
      if (*I)
 | 
			
		||||
        errs() << *I << "\n";
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (ReturnCode != 0) {
 | 
			
		||||
    errs() << "clang-apply-replacements failed with return code " << ReturnCode
 | 
			
		||||
           << "\n";
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string ReplacementHandling::generateTempDir() {
 | 
			
		||||
  SmallString<128> Prefix;
 | 
			
		||||
  path::system_temp_directory(true, Prefix);
 | 
			
		||||
  path::append(Prefix, "clang-modernize");
 | 
			
		||||
  SmallString<128> Result;
 | 
			
		||||
  fs::createUniqueDirectory(Twine(Prefix), Result);
 | 
			
		||||
  return Result.str();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ReplacementHandling::generateReplacementsFileName(
 | 
			
		||||
    StringRef DestinationDir, StringRef MainSourceFile,
 | 
			
		||||
    SmallVectorImpl<char> &Result, SmallVectorImpl<char> &Error) {
 | 
			
		||||
 | 
			
		||||
  Error.clear();
 | 
			
		||||
  SmallString<128> Prefix = DestinationDir;
 | 
			
		||||
  path::append(Prefix, path::filename(MainSourceFile));
 | 
			
		||||
  if (error_code EC =
 | 
			
		||||
          fs::createUniqueFile(Prefix + "_%%_%%_%%_%%_%%_%%.yaml", Result)) {
 | 
			
		||||
    const std::string &Msg = EC.message();
 | 
			
		||||
    Error.append(Msg.begin(), Msg.end());
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,119 @@
 | 
			
		|||
//===-- Core/ReplacementHandling.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 defines the ReplacementHandling class which abstracts
 | 
			
		||||
/// serialization and application of serialized replacements.
 | 
			
		||||
///
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#ifndef CLANG_MODERNIZE_REPLACEMENTHANDLING_H
 | 
			
		||||
#define CLANG_MODERNIZE_REPLACEMENTHANDLING_H
 | 
			
		||||
 | 
			
		||||
#include "llvm/ADT/StringRef.h"
 | 
			
		||||
#include "Core/Transform.h"
 | 
			
		||||
 | 
			
		||||
class ReplacementHandling {
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
  /// \brief Finds the path to the executable 'clang-apply-replacements'.
 | 
			
		||||
  ///
 | 
			
		||||
  /// The executable is searched for on the PATH. If not found, looks in the
 | 
			
		||||
  /// same directory as the image used to start the current executable.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \param[in] Argv0 argv[0] as passed to main().
 | 
			
		||||
  ///
 | 
			
		||||
  /// \returns \li true if clang-apply-replacements was found.
 | 
			
		||||
  ///          \li false otherwise.
 | 
			
		||||
  bool findClangApplyReplacements(const char *Argv0);
 | 
			
		||||
 | 
			
		||||
  /// \brief Set the name of the directory in which replacements will be
 | 
			
		||||
  /// serialized.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \param[in] Dir Destination directory  name
 | 
			
		||||
  void setDestinationDir(llvm::StringRef Dir) { DestinationDir = Dir; }
 | 
			
		||||
 | 
			
		||||
  /// \brief Create a new temporary directory to serialize replacements into.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \returns The name of the directory createdy.
 | 
			
		||||
  llvm::StringRef useTempDestinationDir();
 | 
			
		||||
 | 
			
		||||
  /// \brief Enable clang-apply-replacements do code reformatting when applying
 | 
			
		||||
  /// serialized replacements.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \param[in] Style Value to pass to clang-apply-replacement's --style
 | 
			
		||||
  /// option.
 | 
			
		||||
  /// \param[in] StyleConfigDir If non-empty, value to pass to
 | 
			
		||||
  /// clang-apply-replacement's --style-config option.
 | 
			
		||||
  void enableFormatting(llvm::StringRef Style,
 | 
			
		||||
                        llvm::StringRef StyleConfigDir = "");
 | 
			
		||||
 | 
			
		||||
  /// \brief Write all TranslationUnitReplacements stored in \c Replacements
 | 
			
		||||
  /// to disk.
 | 
			
		||||
  /// 
 | 
			
		||||
  /// \pre Destination directory must have been previously set by calling
 | 
			
		||||
  /// setDestiantionDir() or useTempDestinationDir().
 | 
			
		||||
  /// \pre Destination dir must exist.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \param[in] Replacements Container of replacements to serialize.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \returns \li true if all replacements were serialized successfully to
 | 
			
		||||
  ///          disk.
 | 
			
		||||
  ///          \li false otherwise.
 | 
			
		||||
  bool serializeReplacements(const TUReplacementsMap &Replacements);
 | 
			
		||||
 | 
			
		||||
  /// \brief Invoke clang-apply-replacements to apply all serialized
 | 
			
		||||
  /// replacements stored in the destination directory.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \pre Destination directory must have been previously set by calling
 | 
			
		||||
  /// setDestiantionDir() or useTempDestinationDir().
 | 
			
		||||
  ///
 | 
			
		||||
  /// \returns \li true if clang-apply-replacements was successfully launched
 | 
			
		||||
  ///          and successfully completed.
 | 
			
		||||
  ///          \li false otherwise.
 | 
			
		||||
  bool applyReplacements();
 | 
			
		||||
 | 
			
		||||
  /// \brief Generate a unique filename to store the replacements.
 | 
			
		||||
  ///
 | 
			
		||||
  /// Generates a unique filename in \c DestinationDir. The filename is generated
 | 
			
		||||
  /// following this pattern:
 | 
			
		||||
  ///
 | 
			
		||||
  /// DestinationDir/Prefix_%%_%%_%%_%%_%%_%%.yaml
 | 
			
		||||
  ///
 | 
			
		||||
  /// where Prefix := llvm::sys::path::filename(MainSourceFile) and all '%' will
 | 
			
		||||
  /// be replaced by a randomly chosen hex digit.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \param[in] DestinationDir Directory the unique file should be placed in.
 | 
			
		||||
  /// \param[in] MainSourceFile Full path to the source file.
 | 
			
		||||
  /// \param[out] Result The resulting unique filename.
 | 
			
		||||
  /// \param[out] Error If an error occurs a description of that error is
 | 
			
		||||
  ///             placed in this string.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \returns \li true on success
 | 
			
		||||
  ///          \li false if a unique file name could not be created.
 | 
			
		||||
  static bool generateReplacementsFileName(llvm::StringRef DestinationDir,
 | 
			
		||||
                                           llvm::StringRef MainSourceFile,
 | 
			
		||||
                                           llvm::SmallVectorImpl<char> &Result,
 | 
			
		||||
                                           llvm::SmallVectorImpl<char> &Error);
 | 
			
		||||
 | 
			
		||||
  /// \brief Helper to create a temporary directory name.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \param[out] Resulting name is placed here.
 | 
			
		||||
  static std::string generateTempDir();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
  std::string CARPath;
 | 
			
		||||
  std::string DestinationDir;
 | 
			
		||||
  bool DoFormat;
 | 
			
		||||
  std::string FormatStyle;
 | 
			
		||||
  std::string StyleConfigDir;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // CLANG_MODERNIZE_REPLACEMENTHANDLING_H
 | 
			
		||||
| 
						 | 
				
			
			@ -1,73 +0,0 @@
 | 
			
		|||
//===-- Core/SyntaxCheck.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 exposes functionaliy for doing a syntax-only check on
 | 
			
		||||
/// files with overridden contents.
 | 
			
		||||
///
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#include "Core/SyntaxCheck.h"
 | 
			
		||||
#include "Core/FileOverrides.h"
 | 
			
		||||
#include "clang/Frontend/CompilerInstance.h"
 | 
			
		||||
#include "clang/Frontend/FrontendActions.h"
 | 
			
		||||
#include "clang/Tooling/Tooling.h"
 | 
			
		||||
 | 
			
		||||
using namespace clang;
 | 
			
		||||
using namespace tooling;
 | 
			
		||||
 | 
			
		||||
class SyntaxCheck : public SyntaxOnlyAction {
 | 
			
		||||
public:
 | 
			
		||||
  SyntaxCheck(const FileOverrides &Overrides) : Overrides(Overrides) {}
 | 
			
		||||
 | 
			
		||||
  virtual bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) {
 | 
			
		||||
    if (!SyntaxOnlyAction::BeginSourceFileAction(CI, Filename))
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    Overrides.applyOverrides(CI.getSourceManager());
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  const FileOverrides &Overrides;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class SyntaxCheckFactory : public FrontendActionFactory {
 | 
			
		||||
public:
 | 
			
		||||
  SyntaxCheckFactory(const FileOverrides &Overrides)
 | 
			
		||||
      : Overrides(Overrides) {}
 | 
			
		||||
 | 
			
		||||
  virtual FrontendAction *create() { return new SyntaxCheck(Overrides); }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  const FileOverrides &Overrides;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class SyntaxArgumentsAdjuster : public ArgumentsAdjuster {
 | 
			
		||||
  CommandLineArguments Adjust(const CommandLineArguments &Args) {
 | 
			
		||||
    CommandLineArguments AdjustedArgs = Args;
 | 
			
		||||
    AdjustedArgs.push_back("-fsyntax-only");
 | 
			
		||||
    AdjustedArgs.push_back("-std=c++11");
 | 
			
		||||
    return AdjustedArgs;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool doSyntaxCheck(const CompilationDatabase &Database,
 | 
			
		||||
                   const std::vector<std::string> &SourcePaths,
 | 
			
		||||
                   const FileOverrides &Overrides) {
 | 
			
		||||
  ClangTool SyntaxTool(Database, SourcePaths);
 | 
			
		||||
 | 
			
		||||
  // Ensure C++11 support is enabled.
 | 
			
		||||
  // FIXME: This isn't necessary anymore since the Modernizer requires C++11
 | 
			
		||||
  // to be enabled in the CompilationDatabase. Remove later.
 | 
			
		||||
  SyntaxTool.setArgumentsAdjuster(new SyntaxArgumentsAdjuster);
 | 
			
		||||
 | 
			
		||||
  return SyntaxTool.run(new SyntaxCheckFactory(Overrides)) == 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,38 +0,0 @@
 | 
			
		|||
//===-- Core/SyntaxCheck.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 exposes functionaliy for doing a syntax-only check on
 | 
			
		||||
/// files with overridden contents.
 | 
			
		||||
///
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#ifndef CLANG_MODERNIZE_SYNTAX_CHECK_H
 | 
			
		||||
#define CLANG_MODERNIZE_SYNTAX_CHECK_H
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
// Forward Declarations
 | 
			
		||||
namespace clang {
 | 
			
		||||
namespace tooling {
 | 
			
		||||
class CompilationDatabase;
 | 
			
		||||
} // namespace tooling
 | 
			
		||||
} // namespace clang
 | 
			
		||||
 | 
			
		||||
class FileOverrides;
 | 
			
		||||
 | 
			
		||||
/// \brief Perform a syntax-only check over all files in \c SourcePaths using
 | 
			
		||||
/// options provided by \c Database using file contents from \c Overrides if
 | 
			
		||||
/// available.
 | 
			
		||||
extern bool doSyntaxCheck(const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
                          const std::vector<std::string> &SourcePaths,
 | 
			
		||||
                          const FileOverrides &Overrides);
 | 
			
		||||
 | 
			
		||||
#endif // CLANG_MODERNIZE_SYNTAX_CHECK_H
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +14,6 @@
 | 
			
		|||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#include "Core/Transform.h"
 | 
			
		||||
#include "Core/FileOverrides.h"
 | 
			
		||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
 | 
			
		||||
#include "clang/Basic/LangOptions.h"
 | 
			
		||||
#include "clang/Basic/SourceManager.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +75,7 @@ private:
 | 
			
		|||
} // namespace
 | 
			
		||||
 | 
			
		||||
Transform::Transform(llvm::StringRef Name, const TransformOptions &Options)
 | 
			
		||||
    : Name(Name), GlobalOptions(Options), Overrides(0) {
 | 
			
		||||
    : Name(Name), GlobalOptions(Options) {
 | 
			
		||||
  Reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -95,9 +94,6 @@ bool Transform::isFileModifiable(const SourceManager &SM,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
 | 
			
		||||
  assert(Overrides != 0 && "Subclass transform didn't provide InputState");
 | 
			
		||||
 | 
			
		||||
  Overrides->applyOverrides(CI.getSourceManager());
 | 
			
		||||
  CurrentSource = Filename;
 | 
			
		||||
 | 
			
		||||
  if (Options().EnableTiming) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,9 +50,6 @@ class MatchFinder;
 | 
			
		|||
} // namespace ast_matchers
 | 
			
		||||
} // namespace clang
 | 
			
		||||
 | 
			
		||||
class FileOverrides;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// \brief Maps main source file names to a TranslationUnitReplacements
 | 
			
		||||
// structure storing replacements for that translation unit.
 | 
			
		||||
typedef llvm::StringMap<clang::tooling::TranslationUnitReplacements>
 | 
			
		||||
| 
						 | 
				
			
			@ -95,13 +92,13 @@ public:
 | 
			
		|||
 | 
			
		||||
  /// \brief Apply a transform to all files listed in \p SourcePaths.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \p Database must contain information for how to compile all files in \p
 | 
			
		||||
  /// SourcePaths. \p InputStates contains the file contents of files in \p
 | 
			
		||||
  /// SourcePaths and should take precedence over content of files on disk.
 | 
			
		||||
  /// Upon return, \p ResultStates shall contain the result of performing this
 | 
			
		||||
  /// transform on the files listed in \p SourcePaths.
 | 
			
		||||
  virtual int apply(const FileOverrides &InputStates,
 | 
			
		||||
                    const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
  /// \param[in] Database Contains information for how to compile all files in
 | 
			
		||||
  /// \p SourcePaths.
 | 
			
		||||
  /// \param[in] SourcePaths list of sources to transform.
 | 
			
		||||
  ///
 | 
			
		||||
  /// \returns \li 0 if successful
 | 
			
		||||
  ///          \li 1 otherwise
 | 
			
		||||
  virtual int apply(const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
                    const std::vector<std::string> &SourcePaths) = 0;
 | 
			
		||||
 | 
			
		||||
  /// \brief Query if changes were made during the last call to apply().
 | 
			
		||||
| 
						 | 
				
			
			@ -207,15 +204,6 @@ protected:
 | 
			
		|||
  /// created with.
 | 
			
		||||
  const TransformOptions &Options() { return GlobalOptions; }
 | 
			
		||||
 | 
			
		||||
  /// \brief Affords a subclass to provide file contents overrides before
 | 
			
		||||
  /// applying frontend actions.
 | 
			
		||||
  ///
 | 
			
		||||
  /// It is an error not to call this function before calling ClangTool::run()
 | 
			
		||||
  /// with the factory provided by createActionFactory().
 | 
			
		||||
  void setOverrides(const FileOverrides &Overrides) {
 | 
			
		||||
    this->Overrides = &Overrides;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// \brief Subclasses must call this function to create a
 | 
			
		||||
  /// FrontendActionFactory to pass to ClangTool.
 | 
			
		||||
  ///
 | 
			
		||||
| 
						 | 
				
			
			@ -227,7 +215,6 @@ protected:
 | 
			
		|||
private:
 | 
			
		||||
  const std::string Name;
 | 
			
		||||
  const TransformOptions &GlobalOptions;
 | 
			
		||||
  const FileOverrides *Overrides;
 | 
			
		||||
  TUReplacementsMap Replacements;
 | 
			
		||||
  std::string CurrentSource;
 | 
			
		||||
  TimingVec Timings;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,8 +24,7 @@ using clang::ast_matchers::MatchFinder;
 | 
			
		|||
using namespace clang::tooling;
 | 
			
		||||
using namespace clang;
 | 
			
		||||
 | 
			
		||||
int LoopConvertTransform::apply(const FileOverrides &InputStates,
 | 
			
		||||
                                const CompilationDatabase &Database,
 | 
			
		||||
int LoopConvertTransform::apply(const CompilationDatabase &Database,
 | 
			
		||||
                                const std::vector<std::string> &SourcePaths) {
 | 
			
		||||
  ClangTool LoopTool(Database, SourcePaths);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,8 +48,6 @@ int LoopConvertTransform::apply(const FileOverrides &InputStates,
 | 
			
		|||
                                  LFK_PseudoArray, /*Owner=*/ *this);
 | 
			
		||||
  Finder.addMatcher(makePseudoArrayLoopMatcher(), &PseudoarrrayLoopFixer);
 | 
			
		||||
 | 
			
		||||
  setOverrides(InputStates);
 | 
			
		||||
 | 
			
		||||
  if (int result = LoopTool.run(createActionFactory(Finder))) {
 | 
			
		||||
    llvm::errs() << "Error encountered during translation.\n";
 | 
			
		||||
    return result;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,8 +31,7 @@ public:
 | 
			
		|||
      : Transform("LoopConvert", Options) {}
 | 
			
		||||
 | 
			
		||||
  /// \see Transform::run().
 | 
			
		||||
  virtual int apply(const FileOverrides &InputStates,
 | 
			
		||||
                    const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
  virtual int apply(const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
                    const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
 | 
			
		||||
 | 
			
		||||
  virtual bool handleBeginSource(clang::CompilerInstance &CI,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,8 +21,7 @@ using namespace clang;
 | 
			
		|||
using namespace clang::tooling;
 | 
			
		||||
using namespace clang::ast_matchers;
 | 
			
		||||
 | 
			
		||||
int PassByValueTransform::apply(const FileOverrides &InputStates,
 | 
			
		||||
                                const tooling::CompilationDatabase &Database,
 | 
			
		||||
int PassByValueTransform::apply(const tooling::CompilationDatabase &Database,
 | 
			
		||||
                                const std::vector<std::string> &SourcePaths) {
 | 
			
		||||
  ClangTool Tool(Database, SourcePaths);
 | 
			
		||||
  unsigned AcceptedChanges = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -36,8 +35,6 @@ int PassByValueTransform::apply(const FileOverrides &InputStates,
 | 
			
		|||
  // make the replacer available to handleBeginSource()
 | 
			
		||||
  this->Replacer = &Replacer;
 | 
			
		||||
 | 
			
		||||
  setOverrides(InputStates);
 | 
			
		||||
 | 
			
		||||
  if (Tool.run(createActionFactory(Finder))) {
 | 
			
		||||
    llvm::errs() << "Error encountered during translation.\n";
 | 
			
		||||
    return 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,8 +58,7 @@ public:
 | 
			
		|||
      : Transform("PassByValue", Options), Replacer(0) {}
 | 
			
		||||
 | 
			
		||||
  /// \see Transform::apply().
 | 
			
		||||
  virtual int apply(const FileOverrides &InputStates,
 | 
			
		||||
                    const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
  virtual int apply(const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
                    const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,8 +22,7 @@ using namespace clang::tooling;
 | 
			
		|||
using namespace clang::ast_matchers;
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
ReplaceAutoPtrTransform::apply(const FileOverrides &InputStates,
 | 
			
		||||
                               const CompilationDatabase &Database,
 | 
			
		||||
ReplaceAutoPtrTransform::apply(const CompilationDatabase &Database,
 | 
			
		||||
                               const std::vector<std::string> &SourcePaths) {
 | 
			
		||||
  ClangTool Tool(Database, SourcePaths);
 | 
			
		||||
  unsigned AcceptedChanges = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -35,8 +34,6 @@ ReplaceAutoPtrTransform::apply(const FileOverrides &InputStates,
 | 
			
		|||
  Finder.addMatcher(makeAutoPtrUsingDeclMatcher(), &Replacer);
 | 
			
		||||
  Finder.addMatcher(makeTransferOwnershipExprMatcher(), &Fixer);
 | 
			
		||||
 | 
			
		||||
  setOverrides(InputStates);
 | 
			
		||||
 | 
			
		||||
  if (Tool.run(createActionFactory(Finder))) {
 | 
			
		||||
    llvm::errs() << "Error encountered during translation.\n";
 | 
			
		||||
    return 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,8 +47,7 @@ public:
 | 
			
		|||
      : Transform("ReplaceAutoPtr", Options) {}
 | 
			
		||||
 | 
			
		||||
  /// \see Transform::run().
 | 
			
		||||
  virtual int apply(const FileOverrides &InputStates,
 | 
			
		||||
                    const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
  virtual int apply(const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
                    const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,8 +20,7 @@ using clang::ast_matchers::MatchFinder;
 | 
			
		|||
using namespace clang;
 | 
			
		||||
using namespace clang::tooling;
 | 
			
		||||
 | 
			
		||||
int UseAutoTransform::apply(const FileOverrides &InputStates,
 | 
			
		||||
                            const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
int UseAutoTransform::apply(const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
                            const std::vector<std::string> &SourcePaths) {
 | 
			
		||||
  ClangTool UseAutoTool(Database, SourcePaths);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,8 +36,6 @@ int UseAutoTransform::apply(const FileOverrides &InputStates,
 | 
			
		|||
  Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators);
 | 
			
		||||
  Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew);
 | 
			
		||||
 | 
			
		||||
  setOverrides(InputStates);
 | 
			
		||||
 | 
			
		||||
  if (int Result = UseAutoTool.run(createActionFactory(Finder))) {
 | 
			
		||||
    llvm::errs() << "Error encountered during translation.\n";
 | 
			
		||||
    return Result;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,8 +34,7 @@ public:
 | 
			
		|||
      : Transform("UseAuto", Options) {}
 | 
			
		||||
 | 
			
		||||
  /// \see Transform::run().
 | 
			
		||||
  virtual int apply(const FileOverrides &InputStates,
 | 
			
		||||
                    const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
  virtual int apply(const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
                    const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,8 +24,7 @@ using clang::ast_matchers::MatchFinder;
 | 
			
		|||
using namespace clang::tooling;
 | 
			
		||||
using namespace clang;
 | 
			
		||||
 | 
			
		||||
int UseNullptrTransform::apply(const FileOverrides &InputStates,
 | 
			
		||||
                               const CompilationDatabase &Database,
 | 
			
		||||
int UseNullptrTransform::apply(const CompilationDatabase &Database,
 | 
			
		||||
                               const std::vector<std::string> &SourcePaths) {
 | 
			
		||||
  ClangTool UseNullptrTool(Database, SourcePaths);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,8 +35,6 @@ int UseNullptrTransform::apply(const FileOverrides &InputStates,
 | 
			
		|||
 | 
			
		||||
  Finder.addMatcher(makeCastSequenceMatcher(), &Fixer);
 | 
			
		||||
 | 
			
		||||
  setOverrides(InputStates);
 | 
			
		||||
 | 
			
		||||
  if (int result = UseNullptrTool.run(createActionFactory(Finder))) {
 | 
			
		||||
    llvm::errs() << "Error encountered during translation.\n";
 | 
			
		||||
    return result;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,8 +28,7 @@ public:
 | 
			
		|||
      : Transform("UseNullptr", Options) {}
 | 
			
		||||
 | 
			
		||||
  /// \see Transform::run().
 | 
			
		||||
  virtual int apply(const FileOverrides &InputStates,
 | 
			
		||||
                    const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
  virtual int apply(const clang::tooling::CompilationDatabase &Database,
 | 
			
		||||
                    const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,6 @@ add_dependencies(clang-modernize
 | 
			
		|||
  )
 | 
			
		||||
 | 
			
		||||
target_link_libraries(clang-modernize
 | 
			
		||||
  clangApplyReplacements
 | 
			
		||||
  modernizeCore
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,23 +15,20 @@
 | 
			
		|||
///
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#include "Core/FileOverrides.h"
 | 
			
		||||
#include "Core/PerfSupport.h"
 | 
			
		||||
#include "Core/SyntaxCheck.h"
 | 
			
		||||
#include "Core/ReplacementHandling.h"
 | 
			
		||||
#include "Core/Transform.h"
 | 
			
		||||
#include "Core/Transforms.h"
 | 
			
		||||
#include "Core/Reformatting.h"
 | 
			
		||||
#include "clang/Basic/Diagnostic.h"
 | 
			
		||||
#include "clang/Basic/DiagnosticOptions.h"
 | 
			
		||||
#include "clang/Basic/SourceManager.h"
 | 
			
		||||
#include "clang/Format/Format.h"
 | 
			
		||||
#include "clang/Frontend/FrontendActions.h"
 | 
			
		||||
#include "clang/Rewrite/Core/Rewriter.h"
 | 
			
		||||
#include "clang/Tooling/CommonOptionsParser.h"
 | 
			
		||||
#include "clang/Tooling/Tooling.h"
 | 
			
		||||
#include "clang-apply-replacements/Tooling/ApplyReplacements.h"
 | 
			
		||||
#include "llvm/ADT/STLExtras.h"
 | 
			
		||||
#include "llvm/ADT/StringSwitch.h"
 | 
			
		||||
#include "llvm/Support/MemoryBuffer.h"
 | 
			
		||||
#include "llvm/Support/Path.h"
 | 
			
		||||
#include "llvm/Support/Signals.h"
 | 
			
		||||
 | 
			
		||||
namespace cl = llvm::cl;
 | 
			
		||||
| 
						 | 
				
			
			@ -81,13 +78,29 @@ static cl::opt<bool> FinalSyntaxCheck(
 | 
			
		|||
    cl::desc("Check for correct syntax after applying transformations"),
 | 
			
		||||
    cl::init(false));
 | 
			
		||||
 | 
			
		||||
static cl::opt<std::string> FormatStyleOpt(
 | 
			
		||||
    "format-style",
 | 
			
		||||
    cl::desc("Coding style to use on the replacements, either a builtin style\n"
 | 
			
		||||
             "or a YAML config file (see: clang-format -dump-config).\n"
 | 
			
		||||
             "Currently supports 4 builtins style:\n"
 | 
			
		||||
             "  LLVM, Google, Chromium, Mozilla.\n"),
 | 
			
		||||
    cl::value_desc("string"));
 | 
			
		||||
static cl::OptionCategory FormattingCategory("Formatting Options");
 | 
			
		||||
 | 
			
		||||
static cl::opt<bool> DoFormat(
 | 
			
		||||
    "format",
 | 
			
		||||
    cl::desc("Enable formatting of code changed by applying replacements.\n"
 | 
			
		||||
             "Use -style to choose formatting style.\n"),
 | 
			
		||||
    cl::cat(FormattingCategory));
 | 
			
		||||
 | 
			
		||||
static cl::opt<std::string>
 | 
			
		||||
FormatStyleOpt("style", cl::desc(format::StyleOptionHelpDescription),
 | 
			
		||||
               cl::init("LLVM"), cl::cat(FormattingCategory));
 | 
			
		||||
 | 
			
		||||
// FIXME: Consider making the default behaviour for finding a style
 | 
			
		||||
// configuration file to start the search anew for every file being changed to
 | 
			
		||||
// handle situations where the style is different for different parts of a
 | 
			
		||||
// project.
 | 
			
		||||
 | 
			
		||||
static cl::opt<std::string> FormatStyleConfig(
 | 
			
		||||
    "style-config",
 | 
			
		||||
    cl::desc("Path to a directory containing a .clang-format file\n"
 | 
			
		||||
             "describing a formatting style to use for formatting\n"
 | 
			
		||||
             "code when -style=file.\n"),
 | 
			
		||||
    cl::init(""), cl::cat(FormattingCategory));
 | 
			
		||||
 | 
			
		||||
static cl::opt<bool>
 | 
			
		||||
SummaryMode("summary", cl::desc("Print transform summary"),
 | 
			
		||||
| 
						 | 
				
			
			@ -98,29 +111,46 @@ static cl::opt<std::string> TimingDirectoryName(
 | 
			
		|||
                     "directory. Default: ./migrate_perf"),
 | 
			
		||||
    cl::ValueOptional, cl::value_desc("directory name"));
 | 
			
		||||
 | 
			
		||||
static cl::OptionCategory IncludeExcludeCategory("Inclusion/Exclusion Options");
 | 
			
		||||
 | 
			
		||||
static cl::opt<std::string>
 | 
			
		||||
IncludePaths("include",
 | 
			
		||||
             cl::desc("Comma seperated list of paths to consider to be "
 | 
			
		||||
                      "transformed"));
 | 
			
		||||
                      "transformed"),
 | 
			
		||||
             cl::cat(IncludeExcludeCategory));
 | 
			
		||||
 | 
			
		||||
static cl::opt<std::string>
 | 
			
		||||
ExcludePaths("exclude",
 | 
			
		||||
             cl::desc("Comma seperated list of paths that can not "
 | 
			
		||||
                      "be transformed"));
 | 
			
		||||
ExcludePaths("exclude", cl::desc("Comma seperated list of paths that can not "
 | 
			
		||||
                                 "be transformed"),
 | 
			
		||||
             cl::cat(IncludeExcludeCategory));
 | 
			
		||||
 | 
			
		||||
static cl::opt<std::string>
 | 
			
		||||
IncludeFromFile("include-from", cl::value_desc("filename"),
 | 
			
		||||
                cl::desc("File containing a list of paths to consider to "
 | 
			
		||||
                         "be transformed"));
 | 
			
		||||
                         "be transformed"),
 | 
			
		||||
                cl::cat(IncludeExcludeCategory));
 | 
			
		||||
 | 
			
		||||
static cl::opt<std::string>
 | 
			
		||||
ExcludeFromFile("exclude-from", cl::value_desc("filename"),
 | 
			
		||||
                cl::desc("File containing a list of paths that can not be "
 | 
			
		||||
                         "transforms"));
 | 
			
		||||
                         "transforms"),
 | 
			
		||||
                cl::cat(IncludeExcludeCategory));
 | 
			
		||||
 | 
			
		||||
static cl::OptionCategory SerializeCategory("Serialization Options");
 | 
			
		||||
 | 
			
		||||
static cl::opt<bool>
 | 
			
		||||
SerializeReplacements("serialize-replacements",
 | 
			
		||||
                      cl::Hidden,
 | 
			
		||||
SerializeOnly("serialize-replacements",
 | 
			
		||||
              cl::desc("Serialize translation unit replacements to "
 | 
			
		||||
                       "disk instead of changing files."),
 | 
			
		||||
                      cl::init(false));
 | 
			
		||||
              cl::init(false),
 | 
			
		||||
              cl::cat(SerializeCategory));
 | 
			
		||||
 | 
			
		||||
static cl::opt<std::string>
 | 
			
		||||
SerializeLocation("serialize-dir",
 | 
			
		||||
                  cl::desc("Path to an existing directory in which to write\n"
 | 
			
		||||
                           "serialized replacements. Default behaviour is to\n"
 | 
			
		||||
                           "write to a temporary directory.\n"),
 | 
			
		||||
                  cl::cat(SerializeCategory));
 | 
			
		||||
 | 
			
		||||
cl::opt<std::string> SupportedCompilers(
 | 
			
		||||
    "for-compilers", cl::value_desc("string"),
 | 
			
		||||
| 
						 | 
				
			
			@ -184,102 +214,6 @@ static CompilerVersions handleSupportedCompilers(const char *ProgName,
 | 
			
		|||
  return RequiredVersions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// \brief Creates the Reformatter if the format style option is provided,
 | 
			
		||||
/// return a null pointer otherwise.
 | 
			
		||||
///
 | 
			
		||||
/// \param ProgName The name of the program, \c argv[0], used to print errors.
 | 
			
		||||
/// \param Error If the \c -format-style is provided but with wrong parameters
 | 
			
		||||
/// this is parameter is set to \c true, left untouched otherwise. An error
 | 
			
		||||
/// message is printed with an explanation.
 | 
			
		||||
static Reformatter *handleFormatStyle(const char *ProgName, bool &Error) {
 | 
			
		||||
  if (FormatStyleOpt.getNumOccurrences() > 0) {
 | 
			
		||||
    format::FormatStyle Style;
 | 
			
		||||
    if (!format::getPredefinedStyle(FormatStyleOpt, &Style)) {
 | 
			
		||||
      llvm::StringRef ConfigFilePath = FormatStyleOpt;
 | 
			
		||||
      llvm::OwningPtr<llvm::MemoryBuffer> Text;
 | 
			
		||||
      llvm::error_code ec;
 | 
			
		||||
 | 
			
		||||
      ec = llvm::MemoryBuffer::getFile(ConfigFilePath, Text);
 | 
			
		||||
      if (!ec)
 | 
			
		||||
        ec = parseConfiguration(Text->getBuffer(), &Style);
 | 
			
		||||
 | 
			
		||||
      if (ec) {
 | 
			
		||||
        llvm::errs() << ProgName << ": invalid format style " << FormatStyleOpt
 | 
			
		||||
                     << ": " << ec.message() << "\n";
 | 
			
		||||
        Error = true;
 | 
			
		||||
        return 0;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // force mode to C++11
 | 
			
		||||
    Style.Standard = clang::format::FormatStyle::LS_Cpp11;
 | 
			
		||||
    return new Reformatter(Style);
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// \brief Use \c ChangesReformatter to reformat all changed regions of all
 | 
			
		||||
/// files stored in \c Overrides and write the result to disk.
 | 
			
		||||
///
 | 
			
		||||
/// \returns \li true if reformatting replacements were successfully applied
 | 
			
		||||
///              without conflicts and all files were successfully written to
 | 
			
		||||
///              disk.
 | 
			
		||||
///          \li false if reformatting could not be successfully applied or
 | 
			
		||||
///              if at least one file failed to write to disk.
 | 
			
		||||
void reformat(Reformatter &ChangesReformatter, FileOverrides &Overrides,
 | 
			
		||||
              DiagnosticsEngine &Diagnostics) {
 | 
			
		||||
  FileManager Files((FileSystemOptions()));
 | 
			
		||||
  SourceManager SM(Diagnostics, Files);
 | 
			
		||||
 | 
			
		||||
  replace::TUReplacements AllReplacements(1);
 | 
			
		||||
  ChangesReformatter.reformatChanges(Overrides, SM,
 | 
			
		||||
                                     AllReplacements.front().Replacements);
 | 
			
		||||
 | 
			
		||||
  replace::FileToReplacementsMap GroupedReplacements;
 | 
			
		||||
  if (!replace::mergeAndDeduplicate(AllReplacements, GroupedReplacements, SM)) {
 | 
			
		||||
    llvm::errs() << "Warning: Reformatting produced conflicts.\n";
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Rewriter DestRewriter(SM, LangOptions());
 | 
			
		||||
  if (!replace::applyReplacements(GroupedReplacements, DestRewriter)) {
 | 
			
		||||
    llvm::errs() << "Warning: Failed to apply reformatting conflicts!\n";
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Overrides.updateState(DestRewriter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool serializeReplacements(const replace::TUReplacements &Replacements) {
 | 
			
		||||
  bool Errors = false;
 | 
			
		||||
  for (replace::TUReplacements::const_iterator I = Replacements.begin(),
 | 
			
		||||
                                               E = Replacements.end();
 | 
			
		||||
       I != E; ++I) {
 | 
			
		||||
    llvm::SmallString<128> ReplacementsFileName;
 | 
			
		||||
    llvm::SmallString<64> Error;
 | 
			
		||||
    bool Result = generateReplacementsFileName(I->MainSourceFile,
 | 
			
		||||
                                               ReplacementsFileName, Error);
 | 
			
		||||
    if (!Result) {
 | 
			
		||||
      llvm::errs() << "Failed to generate replacements filename:" << Error
 | 
			
		||||
                   << "\n";
 | 
			
		||||
      Errors = true;
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string ErrorInfo;
 | 
			
		||||
    llvm::raw_fd_ostream ReplacementsFile(ReplacementsFileName.c_str(),
 | 
			
		||||
                                          ErrorInfo, llvm::sys::fs::F_Binary);
 | 
			
		||||
    if (!ErrorInfo.empty()) {
 | 
			
		||||
      llvm::errs() << "Error opening file: " << ErrorInfo << "\n";
 | 
			
		||||
      Errors = true;
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    llvm::yaml::Output YAML(ReplacementsFile);
 | 
			
		||||
    YAML << const_cast<TranslationUnitReplacements &>(*I);
 | 
			
		||||
  }
 | 
			
		||||
  return !Errors;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CompilationDatabase *autoDetectCompilations(std::string &ErrorMessage) {
 | 
			
		||||
  // Auto-detect a compilation database from BuildPath.
 | 
			
		||||
  if (BuildPath.getNumOccurrences() > 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -332,6 +266,7 @@ static bool isFileExplicitlyExcludedPredicate(llvm::StringRef FilePath) {
 | 
			
		|||
int main(int argc, const char **argv) {
 | 
			
		||||
  llvm::sys::PrintStackTraceOnErrorSignal();
 | 
			
		||||
  Transforms TransformManager;
 | 
			
		||||
  ReplacementHandling ReplacementHandler;
 | 
			
		||||
 | 
			
		||||
  TransformManager.registerTransforms();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -386,11 +321,7 @@ int main(int argc, const char **argv) {
 | 
			
		|||
  // Enable timming.
 | 
			
		||||
  GlobalOptions.EnableTiming = TimingDirectoryName.getNumOccurrences() > 0;
 | 
			
		||||
 | 
			
		||||
  // Check the reformatting style option
 | 
			
		||||
  bool CmdSwitchError = false;
 | 
			
		||||
  llvm::OwningPtr<Reformatter> ChangesReformatter(
 | 
			
		||||
      handleFormatStyle(argv[0], CmdSwitchError));
 | 
			
		||||
 | 
			
		||||
  CompilerVersions RequiredVersions =
 | 
			
		||||
      handleSupportedCompilers(argv[0], CmdSwitchError);
 | 
			
		||||
  if (CmdSwitchError)
 | 
			
		||||
| 
						 | 
				
			
			@ -398,15 +329,6 @@ int main(int argc, const char **argv) {
 | 
			
		|||
 | 
			
		||||
  TransformManager.createSelectedTransforms(GlobalOptions, RequiredVersions);
 | 
			
		||||
 | 
			
		||||
  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
 | 
			
		||||
      new DiagnosticOptions());
 | 
			
		||||
  DiagnosticsEngine Diagnostics(
 | 
			
		||||
      llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
 | 
			
		||||
      DiagOpts.getPtr());
 | 
			
		||||
 | 
			
		||||
  // FIXME: Make this DiagnosticsEngine available to all Transforms probably via
 | 
			
		||||
  // GlobalOptions.
 | 
			
		||||
 | 
			
		||||
  if (TransformManager.begin() == TransformManager.end()) {
 | 
			
		||||
    if (SupportedCompilers.empty())
 | 
			
		||||
      llvm::errs() << llvm::sys::path::filename(argv[0])
 | 
			
		||||
| 
						 | 
				
			
			@ -417,28 +339,52 @@ int main(int argc, const char **argv) {
 | 
			
		|||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If SerializeReplacements is requested, then change reformatting must be
 | 
			
		||||
  // turned off and only one transform should be requested. Reformatting is
 | 
			
		||||
  // basically another transform so even if there's only one other transform,
 | 
			
		||||
  // the reformatting pass would make two.
 | 
			
		||||
  if (SerializeReplacements &&
 | 
			
		||||
  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
 | 
			
		||||
      new DiagnosticOptions());
 | 
			
		||||
  DiagnosticsEngine Diagnostics(
 | 
			
		||||
      llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
 | 
			
		||||
      DiagOpts.getPtr());
 | 
			
		||||
 | 
			
		||||
  // FIXME: Make this DiagnosticsEngine available to all Transforms probably via
 | 
			
		||||
  // GlobalOptions.
 | 
			
		||||
 | 
			
		||||
  // If SerializeReplacements is requested, then code reformatting must be
 | 
			
		||||
  // turned off and only one transform should be requested.
 | 
			
		||||
  if (SerializeOnly &&
 | 
			
		||||
      (std::distance(TransformManager.begin(), TransformManager.end()) > 1 ||
 | 
			
		||||
       ChangesReformatter)) {
 | 
			
		||||
       DoFormat)) {
 | 
			
		||||
    llvm::errs() << "Serialization of replacements requested for multiple "
 | 
			
		||||
                    "transforms.\nChanges from only one transform can be "
 | 
			
		||||
                    "serialized.\n";
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If we're asked to apply changes to files on disk, need to locate
 | 
			
		||||
  // clang-apply-replacements.
 | 
			
		||||
  if (!SerializeOnly) {
 | 
			
		||||
    if (!ReplacementHandler.findClangApplyReplacements(argv[0])) {
 | 
			
		||||
      llvm::errs() << "Could not find clang-apply-replacements\n";
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (DoFormat)
 | 
			
		||||
      ReplacementHandler.enableFormatting(FormatStyleOpt, FormatStyleConfig);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  StringRef TempDestinationDir;
 | 
			
		||||
  if (SerializeLocation.getNumOccurrences() > 0)
 | 
			
		||||
    ReplacementHandler.setDestinationDir(SerializeLocation);
 | 
			
		||||
  else
 | 
			
		||||
    TempDestinationDir = ReplacementHandler.useTempDestinationDir();
 | 
			
		||||
 | 
			
		||||
  SourcePerfData PerfData;
 | 
			
		||||
  FileOverrides FileStates;
 | 
			
		||||
 | 
			
		||||
  for (Transforms::const_iterator I = TransformManager.begin(),
 | 
			
		||||
                                  E = TransformManager.end();
 | 
			
		||||
       I != E; ++I) {
 | 
			
		||||
    Transform *T = *I;
 | 
			
		||||
 | 
			
		||||
    if (T->apply(FileStates, *Compilations, Sources) != 0) {
 | 
			
		||||
    if (T->apply(*Compilations, Sources) != 0) {
 | 
			
		||||
      // FIXME: Improve ClangTool to not abort if just one file fails.
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -456,65 +402,25 @@ int main(int argc, const char **argv) {
 | 
			
		|||
      llvm::outs() << "\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Collect all TranslationUnitReplacements generated from the translation
 | 
			
		||||
    // units the transform worked on and store them in AllReplacements.
 | 
			
		||||
    replace::TUReplacements AllReplacements;
 | 
			
		||||
    const TUReplacementsMap &ReplacementsMap = T->getAllReplacements();
 | 
			
		||||
    const TranslationUnitReplacements &(
 | 
			
		||||
        TUReplacementsMap::value_type::*getValue)() const =
 | 
			
		||||
        &TUReplacementsMap::value_type::getValue;
 | 
			
		||||
    std::transform(ReplacementsMap.begin(), ReplacementsMap.end(),
 | 
			
		||||
                   std::back_inserter(AllReplacements),
 | 
			
		||||
                   std::mem_fun_ref(getValue));
 | 
			
		||||
 | 
			
		||||
    if (SerializeReplacements)
 | 
			
		||||
      serializeReplacements(AllReplacements);
 | 
			
		||||
 | 
			
		||||
    FileManager Files((FileSystemOptions()));
 | 
			
		||||
    SourceManager SM(Diagnostics, Files);
 | 
			
		||||
 | 
			
		||||
    // Make sure SourceManager is updated to have the same initial state as the
 | 
			
		||||
    // transforms.
 | 
			
		||||
    FileStates.applyOverrides(SM);
 | 
			
		||||
 | 
			
		||||
    replace::FileToReplacementsMap GroupedReplacements;
 | 
			
		||||
    if (!replace::mergeAndDeduplicate(AllReplacements, GroupedReplacements,
 | 
			
		||||
                                      SM)) {
 | 
			
		||||
      llvm::outs() << "Transform " << T->getName()
 | 
			
		||||
                   << " resulted in conflicts. Discarding all "
 | 
			
		||||
                   << "replacements.\n";
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Apply replacements and update FileStates with new state.
 | 
			
		||||
    Rewriter DestRewriter(SM, LangOptions());
 | 
			
		||||
    if (!replace::applyReplacements(GroupedReplacements, DestRewriter)) {
 | 
			
		||||
      llvm::outs() << "Some replacements failed to apply. Discarding "
 | 
			
		||||
                      "all replacements.\n";
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Update contents of files in memory to serve as initial state for next
 | 
			
		||||
    // transform.
 | 
			
		||||
    FileStates.updateState(DestRewriter);
 | 
			
		||||
 | 
			
		||||
    // Update changed ranges for reformatting
 | 
			
		||||
    if (ChangesReformatter)
 | 
			
		||||
      FileStates.adjustChangedRanges(GroupedReplacements);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Skip writing final file states to disk if we were asked to serialize
 | 
			
		||||
  // replacements. Otherwise reformat changes if reformatting is enabled.
 | 
			
		||||
  if (!SerializeReplacements) {
 | 
			
		||||
    if (ChangesReformatter)
 | 
			
		||||
      reformat(*ChangesReformatter, FileStates, Diagnostics);
 | 
			
		||||
    FileStates.writeToDisk(Diagnostics);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (FinalSyntaxCheck)
 | 
			
		||||
    if (!doSyntaxCheck(*Compilations, Sources, FileStates))
 | 
			
		||||
    if (!ReplacementHandler.serializeReplacements(T->getAllReplacements()))
 | 
			
		||||
      return 1;
 | 
			
		||||
 | 
			
		||||
    if (!SerializeOnly)
 | 
			
		||||
      if (!ReplacementHandler.applyReplacements())
 | 
			
		||||
        return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Let the user know which temporary directory the replacements got written
 | 
			
		||||
  // to.
 | 
			
		||||
  if (SerializeOnly && !TempDestinationDir.empty())
 | 
			
		||||
    llvm::errs() << "Replacements serialized to: " << TempDestinationDir << "\n";
 | 
			
		||||
 | 
			
		||||
  if (FinalSyntaxCheck) {
 | 
			
		||||
    ClangTool SyntaxTool(*Compilations, SourcePaths);
 | 
			
		||||
    if (SyntaxTool.run(newFrontendActionFactory<SyntaxOnlyAction>()) != 0)
 | 
			
		||||
      return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Report execution times.
 | 
			
		||||
  if (GlobalOptions.EnableTiming && !PerfData.empty()) {
 | 
			
		||||
    std::string DirectoryName = TimingDirectoryName;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,14 +36,14 @@ SOURCES += $(addprefix ../ReplaceAutoPtr/,$(notdir $(wildcard $(PROJ_SRC_DIR)/..
 | 
			
		|||
BUILT_SOURCES += $(ObjDir)/../ReplaceAutoPtr/.objdir
 | 
			
		||||
 | 
			
		||||
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc mcparser option
 | 
			
		||||
USEDLIBS = modernizeCore.a clangFormat.a clangApplyReplacements.a clangTooling.a clangFrontend.a \
 | 
			
		||||
USEDLIBS = modernizeCore.a clangFormat.a clangTooling.a clangFrontend.a \
 | 
			
		||||
	   clangSerialization.a clangDriver.a clangRewriteFrontend.a \
 | 
			
		||||
	   clangRewriteCore.a clangParse.a clangSema.a clangAnalysis.a \
 | 
			
		||||
	   clangAST.a clangASTMatchers.a clangEdit.a clangLex.a clangBasic.a
 | 
			
		||||
 | 
			
		||||
include $(CLANG_LEVEL)/Makefile
 | 
			
		||||
 | 
			
		||||
CPP.Flags += -I$(PROJ_SRC_DIR)/.. -I$(PROJ_SRC_DIR)/../../clang-apply-replacements/include
 | 
			
		||||
CPP.Flags += -I$(PROJ_SRC_DIR)/..
 | 
			
		||||
 | 
			
		||||
# BUILT_SOURCES gets used as a prereq for many top-level targets. However, at
 | 
			
		||||
# the point those targets are defined, $(ObjDir) hasn't been defined and so the
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
---
 | 
			
		||||
# BasedOnStyle:  Google
 | 
			
		||||
AccessModifierOffset: -1
 | 
			
		||||
ConstructorInitializerIndentWidth: 4
 | 
			
		||||
AlignEscapedNewlinesLeft: true
 | 
			
		||||
AlignTrailingComments: true
 | 
			
		||||
AllowAllParametersOfDeclarationOnNextLine: true
 | 
			
		||||
AllowShortIfStatementsOnASingleLine: true
 | 
			
		||||
AllowShortLoopsOnASingleLine: true
 | 
			
		||||
AlwaysBreakTemplateDeclarations: true
 | 
			
		||||
AlwaysBreakBeforeMultilineStrings: true
 | 
			
		||||
BreakBeforeBinaryOperators: false
 | 
			
		||||
BreakConstructorInitializersBeforeComma: false
 | 
			
		||||
BinPackParameters: true
 | 
			
		||||
ColumnLimit:     80
 | 
			
		||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
 | 
			
		||||
DerivePointerBinding: true
 | 
			
		||||
ExperimentalAutoDetectBinPacking: false
 | 
			
		||||
IndentCaseLabels: true
 | 
			
		||||
MaxEmptyLinesToKeep: 1
 | 
			
		||||
NamespaceIndentation: None
 | 
			
		||||
ObjCSpaceBeforeProtocolList: false
 | 
			
		||||
PenaltyBreakComment: 60
 | 
			
		||||
PenaltyBreakString: 1000
 | 
			
		||||
PenaltyBreakFirstLessLess: 120
 | 
			
		||||
PenaltyExcessCharacter: 1000000
 | 
			
		||||
PenaltyReturnTypeOnItsOwnLine: 200
 | 
			
		||||
PointerBindsToType: true
 | 
			
		||||
SpacesBeforeTrailingComments: 2
 | 
			
		||||
Cpp11BracedListStyle: true
 | 
			
		||||
Standard:        Auto
 | 
			
		||||
IndentWidth:     2
 | 
			
		||||
TabWidth:        8
 | 
			
		||||
UseTab:          Never
 | 
			
		||||
BreakBeforeBraces: Attach
 | 
			
		||||
IndentFunctionDeclarationAfterType: true
 | 
			
		||||
SpacesInParentheses: false
 | 
			
		||||
SpaceInEmptyParentheses: false
 | 
			
		||||
SpacesInCStyleCastParentheses: false
 | 
			
		||||
SpaceAfterControlStatementKeyword: true
 | 
			
		||||
SpaceBeforeAssignmentOperators: true
 | 
			
		||||
...
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
 | 
			
		||||
// RUN: clang-modernize -format-style=LLVM -use-auto %t.cpp -- -std=c++11
 | 
			
		||||
// RUN: FileCheck --strict-whitespace -input-file=%t.cpp %s
 | 
			
		||||
 | 
			
		||||
class C {};
 | 
			
		||||
 | 
			
		||||
void f() { //
 | 
			
		||||
  C *a = new C();
 | 
			
		||||
  // CHECK: {{^\ \ auto\ a\ \=\ new\ C\(\);}}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,37 @@
 | 
			
		|||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
 | 
			
		||||
// RUN: not clang-modernize -format-style=non_existent_file.yaml -use-auto %t.cpp -- -std=c++11
 | 
			
		||||
// RUN: touch %T/non_format_config.yaml
 | 
			
		||||
// RUN: not clang-modernize -format-style=%T/non_format_config.yaml -use-auto %t.cpp -- -std=c++11
 | 
			
		||||
// RUN: clang-modernize -format-style=LLVM -use-auto %t.cpp -- -std=c++11
 | 
			
		||||
// RUN: clang-modernize -format -use-auto %t.cpp
 | 
			
		||||
// RUN: FileCheck --strict-whitespace -input-file=%t.cpp %s
 | 
			
		||||
 | 
			
		||||
class MyType012345678901234567890123456789 {};
 | 
			
		||||
// Ensure that -style is forwarded to clang-apply-replacements by using a style
 | 
			
		||||
// other than LLVM and ensuring the result is styled as requested.
 | 
			
		||||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
 | 
			
		||||
// RUN: clang-modernize -format -style=Google -use-nullptr %t.cpp
 | 
			
		||||
// RUN: FileCheck --check-prefix=Google --strict-whitespace -input-file=%t.cpp %s
 | 
			
		||||
 | 
			
		||||
// Ensure -style-config is forwarded to clang-apply-replacements. The .clang-format
 | 
			
		||||
// in %S/Inputs is a dump of the Google style so the same test can be used.
 | 
			
		||||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
 | 
			
		||||
// RUN: clang-modernize -format -style=file -style-config=%S/Inputs -use-nullptr %t.cpp
 | 
			
		||||
// RUN: FileCheck --check-prefix=Google --strict-whitespace -input-file=%t.cpp %s
 | 
			
		||||
 | 
			
		||||
class MyType012345678901234567890123456789 {
 | 
			
		||||
public:
 | 
			
		||||
  MyType012345678901234567890123456789()
 | 
			
		||||
      : iiiiiiiiiiii(0), jjjjjjjjjjjj(0), kkkkkkkkkkkk(0), mmmmmmmmmmmm(0),
 | 
			
		||||
        nnnnnnnnnnnn(0) {}
 | 
			
		||||
  // Google: iiiiiiiiiiii(nullptr),
 | 
			
		||||
  // Google-NEXT: jjjjjjjjjjjj(nullptr),
 | 
			
		||||
  // Google-NEXT: kkkkkkkkkkkk(nullptr),
 | 
			
		||||
  // Google-NEXT: mmmmmmmmmmmm(nullptr),
 | 
			
		||||
  // Google-NEXT: nnnnnnnnnnnn(nullptr) {}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  int *iiiiiiiiiiii;
 | 
			
		||||
  int *jjjjjjjjjjjj;
 | 
			
		||||
  int *kkkkkkkkkkkk;
 | 
			
		||||
  int *mmmmmmmmmmmm;
 | 
			
		||||
  int *nnnnnnnnnnnn;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int f() {
 | 
			
		||||
  MyType012345678901234567890123456789 *a =
 | 
			
		||||
| 
						 | 
				
			
			@ -13,4 +39,6 @@ int f() {
 | 
			
		|||
  // CHECK: {{^\ \ auto\ a\ \=\ new\ MyType012345678901234567890123456789\(\);}}
 | 
			
		||||
 | 
			
		||||
  delete a;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@
 | 
			
		|||
// RUN: rm -rf %T/SerializeTest
 | 
			
		||||
// RUN: mkdir -p %T/SerializeTest
 | 
			
		||||
// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %T/SerializeTest
 | 
			
		||||
// RUN: clang-modernize -loop-convert -serialize-replacements -include=%T/SerializeTest %T/SerializeTest/main.cpp %T/SerializeTest/common.cpp --
 | 
			
		||||
// RUN: clang-modernize -loop-convert -serialize-replacements -serialize-dir=%T/SerializeTest -include=%T/SerializeTest %T/SerializeTest/main.cpp %T/SerializeTest/common.cpp --
 | 
			
		||||
// Check that only 1 file is generated per translation unit
 | 
			
		||||
// RUN: ls -1 %T/SerializeTest | FileCheck %s --check-prefix=MAIN_CPP
 | 
			
		||||
// RUN: ls -1 %T/SerializeTest | FileCheck %s --check-prefix=COMMON_CPP
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,8 +15,6 @@ include_directories(
 | 
			
		|||
  )
 | 
			
		||||
 | 
			
		||||
add_extra_unittest(ClangModernizeTests
 | 
			
		||||
  FileOverridesTest.cpp
 | 
			
		||||
  ReformattingTest.cpp
 | 
			
		||||
  IncludeExcludeTest.cpp
 | 
			
		||||
  PerfSupportTest.cpp
 | 
			
		||||
  TransformTest.cpp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,187 +0,0 @@
 | 
			
		|||
//===- clang-modernize/FileOverridesTest.cpp - File overrides unit tests --===//
 | 
			
		||||
//
 | 
			
		||||
//                     The LLVM Compiler Infrastructure
 | 
			
		||||
//
 | 
			
		||||
// This file is distributed under the University of Illinois Open Source
 | 
			
		||||
// License. See LICENSE.TXT for details.
 | 
			
		||||
//
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#include "Core/FileOverrides.h"
 | 
			
		||||
#include "Core/Refactoring.h"
 | 
			
		||||
#include "gtest/gtest.h"
 | 
			
		||||
#include "common/VirtualFileHelper.h"
 | 
			
		||||
#include "clang/Rewrite/Core/Rewriter.h"
 | 
			
		||||
 | 
			
		||||
using namespace clang;
 | 
			
		||||
using namespace clang::tooling;
 | 
			
		||||
 | 
			
		||||
static Replacement makeReplacement(unsigned Offset, unsigned Length,
 | 
			
		||||
                                   unsigned ReplacementLength,
 | 
			
		||||
                                   llvm::StringRef FilePath) {
 | 
			
		||||
  return Replacement(FilePath, Offset, Length,
 | 
			
		||||
                     std::string(ReplacementLength, '~'));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// generate a set of replacements containing one element
 | 
			
		||||
static ReplacementsVec makeReplacements(unsigned Offset, unsigned Length,
 | 
			
		||||
                                        unsigned ReplacementLength,
 | 
			
		||||
                                        llvm::StringRef FilePath = "~") {
 | 
			
		||||
  ReplacementsVec Replaces;
 | 
			
		||||
  Replaces.push_back(
 | 
			
		||||
      makeReplacement(Offset, Length, ReplacementLength, FilePath));
 | 
			
		||||
  return Replaces;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool equalRanges(Range A, Range B) {
 | 
			
		||||
  return A.getOffset() == B.getOffset() && A.getLength() == B.getLength();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ChangedRangesTest, adjustChangedRangesShrink) {
 | 
			
		||||
  ChangedRanges Changes;
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(0, 0, 4));
 | 
			
		||||
  EXPECT_NE(Changes.begin(), Changes.end());
 | 
			
		||||
  EXPECT_TRUE(equalRanges(Range(0, 4), *Changes.begin()));
 | 
			
		||||
  // create a replacement that cuts the end of the last insertion
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(2, 4, 0));
 | 
			
		||||
  Range ExpectedChanges[] = { Range(0, 2) };
 | 
			
		||||
  EXPECT_TRUE(
 | 
			
		||||
      std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ChangedRangesTest, adjustChangedRangesExtend) {
 | 
			
		||||
  ChangedRanges Changes;
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(1, 0, 4));
 | 
			
		||||
  // cut the old one by a bigger one
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(3, 4, 6));
 | 
			
		||||
  Range ExpectedChanges[] = { Range(1, 8) };
 | 
			
		||||
  EXPECT_TRUE(
 | 
			
		||||
      std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ChangedRangesTest, adjustChangedRangesNoOverlap) {
 | 
			
		||||
  ChangedRanges Changes;
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(0, 0, 4));
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(6, 0, 4));
 | 
			
		||||
  Range ExpectedChanges[] = { Range(0, 4), Range(6, 4) };
 | 
			
		||||
  EXPECT_TRUE(
 | 
			
		||||
      std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ChangedRangesTest, adjustChangedRangesNullRange) {
 | 
			
		||||
  ChangedRanges Changes;
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(0, 4, 0));
 | 
			
		||||
  Range ExpectedChanges[] = { Range(0, 0) };
 | 
			
		||||
  EXPECT_TRUE(
 | 
			
		||||
      std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ChangedRangesTest, adjustChangedRangesExtendExisting) {
 | 
			
		||||
  ChangedRanges Changes;
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(0, 0, 3));
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(2, 5, 8));
 | 
			
		||||
  Range ExpectedChanges[] = { Range(0, 10) };
 | 
			
		||||
  EXPECT_TRUE(
 | 
			
		||||
      std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ChangedRangesTest, adjustChangedRangesSplit) {
 | 
			
		||||
  ChangedRanges Changes;
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(0, 0, 3));
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(1, 1, 0));
 | 
			
		||||
  Range ExpectedChanges[] = { Range(0, 2) };
 | 
			
		||||
  EXPECT_TRUE(
 | 
			
		||||
      std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ChangedRangesTest, adjustChangedRangesRangeContained) {
 | 
			
		||||
  ChangedRanges Changes;
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(3, 0, 2));
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(1, 4, 5));
 | 
			
		||||
  Range ExpectedChanges[] = { Range(1, 5) };
 | 
			
		||||
  EXPECT_TRUE(
 | 
			
		||||
      std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ChangedRangesTest, adjustChangedRangesRangeResized) {
 | 
			
		||||
  ChangedRanges Changes;
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(2, 0, 5));
 | 
			
		||||
  // first make the range bigger
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(4, 1, 3));
 | 
			
		||||
  Range ExpectedChanges[] = { Range(2, 7) };
 | 
			
		||||
  EXPECT_TRUE(
 | 
			
		||||
      std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
 | 
			
		||||
  // then smaller
 | 
			
		||||
  Changes.adjustChangedRanges(makeReplacements(3, 3, 1));
 | 
			
		||||
  ExpectedChanges[0] = Range(2, 5);
 | 
			
		||||
  EXPECT_TRUE(
 | 
			
		||||
      std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(FileOverridesTest, applyOverrides) {
 | 
			
		||||
 | 
			
		||||
  // Set up initial state
 | 
			
		||||
  VirtualFileHelper VFHelper;
 | 
			
		||||
 | 
			
		||||
  SmallString<128> fileAPath("fileA.cpp");
 | 
			
		||||
  ASSERT_FALSE(llvm::sys::fs::make_absolute(fileAPath));
 | 
			
		||||
  SmallString<128> fileBPath("fileB.cpp");
 | 
			
		||||
  ASSERT_FALSE(llvm::sys::fs::make_absolute(fileBPath));
 | 
			
		||||
  VFHelper.mapFile(fileAPath, "Content A");
 | 
			
		||||
  VFHelper.mapFile(fileBPath, "Content B");
 | 
			
		||||
  SourceManager &SM = VFHelper.getNewSourceManager();
 | 
			
		||||
 | 
			
		||||
  // Fill a Rewriter with changes
 | 
			
		||||
  Rewriter Rewrites(SM, LangOptions());
 | 
			
		||||
  ReplacementsVec R(1, Replacement(fileAPath, 0, 7, "Stuff"));
 | 
			
		||||
  ASSERT_TRUE(applyAllReplacements(R, Rewrites));
 | 
			
		||||
 | 
			
		||||
  FileOverrides Overrides;
 | 
			
		||||
  Overrides.updateState(Rewrites);
 | 
			
		||||
  
 | 
			
		||||
  const FileOverrides::FileStateMap &State = Overrides.getState();
 | 
			
		||||
  
 | 
			
		||||
  // Ensure state updated
 | 
			
		||||
  ASSERT_TRUE(State.end() == State.find(fileBPath));
 | 
			
		||||
  ASSERT_TRUE(State.begin() == State.find(fileAPath));
 | 
			
		||||
  ASSERT_EQ("Stuff A", State.begin()->getValue());
 | 
			
		||||
 | 
			
		||||
  Overrides.applyOverrides(SM);
 | 
			
		||||
 | 
			
		||||
  const FileEntry *EntryA = SM.getFileManager().getFile(fileAPath);
 | 
			
		||||
  FileID IdA = SM.translateFile(EntryA);
 | 
			
		||||
  ASSERT_FALSE(IdA.isInvalid());
 | 
			
		||||
 | 
			
		||||
  // Ensure the contents of the buffer matches what we'd expect.
 | 
			
		||||
  const llvm::MemoryBuffer *BufferA = SM.getBuffer(IdA);
 | 
			
		||||
  ASSERT_FALSE(0 == BufferA);
 | 
			
		||||
  ASSERT_EQ("Stuff A", BufferA->getBuffer());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(FileOverridesTest, adjustChangedRanges) {
 | 
			
		||||
  SmallString<128> fileAPath("fileA.cpp");
 | 
			
		||||
  ASSERT_FALSE(llvm::sys::fs::make_absolute(fileAPath));
 | 
			
		||||
  SmallString<128> fileBPath("fileB.cpp");
 | 
			
		||||
  ASSERT_FALSE(llvm::sys::fs::make_absolute(fileBPath));
 | 
			
		||||
 | 
			
		||||
  replace::FileToReplacementsMap GroupedReplacements;
 | 
			
		||||
  GroupedReplacements[fileAPath] = makeReplacements(0, 5, 4, fileAPath);
 | 
			
		||||
  GroupedReplacements[fileBPath] = makeReplacements(10, 0, 6, fileBPath);
 | 
			
		||||
 | 
			
		||||
  FileOverrides Overrides;
 | 
			
		||||
 | 
			
		||||
  const FileOverrides::ChangeMap &Map = Overrides.getChangedRanges();
 | 
			
		||||
 | 
			
		||||
  ASSERT_TRUE(Map.empty());
 | 
			
		||||
 | 
			
		||||
  Overrides.adjustChangedRanges(GroupedReplacements);
 | 
			
		||||
 | 
			
		||||
  ASSERT_TRUE(Map.end() != Map.find(fileAPath));
 | 
			
		||||
  ASSERT_TRUE(Map.end() != Map.find(fileBPath));
 | 
			
		||||
  const Range &RA = *Map.find(fileAPath)->second.begin();
 | 
			
		||||
  EXPECT_EQ(0u, RA.getOffset());
 | 
			
		||||
  EXPECT_EQ(4u, RA.getLength());
 | 
			
		||||
  const Range &RB = *Map.find(fileBPath)->second.begin();
 | 
			
		||||
  EXPECT_EQ(10u, RB.getOffset());
 | 
			
		||||
  EXPECT_EQ(6u, RB.getLength());
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -18,8 +18,7 @@ public:
 | 
			
		|||
  TransformA(const TransformOptions &Options)
 | 
			
		||||
      : Transform("TransformA", Options) {}
 | 
			
		||||
 | 
			
		||||
  virtual int apply(const FileOverrides &,
 | 
			
		||||
                    const tooling::CompilationDatabase &,
 | 
			
		||||
  virtual int apply(const tooling::CompilationDatabase &,
 | 
			
		||||
                    const std::vector<std::string> &) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -34,8 +33,7 @@ public:
 | 
			
		|||
  TransformB(const TransformOptions &Options)
 | 
			
		||||
      : Transform("TransformB", Options) {}
 | 
			
		||||
 | 
			
		||||
  virtual int apply(const FileOverrides &,
 | 
			
		||||
                    const tooling::CompilationDatabase &,
 | 
			
		||||
  virtual int apply(const tooling::CompilationDatabase &,
 | 
			
		||||
                    const std::vector<std::string> &) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,55 +0,0 @@
 | 
			
		|||
//===- clang-modernize/ReformattingTest.cpp - Reformatting unit tests -----===//
 | 
			
		||||
//
 | 
			
		||||
//                     The LLVM Compiler Infrastructure
 | 
			
		||||
//
 | 
			
		||||
// This file is distributed under the University of Illinois Open Source
 | 
			
		||||
// License. See LICENSE.TXT for details.
 | 
			
		||||
//
 | 
			
		||||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#include "Core/Reformatting.h"
 | 
			
		||||
#include "Core/FileOverrides.h"
 | 
			
		||||
#include "Core/Refactoring.h"
 | 
			
		||||
#include "gtest/gtest.h"
 | 
			
		||||
#include "common/VirtualFileHelper.h"
 | 
			
		||||
 | 
			
		||||
using namespace clang;
 | 
			
		||||
using namespace clang::tooling;
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
// convenience function to create a ChangedRanges containing one Range
 | 
			
		||||
ChangedRanges makeChangedRanges(unsigned Offset, unsigned Length) {
 | 
			
		||||
  ChangedRanges Changes;
 | 
			
		||||
  ReplacementsVec Replaces;
 | 
			
		||||
 | 
			
		||||
  Replaces.push_back(Replacement("", Offset, 0, std::string(Length, '~')));
 | 
			
		||||
  Changes.adjustChangedRanges(Replaces);
 | 
			
		||||
  return Changes;
 | 
			
		||||
}
 | 
			
		||||
} // end anonymous namespace
 | 
			
		||||
 | 
			
		||||
TEST(Reformatter, SingleReformat) {
 | 
			
		||||
  VirtualFileHelper VFHelper;
 | 
			
		||||
  llvm::StringRef FileName = "<test>";
 | 
			
		||||
  VFHelper.mapFile(FileName, "int  a;\n"
 | 
			
		||||
                             "int  b;\n");
 | 
			
		||||
 | 
			
		||||
  Reformatter ChangesReformatter(format::getLLVMStyle());
 | 
			
		||||
  ChangedRanges Changes = makeChangedRanges(0, 6);
 | 
			
		||||
  tooling::ReplacementsVec Replaces;
 | 
			
		||||
  ChangesReformatter.reformatSingleFile(
 | 
			
		||||
      FileName, Changes, VFHelper.getNewSourceManager(), Replaces);
 | 
			
		||||
 | 
			
		||||
  // We expect the code above to reformatted like so:
 | 
			
		||||
  //
 | 
			
		||||
  // int a;
 | 
			
		||||
  // int  b;
 | 
			
		||||
  //
 | 
			
		||||
  // This test is slightly fragile since there's more than one Replacement that
 | 
			
		||||
  // results in the above change. However, testing the result of applying the
 | 
			
		||||
  // replacement is more trouble than it's worth in this context.
 | 
			
		||||
  ASSERT_EQ(1u, Replaces.size());
 | 
			
		||||
  EXPECT_EQ(3u, Replaces[0].getOffset());
 | 
			
		||||
  EXPECT_EQ(2u, Replaces[0].getLength());
 | 
			
		||||
  EXPECT_EQ(" ", Replaces[0].getReplacementText());
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +8,6 @@
 | 
			
		|||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#include "gtest/gtest.h"
 | 
			
		||||
#include "Core/FileOverrides.h"
 | 
			
		||||
#include "Core/Transform.h"
 | 
			
		||||
#include "clang/AST/ASTConsumer.h"
 | 
			
		||||
#include "clang/AST/DeclGroup.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -26,8 +25,7 @@ public:
 | 
			
		|||
  DummyTransform(llvm::StringRef Name, const TransformOptions &Options)
 | 
			
		||||
      : Transform(Name, Options) {}
 | 
			
		||||
 | 
			
		||||
  virtual int apply(const FileOverrides &,
 | 
			
		||||
                    const tooling::CompilationDatabase &,
 | 
			
		||||
  virtual int apply(const tooling::CompilationDatabase &,
 | 
			
		||||
                    const std::vector<std::string> &) { return 0; }
 | 
			
		||||
 | 
			
		||||
  void setAcceptedChanges(unsigned Changes) {
 | 
			
		||||
| 
						 | 
				
			
			@ -40,10 +38,6 @@ public:
 | 
			
		|||
    Transform::setDeferredChanges(Changes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void setOverrides(FileOverrides &Overrides) {
 | 
			
		||||
    Transform::setOverrides(Overrides);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST(Transform, Interface) {
 | 
			
		||||
| 
						 | 
				
			
			@ -159,11 +153,6 @@ TEST(Transform, Timings) {
 | 
			
		|||
  // handleEndSource() calls to it.
 | 
			
		||||
  CallbackForwarder Callbacks(T);
 | 
			
		||||
 | 
			
		||||
  // Transform's handle* functions require FileOverrides to be set, even if
 | 
			
		||||
  // there aren't any.
 | 
			
		||||
  FileOverrides Overrides;
 | 
			
		||||
  T.setOverrides(Overrides);
 | 
			
		||||
 | 
			
		||||
  Tool.run(clang::tooling::newFrontendActionFactory(&Factory, &Callbacks));
 | 
			
		||||
 | 
			
		||||
  EXPECT_TRUE(Factory.Called);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@
 | 
			
		|||
//===----------------------------------------------------------------------===//
 | 
			
		||||
 | 
			
		||||
#include "gtest/gtest.h"
 | 
			
		||||
#include "Core/FileOverrides.h"
 | 
			
		||||
#include "Core/ReplacementHandling.h"
 | 
			
		||||
#include "llvm/Support/FileSystem.h"
 | 
			
		||||
#include "llvm/Support/Path.h"
 | 
			
		||||
#include "llvm/Support/Regex.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -28,10 +28,13 @@ TEST(UniqueHeaderName, testUniqueHeaderName) {
 | 
			
		|||
  append(SourceFile, "project/lib/feature.cpp");
 | 
			
		||||
  native(SourceFile.str().str(), SourceFile);
 | 
			
		||||
 | 
			
		||||
  llvm::SmallString<128> DestDir(TmpDir);
 | 
			
		||||
  append(DestDir, "replacements");
 | 
			
		||||
 | 
			
		||||
  llvm::SmallString<128> FullActualPath;
 | 
			
		||||
  llvm::SmallString<128> Error;
 | 
			
		||||
  bool Result =
 | 
			
		||||
      generateReplacementsFileName(SourceFile, FullActualPath, Error);
 | 
			
		||||
  bool Result = ReplacementHandling::generateReplacementsFileName(
 | 
			
		||||
      DestDir, SourceFile, FullActualPath, Error);
 | 
			
		||||
 | 
			
		||||
  ASSERT_TRUE(Result);
 | 
			
		||||
  EXPECT_TRUE(Error.empty());
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +48,7 @@ TEST(UniqueHeaderName, testUniqueHeaderName) {
 | 
			
		|||
  llvm::SmallString<128> ActualName =
 | 
			
		||||
      llvm::sys::path::filename(FullActualPath);
 | 
			
		||||
 | 
			
		||||
  EXPECT_STREQ(ExpectedPath.c_str(), ActualPath.c_str());
 | 
			
		||||
  EXPECT_STREQ(DestDir.c_str(), ActualPath.c_str());
 | 
			
		||||
 | 
			
		||||
  llvm::StringRef ExpectedName =
 | 
			
		||||
      "^feature.cpp_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_["
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue