forked from OSchip/llvm-project
Revert "cpp11-migrate: Fixing autoconf build after adding libclangReplace dependency"
Revert "cpp11-migrate: Refactor for driver model of operation" This reverts commit r189691. This reverts commit r189689. This was breaking the phase 1 OS X build for ~2 hours. https://smooshbase.apple.com/buildbot-internal/builders/phase1%20-%20sanity/builds/9559 I reverted the latter commit since I think the latter depended on the former. llvm-svn: 189700
This commit is contained in:
parent
79917a913e
commit
92d9cb4dd1
|
@ -29,13 +29,13 @@ static cl::opt<bool> DetectMacros(
|
||||||
cl::desc("Detect and use macros that expand to the 'override' keyword."),
|
cl::desc("Detect and use macros that expand to the 'override' keyword."),
|
||||||
cl::cat(TransformsOptionsCategory));
|
cl::cat(TransformsOptionsCategory));
|
||||||
|
|
||||||
int AddOverrideTransform::apply(const FileOverrides &InputStates,
|
int AddOverrideTransform::apply(FileOverrides &InputStates,
|
||||||
const CompilationDatabase &Database,
|
const CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) {
|
const std::vector<std::string> &SourcePaths) {
|
||||||
ClangTool AddOverrideTool(Database, SourcePaths);
|
ClangTool AddOverrideTool(Database, SourcePaths);
|
||||||
unsigned AcceptedChanges = 0;
|
unsigned AcceptedChanges = 0;
|
||||||
MatchFinder Finder;
|
MatchFinder Finder;
|
||||||
AddOverrideFixer Fixer(AcceptedChanges, DetectMacros,
|
AddOverrideFixer Fixer(getReplacements(), AcceptedChanges, DetectMacros,
|
||||||
/*Owner=*/ *this);
|
/*Owner=*/ *this);
|
||||||
Finder.addMatcher(makeCandidateForOverrideAttrMatcher(), &Fixer);
|
Finder.addMatcher(makeCandidateForOverrideAttrMatcher(), &Fixer);
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
: Transform("AddOverride", Options) {}
|
: Transform("AddOverride", Options) {}
|
||||||
|
|
||||||
/// \see Transform::run().
|
/// \see Transform::run().
|
||||||
virtual int apply(const FileOverrides &InputStates,
|
virtual int apply(FileOverrides &InputStates,
|
||||||
const clang::tooling::CompilationDatabase &Database,
|
const clang::tooling::CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,6 @@ void AddOverrideFixer::run(const MatchFinder::MatchResult &Result) {
|
||||||
if (!MacroName.empty())
|
if (!MacroName.empty())
|
||||||
ReplacementText = (" " + MacroName).str();
|
ReplacementText = (" " + MacroName).str();
|
||||||
}
|
}
|
||||||
Owner.addReplacementForCurrentTU(
|
Replace.insert(tooling::Replacement(SM, StartLoc, 0, ReplacementText));
|
||||||
tooling::Replacement(SM, StartLoc, 0, ReplacementText));
|
|
||||||
++AcceptedChanges;
|
++AcceptedChanges;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,11 @@ class Transform;
|
||||||
///
|
///
|
||||||
class AddOverrideFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
class AddOverrideFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||||
public:
|
public:
|
||||||
AddOverrideFixer(unsigned &AcceptedChanges, bool DetectMacros,
|
AddOverrideFixer(clang::tooling::Replacements &Replace,
|
||||||
Transform &Owner)
|
unsigned &AcceptedChanges, bool DetectMacros,
|
||||||
: AcceptedChanges(AcceptedChanges), DetectMacros(DetectMacros),
|
const Transform &Owner)
|
||||||
Owner(Owner) {}
|
: Replace(Replace), AcceptedChanges(AcceptedChanges),
|
||||||
|
DetectMacros(DetectMacros), Owner(Owner) {}
|
||||||
|
|
||||||
/// \brief Entry point to the callback called when matches are made.
|
/// \brief Entry point to the callback called when matches are made.
|
||||||
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result);
|
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result);
|
||||||
|
@ -37,9 +38,10 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
clang::Preprocessor *PP;
|
clang::Preprocessor *PP;
|
||||||
|
clang::tooling::Replacements &Replace;
|
||||||
unsigned &AcceptedChanges;
|
unsigned &AcceptedChanges;
|
||||||
bool DetectMacros;
|
bool DetectMacros;
|
||||||
Transform &Owner;
|
const Transform &Owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPP11_MIGRATE_ADD_OVERRIDE_ACTIONS_H
|
#endif // CPP11_MIGRATE_ADD_OVERRIDE_ACTIONS_H
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
get_filename_component(ClangReplaceLocation
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../clang-replace/include" ABSOLUTE)
|
|
||||||
|
|
||||||
include_directories(
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
${ClangReplaceLocation}
|
|
||||||
)
|
|
||||||
|
|
||||||
add_subdirectory(tool)
|
add_subdirectory(tool)
|
||||||
add_subdirectory(Core)
|
add_subdirectory(Core)
|
||||||
|
|
|
@ -29,14 +29,157 @@
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace clang::tooling;
|
using namespace clang::tooling;
|
||||||
|
|
||||||
bool generateReplacementsFileName(const llvm::StringRef MainSourceFile,
|
void HeaderOverride::recordReplacements(
|
||||||
llvm::SmallVectorImpl<char> &Result,
|
const clang::tooling::Replacements &Replaces) {
|
||||||
llvm::SmallVectorImpl<char> &Error) {
|
Replacements.Replacements.resize(Replaces.size());
|
||||||
|
std::copy(Replaces.begin(), Replaces.end(),
|
||||||
|
Replacements.Replacements.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceOverrides::SourceOverrides(llvm::StringRef MainFileName,
|
||||||
|
bool TrackChanges)
|
||||||
|
: MainFileName(MainFileName), TrackChanges(TrackChanges) {}
|
||||||
|
|
||||||
|
void
|
||||||
|
SourceOverrides::applyReplacements(clang::tooling::Replacements &Replaces) {
|
||||||
|
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
|
||||||
|
new DiagnosticOptions());
|
||||||
|
DiagnosticsEngine Diagnostics(
|
||||||
|
llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
|
||||||
|
DiagOpts.getPtr());
|
||||||
|
FileManager Files((FileSystemOptions()));
|
||||||
|
SourceManager SM(Diagnostics, Files);
|
||||||
|
applyReplacements(Replaces, SM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceOverrides::applyReplacements(clang::tooling::Replacements &Replaces,
|
||||||
|
clang::SourceManager &SM) {
|
||||||
|
applyOverrides(SM);
|
||||||
|
|
||||||
|
Rewriter Rewrites(SM, LangOptions());
|
||||||
|
|
||||||
|
// FIXME: applyAllReplacements will indicate if it couldn't apply all
|
||||||
|
// replacements. Handle that case.
|
||||||
|
bool Success = tooling::applyAllReplacements(Replaces, Rewrites);
|
||||||
|
|
||||||
|
if (!Success)
|
||||||
|
llvm::errs() << "error: failed to apply some replacements.";
|
||||||
|
|
||||||
|
std::string ResultBuf;
|
||||||
|
|
||||||
|
for (Rewriter::buffer_iterator I = Rewrites.buffer_begin(),
|
||||||
|
E = Rewrites.buffer_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
const FileEntry *Entry =
|
||||||
|
Rewrites.getSourceMgr().getFileEntryForID(I->first);
|
||||||
|
assert(Entry != NULL && "unexpected null FileEntry");
|
||||||
|
assert(Entry->getName() != NULL &&
|
||||||
|
"unexpected null return from FileEntry::getName()");
|
||||||
|
llvm::StringRef FileName = Entry->getName();
|
||||||
|
|
||||||
|
// Get a copy of the rewritten buffer from the Rewriter.
|
||||||
|
ResultBuf.clear();
|
||||||
|
llvm::raw_string_ostream StringStream(ResultBuf);
|
||||||
|
I->second.write(StringStream);
|
||||||
|
StringStream.flush();
|
||||||
|
|
||||||
|
if (MainFileName == FileName) {
|
||||||
|
MainFileOverride.swap(ResultBuf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header overrides are treated differently. Eventually, raw replacements
|
||||||
|
// will be stored as well for later output to disk. Applying replacements
|
||||||
|
// in memory will always be necessary as the source goes down the transform
|
||||||
|
// pipeline.
|
||||||
|
HeaderOverride &HeaderOv = Headers[FileName];
|
||||||
|
// "Create" HeaderOverride if not already existing
|
||||||
|
if (HeaderOv.getHeaderPath().empty())
|
||||||
|
HeaderOv = HeaderOverride(FileName, MainFileName);
|
||||||
|
|
||||||
|
HeaderOv.swapContentOverride(ResultBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separate replacements to header files
|
||||||
|
Replacements MainFileReplaces;
|
||||||
|
ReplacementsMap HeadersReplaces;
|
||||||
|
for (Replacements::const_iterator I = Replaces.begin(), E = Replaces.end();
|
||||||
|
I != E; ++I) {
|
||||||
|
llvm::StringRef ReplacementFileName = I->getFilePath();
|
||||||
|
|
||||||
|
if (ReplacementFileName == MainFileName) {
|
||||||
|
MainFileReplaces.insert(*I);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeadersReplaces[ReplacementFileName].insert(*I);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record all replacements to headers.
|
||||||
|
for (ReplacementsMap::const_iterator I = HeadersReplaces.begin(),
|
||||||
|
E = HeadersReplaces.end();
|
||||||
|
I != E; ++I) {
|
||||||
|
HeaderOverride &HeaderOv = Headers[I->getKey()];
|
||||||
|
HeaderOv.recordReplacements(I->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TrackChanges)
|
||||||
|
adjustChangedRanges(MainFileReplaces, HeadersReplaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SourceOverrides::adjustChangedRanges(const Replacements &MainFileReplaces,
|
||||||
|
const ReplacementsMap &HeadersReplaces) {
|
||||||
|
// Adjust the changed ranges for each individual file
|
||||||
|
MainFileChanges.adjustChangedRanges(MainFileReplaces);
|
||||||
|
for (ReplacementsMap::const_iterator I = HeadersReplaces.begin(),
|
||||||
|
E = HeadersReplaces.end();
|
||||||
|
I != E; ++I) {
|
||||||
|
Headers[I->getKey()].adjustChangedRanges(I->getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceOverrides::applyOverrides(SourceManager &SM) const {
|
||||||
|
FileManager &FM = SM.getFileManager();
|
||||||
|
|
||||||
|
if (isSourceOverriden())
|
||||||
|
SM.overrideFileContents(FM.getFile(MainFileName),
|
||||||
|
llvm::MemoryBuffer::getMemBuffer(MainFileOverride));
|
||||||
|
|
||||||
|
for (HeaderOverrides::const_iterator I = Headers.begin(), E = Headers.end();
|
||||||
|
I != E; ++I) {
|
||||||
|
assert(!I->second.getContentOverride().empty() &&
|
||||||
|
"Header override should not be empty!");
|
||||||
|
SM.overrideFileContents(
|
||||||
|
FM.getFile(I->second.getHeaderPath()),
|
||||||
|
llvm::MemoryBuffer::getMemBuffer(I->second.getContentOverride()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool generateReplacementsFileName(llvm::StringRef SourceFile,
|
||||||
|
llvm::StringRef HeaderFile,
|
||||||
|
llvm::SmallVectorImpl<char> &Result,
|
||||||
|
llvm::SmallVectorImpl<char> &Error) {
|
||||||
using namespace llvm::sys;
|
using namespace llvm::sys;
|
||||||
|
std::string UniqueHeaderNameModel;
|
||||||
|
|
||||||
|
// Get the filename portion of the path.
|
||||||
|
llvm::StringRef SourceFileRef(path::filename(SourceFile));
|
||||||
|
llvm::StringRef HeaderFileRef(path::filename(HeaderFile));
|
||||||
|
|
||||||
|
// Get the actual path for the header file.
|
||||||
|
llvm::SmallString<128> HeaderPath(HeaderFile);
|
||||||
|
path::remove_filename(HeaderPath);
|
||||||
|
|
||||||
|
// Build the model of the filename.
|
||||||
|
llvm::raw_string_ostream UniqueHeaderNameStream(UniqueHeaderNameModel);
|
||||||
|
UniqueHeaderNameStream << SourceFileRef << "_" << HeaderFileRef
|
||||||
|
<< "_%%_%%_%%_%%_%%_%%" << ".yaml";
|
||||||
|
path::append(HeaderPath, UniqueHeaderNameStream.str());
|
||||||
|
|
||||||
Error.clear();
|
Error.clear();
|
||||||
if (llvm::error_code EC = fs::createUniqueFile(
|
if (llvm::error_code EC =
|
||||||
MainSourceFile + "_%%_%%_%%_%%_%%_%%.yaml", Result)) {
|
fs::createUniqueFile(HeaderPath.c_str(), Result)) {
|
||||||
Error.append(EC.message().begin(), EC.message().end());
|
Error.append(EC.message().begin(), EC.message().end());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -44,6 +187,20 @@ bool generateReplacementsFileName(const llvm::StringRef MainSourceFile,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileOverrides::~FileOverrides() {
|
||||||
|
for (SourceOverridesMap::iterator I = Overrides.begin(), E = Overrides.end();
|
||||||
|
I != E; ++I)
|
||||||
|
delete I->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceOverrides &FileOverrides::getOrCreate(llvm::StringRef Filename) {
|
||||||
|
SourceOverrides *&Override = Overrides[Filename];
|
||||||
|
|
||||||
|
if (Override == NULL)
|
||||||
|
Override = new SourceOverrides(Filename, TrackChanges);
|
||||||
|
return *Override;
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// \brief Comparator to be able to order tooling::Range based on their offset.
|
/// \brief Comparator to be able to order tooling::Range based on their offset.
|
||||||
|
@ -90,11 +247,10 @@ struct RangeReplacedAdjuster {
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
void
|
void ChangedRanges::adjustChangedRanges(const tooling::Replacements &Replaces) {
|
||||||
ChangedRanges::adjustChangedRanges(const tooling::ReplacementsVec &Replaces) {
|
|
||||||
// first adjust existing ranges in case they overlap with the replacements
|
// first adjust existing ranges in case they overlap with the replacements
|
||||||
for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end();
|
for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E;
|
||||||
I != E; ++I) {
|
++I) {
|
||||||
const tooling::Replacement &Replace = *I;
|
const tooling::Replacement &Replace = *I;
|
||||||
|
|
||||||
std::transform(Ranges.begin(), Ranges.end(), Ranges.begin(),
|
std::transform(Ranges.begin(), Ranges.end(), Ranges.begin(),
|
||||||
|
@ -109,8 +265,8 @@ ChangedRanges::adjustChangedRanges(const tooling::ReplacementsVec &Replaces) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// then generate the new ranges from the replacements
|
// then generate the new ranges from the replacements
|
||||||
for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end();
|
for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E;
|
||||||
I != E; ++I) {
|
++I) {
|
||||||
const tooling::Replacement &R = *I;
|
const tooling::Replacement &R = *I;
|
||||||
unsigned Offset = tooling::shiftedCodePosition(Replaces, R.getOffset());
|
unsigned Offset = tooling::shiftedCodePosition(Replaces, R.getOffset());
|
||||||
unsigned Length = R.getReplacementText().size();
|
unsigned Length = R.getReplacementText().size();
|
||||||
|
@ -147,52 +303,3 @@ void ChangedRanges::coalesceRanges() {
|
||||||
std::mem_fun_ref(&Range::contains)),
|
std::mem_fun_ref(&Range::contains)),
|
||||||
Ranges.end());
|
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
#ifndef CPP11_MIGRATE_FILE_OVERRIDES_H
|
#ifndef CPP11_MIGRATE_FILE_OVERRIDES_H
|
||||||
#define CPP11_MIGRATE_FILE_OVERRIDES_H
|
#define CPP11_MIGRATE_FILE_OVERRIDES_H
|
||||||
|
|
||||||
#include "Core/Refactoring.h"
|
#include "clang/Tooling/Refactoring.h"
|
||||||
#include "clang-replace/Tooling/ApplyReplacements.h"
|
|
||||||
#include "clang/Tooling/ReplacementsYaml.h"
|
#include "clang/Tooling/ReplacementsYaml.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
|
|
||||||
|
@ -45,13 +44,13 @@ public:
|
||||||
/// to remove replaced parts.
|
/// to remove replaced parts.
|
||||||
///
|
///
|
||||||
/// Note that all replacements should come from the same file.
|
/// Note that all replacements should come from the same file.
|
||||||
void adjustChangedRanges(const clang::tooling::ReplacementsVec &Replaces);
|
void adjustChangedRanges(const clang::tooling::Replacements &Replaces);
|
||||||
|
|
||||||
/// \brief Iterators.
|
/// \brief Iterators.
|
||||||
/// \{
|
/// @{
|
||||||
const_iterator begin() const { return Ranges.begin(); }
|
const_iterator begin() const { return Ranges.begin(); }
|
||||||
const_iterator end() const { return Ranges.end(); }
|
const_iterator end() const { return Ranges.end(); }
|
||||||
/// \}
|
/// @}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void coalesceRanges();
|
void coalesceRanges();
|
||||||
|
@ -59,71 +58,178 @@ private:
|
||||||
RangeVec Ranges;
|
RangeVec Ranges;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Maintains current state of transformed files and tracks source ranges
|
/// \brief Container for storing override information for a single headers.
|
||||||
/// where changes have been made.
|
class HeaderOverride {
|
||||||
class FileOverrides {
|
|
||||||
public:
|
public:
|
||||||
/// \brief Maps file names to file contents.
|
/// \brief Constructors.
|
||||||
typedef llvm::StringMap<std::string> FileStateMap;
|
/// @{
|
||||||
|
HeaderOverride() {}
|
||||||
|
HeaderOverride(llvm::StringRef HeaderPath,
|
||||||
|
llvm::StringRef MainSourceFile) : HeaderPath(HeaderPath) {
|
||||||
|
Replacements.MainSourceFile = MainSourceFile;
|
||||||
|
}
|
||||||
|
/// @}
|
||||||
|
|
||||||
/// \brief Maps file names to change tracking info for a file.
|
/// \brief Getter for HeaderPath.
|
||||||
typedef llvm::StringMap<ChangedRanges> ChangeMap;
|
llvm::StringRef getHeaderPath() const {
|
||||||
|
return HeaderPath;
|
||||||
|
|
||||||
/// \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
|
/// \brief Accessor for ContentOverride.
|
||||||
/// overrides stored in this object.
|
/// @{
|
||||||
///
|
llvm::StringRef getContentOverride() const { return ContentOverride; }
|
||||||
/// \param Rewrites Rewriter containing changes to files.
|
void setContentOverride(const llvm::StringRef S) { ContentOverride = S; }
|
||||||
void updateState(const clang::Rewriter &Rewrites);
|
/// @}
|
||||||
|
|
||||||
/// \brief Accessor for current file state.
|
/// \brief Getter for Changes.
|
||||||
const FileStateMap &getState() const { return FileStates; }
|
const ChangedRanges &getChanges() const { return Changes; }
|
||||||
|
|
||||||
/// \brief Write all file contents overrides to disk.
|
/// \brief Swaps the content of ContentOverride with \p S.
|
||||||
///
|
void swapContentOverride(std::string &S) { ContentOverride.swap(S); }
|
||||||
/// \param Diagnostics DiagnosticsEngine for error output.
|
|
||||||
///
|
/// \brief Getter for Replacements.
|
||||||
/// \returns \li true if all files with overridden file contents were written
|
const clang::tooling::TranslationUnitReplacements &getReplacements() const {
|
||||||
/// to disk successfully.
|
return Replacements;
|
||||||
/// \li false if any failure occurred.
|
}
|
||||||
bool writeToDisk(clang::DiagnosticsEngine &Diagnostics) const;
|
|
||||||
|
/// \brief Stores the replacements made by a transform to the header this
|
||||||
|
/// object represents.
|
||||||
|
void recordReplacements(const clang::tooling::Replacements &Replaces);
|
||||||
|
|
||||||
|
/// \brief Helper function to adjust the changed ranges.
|
||||||
|
void adjustChangedRanges(const clang::tooling::Replacements &Replaces) {
|
||||||
|
Changes.adjustChangedRanges(Replaces);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FileStateMap FileStates;
|
std::string ContentOverride;
|
||||||
ChangeMap ChangeTracking;
|
ChangedRanges Changes;
|
||||||
|
std::string HeaderPath;
|
||||||
|
clang::tooling::TranslationUnitReplacements Replacements;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Container mapping header file names to override information.
|
||||||
|
typedef llvm::StringMap<HeaderOverride> HeaderOverrides;
|
||||||
|
|
||||||
|
/// \brief Container storing the file content overrides for a source file and
|
||||||
|
/// any headers included by the source file either directly or indirectly to
|
||||||
|
/// which changes have been made.
|
||||||
|
class SourceOverrides {
|
||||||
|
public:
|
||||||
|
SourceOverrides(llvm::StringRef MainFileName, bool TrackChanges);
|
||||||
|
|
||||||
|
/// \brief Accessors.
|
||||||
|
/// @{
|
||||||
|
llvm::StringRef getMainFileName() const { return MainFileName; }
|
||||||
|
llvm::StringRef getMainFileContent() const { return MainFileOverride; }
|
||||||
|
const ChangedRanges &getChangedRanges() const { return MainFileChanges; }
|
||||||
|
|
||||||
|
/// \brief Is file change tracking enabled?
|
||||||
|
///
|
||||||
|
/// Tracking file changes can be useful to reformat the code for example.
|
||||||
|
bool isTrackingFileChanges() const { return TrackChanges; }
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \brief Indicates if the source file has been overridden.
|
||||||
|
///
|
||||||
|
/// It's possible for a source to remain unchanged while only headers are
|
||||||
|
/// changed.
|
||||||
|
bool isSourceOverriden() const { return !MainFileOverride.empty(); }
|
||||||
|
|
||||||
|
/// \brief Override the file contents by applying all the replacements.
|
||||||
|
///
|
||||||
|
/// \param Replaces The replacements to apply.
|
||||||
|
/// \param SM A user provided SourceManager to be used when applying rewrites.
|
||||||
|
void applyReplacements(clang::tooling::Replacements &Replaces,
|
||||||
|
clang::SourceManager &SM);
|
||||||
|
void applyReplacements(clang::tooling::Replacements &Replaces);
|
||||||
|
|
||||||
|
/// \brief Convenience function for applying this source's overrides to
|
||||||
|
/// the given SourceManager.
|
||||||
|
void applyOverrides(clang::SourceManager &SM) const;
|
||||||
|
|
||||||
|
/// \brief Iterators.
|
||||||
|
/// @{
|
||||||
|
HeaderOverrides::iterator headers_begin() { return Headers.begin(); }
|
||||||
|
HeaderOverrides::iterator headers_end() { return Headers.end(); }
|
||||||
|
HeaderOverrides::const_iterator headers_begin() const {
|
||||||
|
return Headers.begin();
|
||||||
|
}
|
||||||
|
HeaderOverrides::const_iterator headers_end() const { return Headers.end(); }
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef llvm::StringMap<clang::tooling::Replacements> ReplacementsMap;
|
||||||
|
|
||||||
|
/// \brief Flatten the Rewriter buffers of \p Rewrite and store results as
|
||||||
|
/// file content overrides.
|
||||||
|
void applyRewrites(clang::Rewriter &Rewrite);
|
||||||
|
|
||||||
|
/// \brief Adjust the changed ranges to reflect the parts of the files that
|
||||||
|
/// have been replaced.
|
||||||
|
void adjustChangedRanges(const clang::tooling::Replacements &Replaces,
|
||||||
|
const ReplacementsMap &HeadersReplaces);
|
||||||
|
|
||||||
|
const std::string MainFileName;
|
||||||
|
std::string MainFileOverride;
|
||||||
|
const bool TrackChanges;
|
||||||
|
ChangedRanges MainFileChanges;
|
||||||
|
HeaderOverrides Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Maps source file names to content override information.
|
||||||
|
class FileOverrides {
|
||||||
|
public:
|
||||||
|
typedef llvm::StringMap<SourceOverrides *> SourceOverridesMap;
|
||||||
|
typedef SourceOverridesMap::const_iterator const_iterator;
|
||||||
|
|
||||||
|
/// \brief Construct the SourceOverrides manager.
|
||||||
|
///
|
||||||
|
/// \param TrackChanges Wether or not the \c SourceOverrides should keep track
|
||||||
|
/// of changes. See \c SourceOverrides::isTrackingFileChanges().
|
||||||
|
FileOverrides(bool TrackChanges) : TrackChanges(TrackChanges) {}
|
||||||
|
~FileOverrides();
|
||||||
|
|
||||||
|
const_iterator find(llvm::StringRef Filename) const {
|
||||||
|
return Overrides.find(Filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Get the \c SourceOverrides for \p Filename, creating it if
|
||||||
|
/// necessary.
|
||||||
|
SourceOverrides &getOrCreate(llvm::StringRef Filename);
|
||||||
|
|
||||||
|
/// \brief Iterators.
|
||||||
|
/// @{
|
||||||
|
const_iterator begin() const { return Overrides.begin(); }
|
||||||
|
const_iterator end() const { return Overrides.end(); }
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FileOverrides(const FileOverrides &) LLVM_DELETED_FUNCTION;
|
||||||
|
FileOverrides &operator=(const FileOverrides &) LLVM_DELETED_FUNCTION;
|
||||||
|
|
||||||
|
SourceOverridesMap Overrides;
|
||||||
|
const bool TrackChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Generate a unique filename to store the replacements.
|
/// \brief Generate a unique filename to store the replacements.
|
||||||
///
|
///
|
||||||
/// Generates a unique filename in the same directory as \c MainSourceFile. The
|
/// Generates a unique filename in the same directory as the header file. The
|
||||||
/// filename is generated following this pattern:
|
/// filename is based on the following model:
|
||||||
///
|
///
|
||||||
/// MainSourceFile_%%_%%_%%_%%_%%_%%.yaml
|
/// source.cpp_header.h_%%_%%_%%_%%_%%_%%.yaml
|
||||||
///
|
///
|
||||||
/// where all '%' will be replaced by a randomly chosen hex number.
|
/// where all '%' will be replaced by a randomly chosen hex number.
|
||||||
///
|
///
|
||||||
/// \param[in] MainSourceFile Full path to the source file.
|
/// @param SourceFile Full path to the source file.
|
||||||
/// \param[out] Result The resulting unique filename in the same directory as
|
/// @param HeaderFile Full path to the header file.
|
||||||
/// the \c MainSourceFile.
|
/// @param Result The resulting unique filename in the same directory as the
|
||||||
/// \param[out] Error If an error occurs a description of that error is
|
/// header file.
|
||||||
/// placed in this string.
|
/// @param Error Description of the error if there is any.
|
||||||
/// \returns true on success, false if a unique file name could not be created.
|
/// @returns true if succeeded, false otherwise.
|
||||||
bool generateReplacementsFileName(const llvm::StringRef MainSourceFile,
|
bool generateReplacementsFileName(llvm::StringRef SourceFile,
|
||||||
llvm::SmallVectorImpl<char> &Result,
|
llvm::StringRef HeaderFile,
|
||||||
llvm::SmallVectorImpl<char> &Error);
|
llvm::SmallVectorImpl<char> &Result,
|
||||||
|
llvm::SmallVectorImpl<char> &Error);
|
||||||
|
|
||||||
#endif // CPP11_MIGRATE_FILE_OVERRIDES_H
|
#endif // CPP11_MIGRATE_FILE_OVERRIDES_H
|
||||||
|
|
|
@ -11,4 +11,4 @@ LIBRARYNAME := migrateCore
|
||||||
|
|
||||||
include $(CLANG_LEVEL)/Makefile
|
include $(CLANG_LEVEL)/Makefile
|
||||||
|
|
||||||
CPP.Flags += -I$(PROJ_SRC_DIR)/.. -I$(PROJ_SRC_DIR)/../../clang-replace/include
|
CPP.Flags += -I$(PROJ_SRC_DIR)/..
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
//===-- Core/Refactoring.h - Stand-in for Tooling/Refactoring.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 is meant to be used instead of clang/Tooling/Refactoring.h
|
|
||||||
/// until such time as clang::tooling::Replacements is re-implemented as a
|
|
||||||
/// vector instead of a set.
|
|
||||||
///
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef CPP11_MIGRATE_REPLACEMENTS_VEC_H
|
|
||||||
#define CPP11_MIGRATE_REPLACEMENTS_VEC_H
|
|
||||||
|
|
||||||
#include "clang/Tooling/Refactoring.h"
|
|
||||||
|
|
||||||
// FIXME: Remove this file when clang::tooling::Replacements becomes a vector
|
|
||||||
// instead of a set.
|
|
||||||
|
|
||||||
namespace clang {
|
|
||||||
namespace tooling {
|
|
||||||
typedef std::vector<clang::tooling::Replacement> ReplacementsVec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // CPP11_MIGRATE_REPLACEMENTS_VEC_H
|
|
|
@ -22,23 +22,39 @@
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
void Reformatter::reformatChanges(const FileOverrides &FileStates,
|
void Reformatter::reformatChanges(SourceOverrides &Overrides) {
|
||||||
clang::SourceManager &SM,
|
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
|
||||||
clang::tooling::ReplacementsVec &Replaces) {
|
new DiagnosticOptions());
|
||||||
FileStates.applyOverrides(SM);
|
DiagnosticsEngine Diagnostics(
|
||||||
|
llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
|
||||||
|
DiagOpts.getPtr());
|
||||||
|
FileManager Files((FileSystemOptions()));
|
||||||
|
SourceManager SM(Diagnostics, Files);
|
||||||
|
|
||||||
for (FileOverrides::ChangeMap::const_iterator
|
reformatChanges(Overrides, SM);
|
||||||
I = FileStates.getChangedRanges().begin(),
|
|
||||||
E = FileStates.getChangedRanges().end();
|
|
||||||
I != E; ++I) {
|
|
||||||
reformatSingleFile(I->getKey(), I->getValue(), SM, Replaces);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reformatter::reformatSingleFile(
|
void Reformatter::reformatChanges(SourceOverrides &Overrides,
|
||||||
const llvm::StringRef FileName, const ChangedRanges &Changes,
|
clang::SourceManager &SM) {
|
||||||
SourceManager &SM, clang::tooling::ReplacementsVec &FormatReplacements) {
|
tooling::Replacements Replaces;
|
||||||
|
Overrides.applyOverrides(SM);
|
||||||
|
if (Overrides.isSourceOverriden())
|
||||||
|
Replaces = reformatSingleFile(Overrides.getMainFileName(),
|
||||||
|
Overrides.getChangedRanges(), SM);
|
||||||
|
|
||||||
|
for (HeaderOverrides::const_iterator I = Overrides.headers_begin(),
|
||||||
|
E = Overrides.headers_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
const HeaderOverride &Header = I->getValue();
|
||||||
|
const tooling::Replacements &HeaderReplaces =
|
||||||
|
reformatSingleFile(Header.getHeaderPath(), Header.getChanges(), SM);
|
||||||
|
Replaces.insert(HeaderReplaces.begin(), HeaderReplaces.end());
|
||||||
|
}
|
||||||
|
Overrides.applyReplacements(Replaces, SM);
|
||||||
|
}
|
||||||
|
|
||||||
|
tooling::Replacements Reformatter::reformatSingleFile(
|
||||||
|
llvm::StringRef FileName, const ChangedRanges &Changes, SourceManager &SM) {
|
||||||
const clang::FileEntry *Entry = SM.getFileManager().getFile(FileName);
|
const clang::FileEntry *Entry = SM.getFileManager().getFile(FileName);
|
||||||
assert(Entry && "expected an existing file");
|
assert(Entry && "expected an existing file");
|
||||||
|
|
||||||
|
@ -56,7 +72,5 @@ void Reformatter::reformatSingleFile(
|
||||||
}
|
}
|
||||||
|
|
||||||
Lexer Lex(ID, SM.getBuffer(ID), SM, getFormattingLangOpts(Style.Standard));
|
Lexer Lex(ID, SM.getBuffer(ID), SM, getFormattingLangOpts(Style.Standard));
|
||||||
const tooling::Replacements &R =
|
return format::reformat(Style, Lex, SM, ReformatRanges);
|
||||||
format::reformat(Style, Lex, SM, ReformatRanges);
|
|
||||||
std::copy(R.begin(), R.end(), std::back_inserter(FormatReplacements));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,9 @@
|
||||||
#ifndef CPP11_MIGRATE_REFORMATTING_H
|
#ifndef CPP11_MIGRATE_REFORMATTING_H
|
||||||
#define CPP11_MIGRATE_REFORMATTING_H
|
#define CPP11_MIGRATE_REFORMATTING_H
|
||||||
|
|
||||||
#include "Core/Refactoring.h"
|
|
||||||
#include "clang/Format/Format.h"
|
#include "clang/Format/Format.h"
|
||||||
|
|
||||||
class FileOverrides;
|
class SourceOverrides;
|
||||||
class ChangedRanges;
|
class ChangedRanges;
|
||||||
|
|
||||||
class Reformatter {
|
class Reformatter {
|
||||||
|
@ -28,30 +27,31 @@ public:
|
||||||
|
|
||||||
/// \brief Reformat the changes made to the file overrides.
|
/// \brief Reformat the changes made to the file overrides.
|
||||||
///
|
///
|
||||||
/// This function will apply the state of files stored in \c FileState to \c
|
/// \param Overrides Overriden source files to reformat. Note that since only
|
||||||
/// SM.
|
/// the changes are reformatted, file change tracking has to be enabled.
|
||||||
|
/// \param SM A SourceManager where the overridens files can be found.
|
||||||
///
|
///
|
||||||
/// \param[in] FileState Files to reformat.
|
/// \sa \c SourceOverrides::isTrackingFileChanges()
|
||||||
/// \param[in] SM SourceManager for access to source files.
|
void reformatChanges(SourceOverrides &Overrides, clang::SourceManager &SM);
|
||||||
/// \param[out] Replaces Container to store all reformatting replacements.
|
|
||||||
void reformatChanges(const FileOverrides &FileState, clang::SourceManager &SM,
|
/// \brief Overload of \c reformatChanges() providing it's own
|
||||||
clang::tooling::ReplacementsVec &Replaces);
|
/// \c SourceManager.
|
||||||
|
void reformatChanges(SourceOverrides &Overrides);
|
||||||
|
|
||||||
/// \brief Produce a list of replacements to apply on \p FileName, only the
|
/// \brief Produce a list of replacements to apply on \p FileName, only the
|
||||||
/// ranges in \p Changes are replaced.
|
/// ranges in \p Changes are replaced.
|
||||||
///
|
///
|
||||||
/// Since this routine use \c clang::format::reformat() the rules that
|
/// Since this routine use \c clang::format::reformat() the rules that applies
|
||||||
/// function applies to ranges also apply here.
|
/// on the ranges are identical:
|
||||||
///
|
///
|
||||||
/// \param[in] FileName Name of file to reformat.
|
/// \par
|
||||||
/// \param[in] Changes Description of where changes were made to the file.
|
/// Each range is extended on either end to its next bigger logic
|
||||||
/// \param[in] SM SourceManager required to create replacements.
|
/// unit, i.e. everything that might influence its formatting or might be
|
||||||
/// \param[out] FormatReplacements New reformatting replacements are appended
|
/// influenced by its formatting.
|
||||||
/// to this container.
|
/// -- \c clang::format::reformat()
|
||||||
void reformatSingleFile(const llvm::StringRef FileName,
|
clang::tooling::Replacements reformatSingleFile(llvm::StringRef FileName,
|
||||||
const ChangedRanges &Changes,
|
const ChangedRanges &Changes,
|
||||||
clang::SourceManager &SM,
|
clang::SourceManager &SM);
|
||||||
clang::tooling::ReplacementsVec &FormatReplacements);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
clang::format::FormatStyle Style;
|
clang::format::FormatStyle Style;
|
||||||
|
|
|
@ -30,7 +30,9 @@ public:
|
||||||
if (!SyntaxOnlyAction::BeginSourceFileAction(CI, Filename))
|
if (!SyntaxOnlyAction::BeginSourceFileAction(CI, Filename))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Overrides.applyOverrides(CI.getSourceManager());
|
FileOverrides::const_iterator I = Overrides.find(Filename);
|
||||||
|
if (I != Overrides.end())
|
||||||
|
I->second->applyOverrides(CI.getSourceManager());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,8 +100,13 @@ bool Transform::isFileModifiable(const SourceManager &SM,
|
||||||
bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
|
bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
|
||||||
assert(Overrides != 0 && "Subclass transform didn't provide InputState");
|
assert(Overrides != 0 && "Subclass transform didn't provide InputState");
|
||||||
|
|
||||||
Overrides->applyOverrides(CI.getSourceManager());
|
CurrentSource = Filename.str();
|
||||||
CurrentSource = Filename;
|
|
||||||
|
FileOverrides::const_iterator I = Overrides->find(CurrentSource);
|
||||||
|
if (I != Overrides->end())
|
||||||
|
I->second->applyOverrides(CI.getSourceManager());
|
||||||
|
|
||||||
|
Replace.clear();
|
||||||
|
|
||||||
if (Options().EnableTiming) {
|
if (Options().EnableTiming) {
|
||||||
Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord()));
|
Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord()));
|
||||||
|
@ -111,7 +116,11 @@ bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transform::handleEndSource() {
|
void Transform::handleEndSource() {
|
||||||
CurrentSource.clear();
|
if (!getReplacements().empty()) {
|
||||||
|
SourceOverrides &SO = Overrides->getOrCreate(CurrentSource);
|
||||||
|
SO.applyReplacements(getReplacements());
|
||||||
|
}
|
||||||
|
|
||||||
if (Options().EnableTiming)
|
if (Options().EnableTiming)
|
||||||
Timings.back().second += llvm::TimeRecord::getCurrentTime(false);
|
Timings.back().second += llvm::TimeRecord::getCurrentTime(false);
|
||||||
}
|
}
|
||||||
|
@ -120,19 +129,6 @@ void Transform::addTiming(llvm::StringRef Label, llvm::TimeRecord Duration) {
|
||||||
Timings.push_back(std::make_pair(Label.str(), Duration));
|
Timings.push_back(std::make_pair(Label.str(), Duration));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
Transform::addReplacementForCurrentTU(const clang::tooling::Replacement &R) {
|
|
||||||
if (CurrentSource.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
TranslationUnitReplacements &TU = Replacements[CurrentSource];
|
|
||||||
if (TU.MainSourceFile.empty())
|
|
||||||
TU.MainSourceFile = CurrentSource;
|
|
||||||
TU.Replacements.push_back(R);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
FrontendActionFactory *Transform::createActionFactory(MatchFinder &Finder) {
|
FrontendActionFactory *Transform::createActionFactory(MatchFinder &Finder) {
|
||||||
return new ActionFactory(Finder, /*Owner=*/ *this);
|
return new ActionFactory(Finder, /*Owner=*/ *this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#define CPP11_MIGRATE_TRANSFORM_H
|
#define CPP11_MIGRATE_TRANSFORM_H
|
||||||
|
|
||||||
#include "Core/IncludeExcludeInfo.h"
|
#include "Core/IncludeExcludeInfo.h"
|
||||||
#include "Core/Refactoring.h"
|
#include "clang/Tooling/Refactoring.h"
|
||||||
#include "llvm/ADT/OwningPtr.h"
|
#include "llvm/ADT/OwningPtr.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Registry.h"
|
#include "llvm/Support/Registry.h"
|
||||||
|
@ -52,12 +52,6 @@ class MatchFinder;
|
||||||
|
|
||||||
class FileOverrides;
|
class FileOverrides;
|
||||||
|
|
||||||
|
|
||||||
// \brief Maps main source file names to a TranslationUnitReplacements
|
|
||||||
// structure storing replacements for that translation unit.
|
|
||||||
typedef llvm::StringMap<clang::tooling::TranslationUnitReplacements>
|
|
||||||
TUReplacementsMap;
|
|
||||||
|
|
||||||
/// \brief To group transforms' options together when printing the help.
|
/// \brief To group transforms' options together when printing the help.
|
||||||
extern llvm::cl::OptionCategory TransformsOptionsCategory;
|
extern llvm::cl::OptionCategory TransformsOptionsCategory;
|
||||||
|
|
||||||
|
@ -105,7 +99,7 @@ public:
|
||||||
/// SourcePaths and should take precedence over content of files on disk.
|
/// SourcePaths and should take precedence over content of files on disk.
|
||||||
/// Upon return, \p ResultStates shall contain the result of performing this
|
/// Upon return, \p ResultStates shall contain the result of performing this
|
||||||
/// transform on the files listed in \p SourcePaths.
|
/// transform on the files listed in \p SourcePaths.
|
||||||
virtual int apply(const FileOverrides &InputStates,
|
virtual int apply(FileOverrides &InputStates,
|
||||||
const clang::tooling::CompilationDatabase &Database,
|
const clang::tooling::CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) = 0;
|
const std::vector<std::string> &SourcePaths) = 0;
|
||||||
|
|
||||||
|
@ -178,17 +172,6 @@ public:
|
||||||
/// \brief Return an iterator to the start of collected timing data.
|
/// \brief Return an iterator to the start of collected timing data.
|
||||||
TimingVec::const_iterator timing_end() const { return Timings.end(); }
|
TimingVec::const_iterator timing_end() const { return Timings.end(); }
|
||||||
|
|
||||||
/// \brief Add a Replacement to the list for the current translation unit.
|
|
||||||
///
|
|
||||||
/// \returns \li true on success
|
|
||||||
/// \li false if there is no current translation unit
|
|
||||||
bool addReplacementForCurrentTU(const clang::tooling::Replacement &R);
|
|
||||||
|
|
||||||
/// \brief Accessor to Replacements across all transformed translation units.
|
|
||||||
const TUReplacementsMap &getAllReplacements() const {
|
|
||||||
return Replacements;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void setAcceptedChanges(unsigned Changes) {
|
void setAcceptedChanges(unsigned Changes) {
|
||||||
|
@ -212,12 +195,16 @@ protected:
|
||||||
/// created with.
|
/// created with.
|
||||||
const TransformOptions &Options() { return GlobalOptions; }
|
const TransformOptions &Options() { return GlobalOptions; }
|
||||||
|
|
||||||
|
/// \brief Provide access for subclasses for the container to store
|
||||||
|
/// translation unit replacements.
|
||||||
|
clang::tooling::Replacements &getReplacements() { return Replace; }
|
||||||
|
|
||||||
/// \brief Affords a subclass to provide file contents overrides before
|
/// \brief Affords a subclass to provide file contents overrides before
|
||||||
/// applying frontend actions.
|
/// applying frontend actions.
|
||||||
///
|
///
|
||||||
/// It is an error not to call this function before calling ClangTool::run()
|
/// It is an error not to call this function before calling ClangTool::run()
|
||||||
/// with the factory provided by createActionFactory().
|
/// with the factory provided by createActionFactory().
|
||||||
void setOverrides(const FileOverrides &Overrides) {
|
void setOverrides(FileOverrides &Overrides) {
|
||||||
this->Overrides = &Overrides;
|
this->Overrides = &Overrides;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,8 +219,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
const std::string Name;
|
const std::string Name;
|
||||||
const TransformOptions &GlobalOptions;
|
const TransformOptions &GlobalOptions;
|
||||||
const FileOverrides *Overrides;
|
FileOverrides *Overrides;
|
||||||
TUReplacementsMap Replacements;
|
clang::tooling::Replacements Replace;
|
||||||
std::string CurrentSource;
|
std::string CurrentSource;
|
||||||
TimingVec Timings;
|
TimingVec Timings;
|
||||||
unsigned AcceptedChanges;
|
unsigned AcceptedChanges;
|
||||||
|
|
|
@ -815,9 +815,9 @@ void LoopFixer::doConversion(ASTContext *Context,
|
||||||
// the declaration of the alias variable. This is probably a bug.
|
// the declaration of the alias variable. This is probably a bug.
|
||||||
ReplacementText = ";";
|
ReplacementText = ";";
|
||||||
|
|
||||||
Owner.addReplacementForCurrentTU(Replacement(
|
Replace->insert(Replacement(Context->getSourceManager(),
|
||||||
Context->getSourceManager(),
|
CharSourceRange::getTokenRange(ReplaceRange),
|
||||||
CharSourceRange::getTokenRange(ReplaceRange), ReplacementText));
|
ReplacementText));
|
||||||
// No further replacements are made to the loop, since the iterator or index
|
// No further replacements are made to the loop, since the iterator or index
|
||||||
// was used exactly once - in the initialization of AliasVar.
|
// was used exactly once - in the initialization of AliasVar.
|
||||||
} else {
|
} else {
|
||||||
|
@ -830,9 +830,10 @@ void LoopFixer::doConversion(ASTContext *Context,
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
std::string ReplaceText = I->IsArrow ? VarName + "." : VarName;
|
std::string ReplaceText = I->IsArrow ? VarName + "." : VarName;
|
||||||
ReplacedVarRanges->insert(std::make_pair(TheLoop, IndexVar));
|
ReplacedVarRanges->insert(std::make_pair(TheLoop, IndexVar));
|
||||||
Owner.addReplacementForCurrentTU(
|
Replace->insert(
|
||||||
Replacement(Context->getSourceManager(),
|
Replacement(Context->getSourceManager(),
|
||||||
CharSourceRange::getTokenRange(I->Range), ReplaceText));
|
CharSourceRange::getTokenRange(I->Range),
|
||||||
|
ReplaceText));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,9 +862,9 @@ void LoopFixer::doConversion(ASTContext *Context,
|
||||||
std::string TypeString = AutoRefType.getAsString();
|
std::string TypeString = AutoRefType.getAsString();
|
||||||
std::string Range = ("(" + TypeString + " " + VarName + " : "
|
std::string Range = ("(" + TypeString + " " + VarName + " : "
|
||||||
+ MaybeDereference + ContainerString + ")").str();
|
+ MaybeDereference + ContainerString + ")").str();
|
||||||
Owner.addReplacementForCurrentTU(
|
Replace->insert(Replacement(Context->getSourceManager(),
|
||||||
Replacement(Context->getSourceManager(),
|
CharSourceRange::getTokenRange(ParenRange),
|
||||||
CharSourceRange::getTokenRange(ParenRange), Range));
|
Range));
|
||||||
GeneratedDecls->insert(make_pair(TheLoop, VarName));
|
GeneratedDecls->insert(make_pair(TheLoop, VarName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,12 @@ enum LoopFixerKind {
|
||||||
class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||||
public:
|
public:
|
||||||
LoopFixer(StmtAncestorASTVisitor *ParentFinder,
|
LoopFixer(StmtAncestorASTVisitor *ParentFinder,
|
||||||
|
clang::tooling::Replacements *Replace,
|
||||||
StmtGeneratedVarNameMap *GeneratedDecls,
|
StmtGeneratedVarNameMap *GeneratedDecls,
|
||||||
ReplacedVarsMap *ReplacedVarRanges, unsigned *AcceptedChanges,
|
ReplacedVarsMap *ReplacedVarRanges, unsigned *AcceptedChanges,
|
||||||
unsigned *DeferredChanges, unsigned *RejectedChanges,
|
unsigned *DeferredChanges, unsigned *RejectedChanges,
|
||||||
RiskLevel MaxRisk, LoopFixerKind FixerKind, Transform &Owner)
|
RiskLevel MaxRisk, LoopFixerKind FixerKind, const Transform &Owner)
|
||||||
: ParentFinder(ParentFinder),
|
: ParentFinder(ParentFinder), Replace(Replace),
|
||||||
GeneratedDecls(GeneratedDecls), ReplacedVarRanges(ReplacedVarRanges),
|
GeneratedDecls(GeneratedDecls), ReplacedVarRanges(ReplacedVarRanges),
|
||||||
AcceptedChanges(AcceptedChanges), DeferredChanges(DeferredChanges),
|
AcceptedChanges(AcceptedChanges), DeferredChanges(DeferredChanges),
|
||||||
RejectedChanges(RejectedChanges), MaxRisk(MaxRisk),
|
RejectedChanges(RejectedChanges), MaxRisk(MaxRisk),
|
||||||
|
@ -56,6 +57,7 @@ class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StmtAncestorASTVisitor *ParentFinder;
|
StmtAncestorASTVisitor *ParentFinder;
|
||||||
|
clang::tooling::Replacements *Replace;
|
||||||
StmtGeneratedVarNameMap *GeneratedDecls;
|
StmtGeneratedVarNameMap *GeneratedDecls;
|
||||||
ReplacedVarsMap *ReplacedVarRanges;
|
ReplacedVarsMap *ReplacedVarRanges;
|
||||||
unsigned *AcceptedChanges;
|
unsigned *AcceptedChanges;
|
||||||
|
@ -63,7 +65,7 @@ class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||||
unsigned *RejectedChanges;
|
unsigned *RejectedChanges;
|
||||||
RiskLevel MaxRisk;
|
RiskLevel MaxRisk;
|
||||||
LoopFixerKind FixerKind;
|
LoopFixerKind FixerKind;
|
||||||
Transform &Owner;
|
const Transform &Owner;
|
||||||
|
|
||||||
/// \brief Computes the changes needed to convert a given for loop, and
|
/// \brief Computes the changes needed to convert a given for loop, and
|
||||||
/// applies it.
|
/// applies it.
|
||||||
|
|
|
@ -24,7 +24,7 @@ using clang::ast_matchers::MatchFinder;
|
||||||
using namespace clang::tooling;
|
using namespace clang::tooling;
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
int LoopConvertTransform::apply(const FileOverrides &InputStates,
|
int LoopConvertTransform::apply(FileOverrides &InputStates,
|
||||||
const CompilationDatabase &Database,
|
const CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) {
|
const std::vector<std::string> &SourcePaths) {
|
||||||
ClangTool LoopTool(Database, SourcePaths);
|
ClangTool LoopTool(Database, SourcePaths);
|
||||||
|
@ -37,20 +37,20 @@ int LoopConvertTransform::apply(const FileOverrides &InputStates,
|
||||||
unsigned RejectedChanges = 0;
|
unsigned RejectedChanges = 0;
|
||||||
|
|
||||||
MatchFinder Finder;
|
MatchFinder Finder;
|
||||||
LoopFixer ArrayLoopFixer(&ParentFinder, &GeneratedDecls, &ReplacedVars,
|
LoopFixer ArrayLoopFixer(&ParentFinder, &getReplacements(), &GeneratedDecls,
|
||||||
&AcceptedChanges, &DeferredChanges, &RejectedChanges,
|
&ReplacedVars, &AcceptedChanges, &DeferredChanges,
|
||||||
Options().MaxRiskLevel, LFK_Array,
|
&RejectedChanges, Options().MaxRiskLevel, LFK_Array,
|
||||||
/*Owner=*/ *this);
|
/*Owner=*/ *this);
|
||||||
Finder.addMatcher(makeArrayLoopMatcher(), &ArrayLoopFixer);
|
Finder.addMatcher(makeArrayLoopMatcher(), &ArrayLoopFixer);
|
||||||
LoopFixer IteratorLoopFixer(&ParentFinder, &GeneratedDecls, &ReplacedVars,
|
LoopFixer IteratorLoopFixer(
|
||||||
&AcceptedChanges, &DeferredChanges,
|
&ParentFinder, &getReplacements(), &GeneratedDecls, &ReplacedVars,
|
||||||
&RejectedChanges, Options().MaxRiskLevel,
|
&AcceptedChanges, &DeferredChanges, &RejectedChanges,
|
||||||
LFK_Iterator, /*Owner=*/ *this);
|
Options().MaxRiskLevel, LFK_Iterator, /*Owner=*/ *this);
|
||||||
Finder.addMatcher(makeIteratorLoopMatcher(), &IteratorLoopFixer);
|
Finder.addMatcher(makeIteratorLoopMatcher(), &IteratorLoopFixer);
|
||||||
LoopFixer PseudoarrrayLoopFixer(&ParentFinder, &GeneratedDecls, &ReplacedVars,
|
LoopFixer PseudoarrrayLoopFixer(
|
||||||
&AcceptedChanges, &DeferredChanges,
|
&ParentFinder, &getReplacements(), &GeneratedDecls, &ReplacedVars,
|
||||||
&RejectedChanges, Options().MaxRiskLevel,
|
&AcceptedChanges, &DeferredChanges, &RejectedChanges,
|
||||||
LFK_PseudoArray, /*Owner=*/ *this);
|
Options().MaxRiskLevel, LFK_PseudoArray, /*Owner=*/ *this);
|
||||||
Finder.addMatcher(makePseudoArrayLoopMatcher(), &PseudoarrrayLoopFixer);
|
Finder.addMatcher(makePseudoArrayLoopMatcher(), &PseudoarrrayLoopFixer);
|
||||||
|
|
||||||
setOverrides(InputStates);
|
setOverrides(InputStates);
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
: Transform("LoopConvert", Options) {}
|
: Transform("LoopConvert", Options) {}
|
||||||
|
|
||||||
/// \see Transform::run().
|
/// \see Transform::run().
|
||||||
virtual int apply(const FileOverrides &InputStates,
|
virtual int apply(FileOverrides &InputStates,
|
||||||
const clang::tooling::CompilationDatabase &Database,
|
const clang::tooling::CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,14 +21,15 @@ using namespace clang;
|
||||||
using namespace clang::tooling;
|
using namespace clang::tooling;
|
||||||
using namespace clang::ast_matchers;
|
using namespace clang::ast_matchers;
|
||||||
|
|
||||||
int PassByValueTransform::apply(const FileOverrides &InputStates,
|
int PassByValueTransform::apply(
|
||||||
const tooling::CompilationDatabase &Database,
|
FileOverrides &InputStates, const tooling::CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) {
|
const std::vector<std::string> &SourcePaths) {
|
||||||
ClangTool Tool(Database, SourcePaths);
|
ClangTool Tool(Database, SourcePaths);
|
||||||
unsigned AcceptedChanges = 0;
|
unsigned AcceptedChanges = 0;
|
||||||
unsigned RejectedChanges = 0;
|
unsigned RejectedChanges = 0;
|
||||||
MatchFinder Finder;
|
MatchFinder Finder;
|
||||||
ConstructorParamReplacer Replacer(AcceptedChanges, RejectedChanges,
|
ConstructorParamReplacer Replacer(getReplacements(), AcceptedChanges,
|
||||||
|
RejectedChanges,
|
||||||
/*Owner=*/ *this);
|
/*Owner=*/ *this);
|
||||||
|
|
||||||
Finder.addMatcher(makePassByValueCtorParamMatcher(), &Replacer);
|
Finder.addMatcher(makePassByValueCtorParamMatcher(), &Replacer);
|
||||||
|
|
|
@ -58,7 +58,7 @@ public:
|
||||||
: Transform("PassByValue", Options), Replacer(0) {}
|
: Transform("PassByValue", Options), Replacer(0) {}
|
||||||
|
|
||||||
/// \see Transform::apply().
|
/// \see Transform::apply().
|
||||||
virtual int apply(const FileOverrides &InputStates,
|
virtual int apply(FileOverrides &InputStates,
|
||||||
const clang::tooling::CompilationDatabase &Database,
|
const clang::tooling::CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||||
|
|
||||||
|
|
|
@ -151,21 +151,17 @@ void ConstructorParamReplacer::run(const MatchFinder::MatchResult &Result) {
|
||||||
const tooling::Replacement &IncludeReplace =
|
const tooling::Replacement &IncludeReplace =
|
||||||
IncludeManager->addAngledInclude(STDMoveFile, "utility");
|
IncludeManager->addAngledInclude(STDMoveFile, "utility");
|
||||||
if (IncludeReplace.isApplicable()) {
|
if (IncludeReplace.isApplicable()) {
|
||||||
Owner.addReplacementForCurrentTU(IncludeReplace);
|
Replaces.insert(IncludeReplace);
|
||||||
AcceptedChanges++;
|
AcceptedChanges++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const-ref params becomes values (const Foo & -> Foo)
|
// const-ref params becomes values (const Foo & -> Foo)
|
||||||
for (const Replacement *I = ParamReplaces.begin(), *E = ParamReplaces.end();
|
Replaces.insert(ParamReplaces.begin(), ParamReplaces.end());
|
||||||
I != E; ++I) {
|
|
||||||
Owner.addReplacementForCurrentTU(*I);
|
|
||||||
}
|
|
||||||
AcceptedChanges += ParamReplaces.size();
|
AcceptedChanges += ParamReplaces.size();
|
||||||
|
|
||||||
// move the value in the init-list
|
// move the value in the init-list
|
||||||
Owner.addReplacementForCurrentTU(Replacement(
|
Replaces.insert(Replacement(
|
||||||
SM, Initializer->getLParenLoc().getLocWithOffset(1), 0, "std::move("));
|
SM, Initializer->getLParenLoc().getLocWithOffset(1), 0, "std::move("));
|
||||||
Owner.addReplacementForCurrentTU(
|
Replaces.insert(Replacement(SM, Initializer->getRParenLoc(), 0, ")"));
|
||||||
Replacement(SM, Initializer->getRParenLoc(), 0, ")"));
|
|
||||||
AcceptedChanges += 2;
|
AcceptedChanges += 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,10 +51,11 @@ class IncludeDirectives;
|
||||||
class ConstructorParamReplacer
|
class ConstructorParamReplacer
|
||||||
: public clang::ast_matchers::MatchFinder::MatchCallback {
|
: public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||||
public:
|
public:
|
||||||
ConstructorParamReplacer(unsigned &AcceptedChanges, unsigned &RejectedChanges,
|
ConstructorParamReplacer(clang::tooling::Replacements &Replaces,
|
||||||
Transform &Owner)
|
unsigned &AcceptedChanges, unsigned &RejectedChanges,
|
||||||
: AcceptedChanges(AcceptedChanges), RejectedChanges(RejectedChanges),
|
const Transform &Owner)
|
||||||
Owner(Owner), IncludeManager(0) {}
|
: Replaces(Replaces), AcceptedChanges(AcceptedChanges),
|
||||||
|
RejectedChanges(RejectedChanges), Owner(Owner), IncludeManager(0) {}
|
||||||
|
|
||||||
void setIncludeDirectives(IncludeDirectives *Includes) {
|
void setIncludeDirectives(IncludeDirectives *Includes) {
|
||||||
IncludeManager = Includes;
|
IncludeManager = Includes;
|
||||||
|
@ -65,9 +66,10 @@ private:
|
||||||
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
|
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
|
||||||
LLVM_OVERRIDE;
|
LLVM_OVERRIDE;
|
||||||
|
|
||||||
|
clang::tooling::Replacements &Replaces;
|
||||||
unsigned &AcceptedChanges;
|
unsigned &AcceptedChanges;
|
||||||
unsigned &RejectedChanges;
|
unsigned &RejectedChanges;
|
||||||
Transform &Owner;
|
const Transform &Owner;
|
||||||
IncludeDirectives *IncludeManager;
|
IncludeDirectives *IncludeManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,16 @@ using namespace clang::tooling;
|
||||||
using namespace clang::ast_matchers;
|
using namespace clang::ast_matchers;
|
||||||
|
|
||||||
int
|
int
|
||||||
ReplaceAutoPtrTransform::apply(const FileOverrides &InputStates,
|
ReplaceAutoPtrTransform::apply(FileOverrides &InputStates,
|
||||||
const CompilationDatabase &Database,
|
const CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) {
|
const std::vector<std::string> &SourcePaths) {
|
||||||
ClangTool Tool(Database, SourcePaths);
|
ClangTool Tool(Database, SourcePaths);
|
||||||
unsigned AcceptedChanges = 0;
|
unsigned AcceptedChanges = 0;
|
||||||
MatchFinder Finder;
|
MatchFinder Finder;
|
||||||
AutoPtrReplacer Replacer(AcceptedChanges, /*Owner=*/ *this);
|
AutoPtrReplacer Replacer(getReplacements(), AcceptedChanges,
|
||||||
OwnershipTransferFixer Fixer(AcceptedChanges, /*Owner=*/ *this);
|
/*Owner=*/*this);
|
||||||
|
OwnershipTransferFixer Fixer(getReplacements(), AcceptedChanges,
|
||||||
|
/*Owner=*/*this);
|
||||||
|
|
||||||
Finder.addMatcher(makeAutoPtrTypeLocMatcher(), &Replacer);
|
Finder.addMatcher(makeAutoPtrTypeLocMatcher(), &Replacer);
|
||||||
Finder.addMatcher(makeAutoPtrUsingDeclMatcher(), &Replacer);
|
Finder.addMatcher(makeAutoPtrUsingDeclMatcher(), &Replacer);
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
: Transform("ReplaceAutoPtr", Options) {}
|
: Transform("ReplaceAutoPtr", Options) {}
|
||||||
|
|
||||||
/// \see Transform::run().
|
/// \see Transform::run().
|
||||||
virtual int apply(const FileOverrides &InputStates,
|
virtual int apply(FileOverrides &InputStates,
|
||||||
const clang::tooling::CompilationDatabase &Database,
|
const clang::tooling::CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,7 +66,7 @@ void AutoPtrReplacer::run(const MatchFinder::MatchResult &Result) {
|
||||||
if (!checkTokenIsAutoPtr(IdentifierLoc, SM, LangOptions()))
|
if (!checkTokenIsAutoPtr(IdentifierLoc, SM, LangOptions()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Owner.addReplacementForCurrentTU(
|
Replace.insert(
|
||||||
Replacement(SM, IdentifierLoc, strlen("auto_ptr"), "unique_ptr"));
|
Replacement(SM, IdentifierLoc, strlen("auto_ptr"), "unique_ptr"));
|
||||||
++AcceptedChanges;
|
++AcceptedChanges;
|
||||||
}
|
}
|
||||||
|
@ -101,8 +101,7 @@ void OwnershipTransferFixer::run(const MatchFinder::MatchResult &Result) {
|
||||||
if (!Owner.isFileModifiable(SM, Range.getBegin()))
|
if (!Owner.isFileModifiable(SM, Range.getBegin()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Owner.addReplacementForCurrentTU(
|
Replace.insert(Replacement(SM, Range.getBegin(), 0, "std::move("));
|
||||||
Replacement(SM, Range.getBegin(), 0, "std::move("));
|
Replace.insert(Replacement(SM, Range.getEnd(), 0, ")"));
|
||||||
Owner.addReplacementForCurrentTU(Replacement(SM, Range.getEnd(), 0, ")"));
|
|
||||||
AcceptedChanges += 2;
|
AcceptedChanges += 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,9 @@ class Transform;
|
||||||
/// using declarations.
|
/// using declarations.
|
||||||
class AutoPtrReplacer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
class AutoPtrReplacer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||||
public:
|
public:
|
||||||
AutoPtrReplacer(unsigned &AcceptedChanges, Transform &Owner)
|
AutoPtrReplacer(clang::tooling::Replacements &Replace,
|
||||||
: AcceptedChanges(AcceptedChanges), Owner(Owner) {}
|
unsigned &AcceptedChanges, const Transform &Owner)
|
||||||
|
: Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {}
|
||||||
|
|
||||||
/// \brief Entry point to the callback called when matches are made.
|
/// \brief Entry point to the callback called when matches are made.
|
||||||
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
|
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
|
||||||
|
@ -62,8 +63,9 @@ private:
|
||||||
const clang::SourceManager &SM);
|
const clang::SourceManager &SM);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
clang::tooling::Replacements &Replace;
|
||||||
unsigned &AcceptedChanges;
|
unsigned &AcceptedChanges;
|
||||||
Transform &Owner;
|
const Transform &Owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief The callback to be used to fix the ownership transfers of
|
/// \brief The callback to be used to fix the ownership transfers of
|
||||||
|
@ -84,16 +86,18 @@ private:
|
||||||
class OwnershipTransferFixer
|
class OwnershipTransferFixer
|
||||||
: public clang::ast_matchers::MatchFinder::MatchCallback {
|
: public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||||
public:
|
public:
|
||||||
OwnershipTransferFixer(unsigned &AcceptedChanges, Transform &Owner)
|
OwnershipTransferFixer(clang::tooling::Replacements &Replace,
|
||||||
: AcceptedChanges(AcceptedChanges), Owner(Owner) {}
|
unsigned &AcceptedChanges, const Transform &Owner)
|
||||||
|
: Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {}
|
||||||
|
|
||||||
/// \brief Entry point to the callback called when matches are made.
|
/// \brief Entry point to the callback called when matches are made.
|
||||||
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
|
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
|
||||||
LLVM_OVERRIDE;
|
LLVM_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
clang::tooling::Replacements &Replace;
|
||||||
unsigned &AcceptedChanges;
|
unsigned &AcceptedChanges;
|
||||||
Transform &Owner;
|
const Transform &Owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPP11_MIGRATE_REPLACE_AUTO_PTR_ACTIONS_H
|
#endif // CPP11_MIGRATE_REPLACE_AUTO_PTR_ACTIONS_H
|
||||||
|
|
|
@ -20,7 +20,7 @@ using clang::ast_matchers::MatchFinder;
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace clang::tooling;
|
using namespace clang::tooling;
|
||||||
|
|
||||||
int UseAutoTransform::apply(const FileOverrides &InputStates,
|
int UseAutoTransform::apply(FileOverrides &InputStates,
|
||||||
const clang::tooling::CompilationDatabase &Database,
|
const clang::tooling::CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) {
|
const std::vector<std::string> &SourcePaths) {
|
||||||
ClangTool UseAutoTool(Database, SourcePaths);
|
ClangTool UseAutoTool(Database, SourcePaths);
|
||||||
|
@ -28,11 +28,10 @@ int UseAutoTransform::apply(const FileOverrides &InputStates,
|
||||||
unsigned AcceptedChanges = 0;
|
unsigned AcceptedChanges = 0;
|
||||||
|
|
||||||
MatchFinder Finder;
|
MatchFinder Finder;
|
||||||
ReplacementsVec Replaces;
|
IteratorReplacer ReplaceIterators(getReplacements(), AcceptedChanges,
|
||||||
IteratorReplacer ReplaceIterators(AcceptedChanges, Options().MaxRiskLevel,
|
Options().MaxRiskLevel, /*Owner=*/ *this);
|
||||||
/*Owner=*/ *this);
|
NewReplacer ReplaceNew(getReplacements(), AcceptedChanges,
|
||||||
NewReplacer ReplaceNew(AcceptedChanges, Options().MaxRiskLevel,
|
Options().MaxRiskLevel, /*Owner=*/ *this);
|
||||||
/*Owner=*/ *this);
|
|
||||||
|
|
||||||
Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators);
|
Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators);
|
||||||
Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew);
|
Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew);
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
: Transform("UseAuto", Options) {}
|
: Transform("UseAuto", Options) {}
|
||||||
|
|
||||||
/// \see Transform::run().
|
/// \see Transform::run().
|
||||||
virtual int apply(const FileOverrides &InputStates,
|
virtual int apply(FileOverrides &InputStates,
|
||||||
const clang::tooling::CompilationDatabase &Database,
|
const clang::tooling::CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
|
@ -73,7 +73,7 @@ void IteratorReplacer::run(const MatchFinder::MatchResult &Result) {
|
||||||
// iterators but something to keep in mind in the future.
|
// iterators but something to keep in mind in the future.
|
||||||
|
|
||||||
CharSourceRange Range(TL.getSourceRange(), true);
|
CharSourceRange Range(TL.getSourceRange(), true);
|
||||||
Owner.addReplacementForCurrentTU(tooling::Replacement(SM, Range, "auto"));
|
Replace.insert(tooling::Replacement(SM, Range, "auto"));
|
||||||
++AcceptedChanges;
|
++AcceptedChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,9 +131,8 @@ void NewReplacer::run(const MatchFinder::MatchResult &Result) {
|
||||||
for (std::vector<SourceLocation>::iterator I = StarLocations.begin(),
|
for (std::vector<SourceLocation>::iterator I = StarLocations.begin(),
|
||||||
E = StarLocations.end();
|
E = StarLocations.end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
Owner.addReplacementForCurrentTU(tooling::Replacement(SM, *I, 1, ""));
|
Replace.insert(tooling::Replacement(SM, *I, 1, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: There is, however, one case we can address: when the VarDecl
|
// FIXME: There is, however, one case we can address: when the VarDecl
|
||||||
// pointee is the same as the initializer, just more CV-qualified. However,
|
// pointee is the same as the initializer, just more CV-qualified. However,
|
||||||
// TypeLoc information is not reliable where CV qualifiers are concerned so
|
// TypeLoc information is not reliable where CV qualifiers are concerned so
|
||||||
|
@ -142,6 +141,6 @@ void NewReplacer::run(const MatchFinder::MatchResult &Result) {
|
||||||
FirstDecl->getTypeSourceInfo()->getTypeLoc().getSourceRange(), true);
|
FirstDecl->getTypeSourceInfo()->getTypeLoc().getSourceRange(), true);
|
||||||
// Space after 'auto' to handle cases where the '*' in the pointer type
|
// Space after 'auto' to handle cases where the '*' in the pointer type
|
||||||
// is next to the identifier. This avoids changing 'int *p' into 'autop'.
|
// is next to the identifier. This avoids changing 'int *p' into 'autop'.
|
||||||
Owner.addReplacementForCurrentTU(tooling::Replacement(SM, Range, "auto "));
|
Replace.insert(tooling::Replacement(SM, Range, "auto "));
|
||||||
++AcceptedChanges;
|
++AcceptedChanges;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,32 +25,36 @@
|
||||||
class IteratorReplacer
|
class IteratorReplacer
|
||||||
: public clang::ast_matchers::MatchFinder::MatchCallback {
|
: public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||||
public:
|
public:
|
||||||
IteratorReplacer(unsigned &AcceptedChanges, RiskLevel, Transform &Owner)
|
IteratorReplacer(clang::tooling::Replacements &Replace,
|
||||||
: AcceptedChanges(AcceptedChanges), Owner(Owner) {}
|
unsigned &AcceptedChanges, RiskLevel, const Transform &Owner)
|
||||||
|
: Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {}
|
||||||
|
|
||||||
/// \brief Entry point to the callback called when matches are made.
|
/// \brief Entry point to the callback called when matches are made.
|
||||||
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
|
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
|
||||||
LLVM_OVERRIDE;
|
LLVM_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
clang::tooling::Replacements &Replace;
|
||||||
unsigned &AcceptedChanges;
|
unsigned &AcceptedChanges;
|
||||||
Transform &Owner;
|
const Transform &Owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief The callback used when replacing type specifiers of variable
|
/// \brief The callback used when replacing type specifiers of variable
|
||||||
/// declarations initialized by a C++ new expression.
|
/// declarations initialized by a C++ new expression.
|
||||||
class NewReplacer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
class NewReplacer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||||
public:
|
public:
|
||||||
NewReplacer(unsigned &AcceptedChanges, RiskLevel, Transform &Owner)
|
NewReplacer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges,
|
||||||
: AcceptedChanges(AcceptedChanges), Owner(Owner) {}
|
RiskLevel, const Transform &Owner)
|
||||||
|
: Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {}
|
||||||
|
|
||||||
/// \brief Entry point to the callback called when matches are made.
|
/// \brief Entry point to the callback called when matches are made.
|
||||||
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
|
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
|
||||||
LLVM_OVERRIDE;
|
LLVM_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
clang::tooling::Replacements &Replace;
|
||||||
unsigned &AcceptedChanges;
|
unsigned &AcceptedChanges;
|
||||||
Transform &Owner;
|
const Transform &Owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPP11_MIGRATE_USE_AUTO_ACTIONS_H
|
#endif // CPP11_MIGRATE_USE_AUTO_ACTIONS_H
|
||||||
|
|
|
@ -47,7 +47,7 @@ bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
|
||||||
/// \brief Replaces the provided range with the text "nullptr", but only if
|
/// \brief Replaces the provided range with the text "nullptr", but only if
|
||||||
/// the start and end location are both in main file.
|
/// the start and end location are both in main file.
|
||||||
/// Returns true if and only if a replacement was made.
|
/// Returns true if and only if a replacement was made.
|
||||||
void ReplaceWithNullptr(Transform &Owner, SourceManager &SM,
|
void ReplaceWithNullptr(tooling::Replacements &Replace, SourceManager &SM,
|
||||||
SourceLocation StartLoc, SourceLocation EndLoc) {
|
SourceLocation StartLoc, SourceLocation EndLoc) {
|
||||||
CharSourceRange Range(SourceRange(StartLoc, EndLoc), true);
|
CharSourceRange Range(SourceRange(StartLoc, EndLoc), true);
|
||||||
// Add a space if nullptr follows an alphanumeric character. This happens
|
// Add a space if nullptr follows an alphanumeric character. This happens
|
||||||
|
@ -55,11 +55,9 @@ void ReplaceWithNullptr(Transform &Owner, SourceManager &SM,
|
||||||
// parentheses and right beside a return statement.
|
// parentheses and right beside a return statement.
|
||||||
SourceLocation PreviousLocation = StartLoc.getLocWithOffset(-1);
|
SourceLocation PreviousLocation = StartLoc.getLocWithOffset(-1);
|
||||||
if (isAlphanumeric(*FullSourceLoc(PreviousLocation, SM).getCharacterData()))
|
if (isAlphanumeric(*FullSourceLoc(PreviousLocation, SM).getCharacterData()))
|
||||||
Owner.addReplacementForCurrentTU(
|
Replace.insert(tooling::Replacement(SM, Range, " nullptr"));
|
||||||
tooling::Replacement(SM, Range, " nullptr"));
|
|
||||||
else
|
else
|
||||||
Owner.addReplacementForCurrentTU(
|
Replace.insert(tooling::Replacement(SM, Range, "nullptr"));
|
||||||
tooling::Replacement(SM, Range, "nullptr"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Returns the name of the outermost macro.
|
/// \brief Returns the name of the outermost macro.
|
||||||
|
@ -155,9 +153,10 @@ private:
|
||||||
/// ambiguities.
|
/// ambiguities.
|
||||||
class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
|
class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
|
||||||
public:
|
public:
|
||||||
CastSequenceVisitor(ASTContext &Context, const UserMacroNames &UserNullMacros,
|
CastSequenceVisitor(tooling::Replacements &R, ASTContext &Context,
|
||||||
unsigned &AcceptedChanges, Transform &Owner)
|
const UserMacroNames &UserNullMacros,
|
||||||
: SM(Context.getSourceManager()), Context(Context),
|
unsigned &AcceptedChanges, const Transform &Owner)
|
||||||
|
: Replace(R), SM(Context.getSourceManager()), Context(Context),
|
||||||
UserNullMacros(UserNullMacros), AcceptedChanges(AcceptedChanges),
|
UserNullMacros(UserNullMacros), AcceptedChanges(AcceptedChanges),
|
||||||
Owner(Owner), FirstSubExpr(0), PruneSubtree(false) {}
|
Owner(Owner), FirstSubExpr(0), PruneSubtree(false) {}
|
||||||
|
|
||||||
|
@ -197,7 +196,7 @@ public:
|
||||||
FileLocEnd = SM.getFileLoc(EndLoc);
|
FileLocEnd = SM.getFileLoc(EndLoc);
|
||||||
if (isReplaceableRange(FileLocStart, FileLocEnd, SM, Owner) &&
|
if (isReplaceableRange(FileLocStart, FileLocEnd, SM, Owner) &&
|
||||||
allArgUsesValid(C)) {
|
allArgUsesValid(C)) {
|
||||||
ReplaceWithNullptr(Owner, SM, FileLocStart, FileLocEnd);
|
ReplaceWithNullptr(Replace, SM, FileLocStart, FileLocEnd);
|
||||||
++AcceptedChanges;
|
++AcceptedChanges;
|
||||||
}
|
}
|
||||||
return skipSubTree();
|
return skipSubTree();
|
||||||
|
@ -221,7 +220,7 @@ public:
|
||||||
if (!isReplaceableRange(StartLoc, EndLoc, SM, Owner)) {
|
if (!isReplaceableRange(StartLoc, EndLoc, SM, Owner)) {
|
||||||
return skipSubTree();
|
return skipSubTree();
|
||||||
}
|
}
|
||||||
ReplaceWithNullptr(Owner, SM, StartLoc, EndLoc);
|
ReplaceWithNullptr(Replace, SM, StartLoc, EndLoc);
|
||||||
++AcceptedChanges;
|
++AcceptedChanges;
|
||||||
|
|
||||||
return skipSubTree();
|
return skipSubTree();
|
||||||
|
@ -418,19 +417,21 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
tooling::Replacements &Replace;
|
||||||
SourceManager &SM;
|
SourceManager &SM;
|
||||||
ASTContext &Context;
|
ASTContext &Context;
|
||||||
const UserMacroNames &UserNullMacros;
|
const UserMacroNames &UserNullMacros;
|
||||||
unsigned &AcceptedChanges;
|
unsigned &AcceptedChanges;
|
||||||
Transform &Owner;
|
const Transform &Owner;
|
||||||
Expr *FirstSubExpr;
|
Expr *FirstSubExpr;
|
||||||
bool PruneSubtree;
|
bool PruneSubtree;
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
NullptrFixer::NullptrFixer(unsigned &AcceptedChanges, RiskLevel,
|
NullptrFixer::NullptrFixer(clang::tooling::Replacements &Replace,
|
||||||
Transform &Owner)
|
unsigned &AcceptedChanges, RiskLevel,
|
||||||
: AcceptedChanges(AcceptedChanges), Owner(Owner) {
|
const Transform &Owner)
|
||||||
|
: Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {
|
||||||
if (!UserNullMacroNames.empty()) {
|
if (!UserNullMacroNames.empty()) {
|
||||||
llvm::StringRef S = UserNullMacroNames;
|
llvm::StringRef S = UserNullMacroNames;
|
||||||
S.split(UserNullMacros, ",");
|
S.split(UserNullMacros, ",");
|
||||||
|
@ -444,7 +445,7 @@ void NullptrFixer::run(const ast_matchers::MatchFinder::MatchResult &Result) {
|
||||||
// Given an implicit null-ptr cast or an explicit cast with an implicit
|
// Given an implicit null-ptr cast or an explicit cast with an implicit
|
||||||
// null-to-pointer cast within use CastSequenceVisitor to identify sequences
|
// null-to-pointer cast within use CastSequenceVisitor to identify sequences
|
||||||
// of explicit casts that can be converted into 'nullptr'.
|
// of explicit casts that can be converted into 'nullptr'.
|
||||||
CastSequenceVisitor Visitor(*Result.Context, UserNullMacros, AcceptedChanges,
|
CastSequenceVisitor Visitor(Replace, *Result.Context, UserNullMacros,
|
||||||
Owner);
|
AcceptedChanges, Owner);
|
||||||
Visitor.TraverseStmt(const_cast<CastExpr *>(NullCast));
|
Visitor.TraverseStmt(const_cast<CastExpr *>(NullCast));
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,17 @@ typedef llvm::SmallVector<llvm::StringRef, 1> UserMacroNames;
|
||||||
///
|
///
|
||||||
class NullptrFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
class NullptrFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||||
public:
|
public:
|
||||||
NullptrFixer(unsigned &AcceptedChanges, RiskLevel, Transform &Owner);
|
NullptrFixer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges,
|
||||||
|
RiskLevel, const Transform &Owner);
|
||||||
|
|
||||||
/// \brief Entry point to the callback called when matches are made.
|
/// \brief Entry point to the callback called when matches are made.
|
||||||
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result);
|
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
clang::tooling::Replacements &Replace;
|
||||||
unsigned &AcceptedChanges;
|
unsigned &AcceptedChanges;
|
||||||
UserMacroNames UserNullMacros;
|
UserMacroNames UserNullMacros;
|
||||||
Transform &Owner;
|
const Transform &Owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPP11_MIGRATE_NULLPTR_ACTIONS_H
|
#endif // CPP11_MIGRATE_NULLPTR_ACTIONS_H
|
||||||
|
|
|
@ -24,7 +24,7 @@ using clang::ast_matchers::MatchFinder;
|
||||||
using namespace clang::tooling;
|
using namespace clang::tooling;
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
int UseNullptrTransform::apply(const FileOverrides &InputStates,
|
int UseNullptrTransform::apply(FileOverrides &InputStates,
|
||||||
const CompilationDatabase &Database,
|
const CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) {
|
const std::vector<std::string> &SourcePaths) {
|
||||||
ClangTool UseNullptrTool(Database, SourcePaths);
|
ClangTool UseNullptrTool(Database, SourcePaths);
|
||||||
|
@ -32,7 +32,8 @@ int UseNullptrTransform::apply(const FileOverrides &InputStates,
|
||||||
unsigned AcceptedChanges = 0;
|
unsigned AcceptedChanges = 0;
|
||||||
|
|
||||||
MatchFinder Finder;
|
MatchFinder Finder;
|
||||||
NullptrFixer Fixer(AcceptedChanges, Options().MaxRiskLevel, /*Owner=*/ *this);
|
NullptrFixer Fixer(getReplacements(), AcceptedChanges, Options().MaxRiskLevel,
|
||||||
|
/*Owner=*/ *this);
|
||||||
|
|
||||||
Finder.addMatcher(makeCastSequenceMatcher(), &Fixer);
|
Finder.addMatcher(makeCastSequenceMatcher(), &Fixer);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
: Transform("UseNullptr", Options) {}
|
: Transform("UseNullptr", Options) {}
|
||||||
|
|
||||||
/// \see Transform::run().
|
/// \see Transform::run().
|
||||||
virtual int apply(const FileOverrides &InputStates,
|
virtual int apply(FileOverrides &InputStates,
|
||||||
const clang::tooling::CompilationDatabase &Database,
|
const clang::tooling::CompilationDatabase &Database,
|
||||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,7 +34,6 @@ add_dependencies(cpp11-migrate
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(cpp11-migrate
|
target_link_libraries(cpp11-migrate
|
||||||
clangReplace
|
|
||||||
migrateCore
|
migrateCore
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -21,14 +21,9 @@
|
||||||
#include "Core/Transform.h"
|
#include "Core/Transform.h"
|
||||||
#include "Core/Transforms.h"
|
#include "Core/Transforms.h"
|
||||||
#include "Core/Reformatting.h"
|
#include "Core/Reformatting.h"
|
||||||
#include "clang/Basic/Diagnostic.h"
|
|
||||||
#include "clang/Basic/DiagnosticOptions.h"
|
|
||||||
#include "clang/Basic/SourceManager.h"
|
|
||||||
#include "clang/Frontend/FrontendActions.h"
|
#include "clang/Frontend/FrontendActions.h"
|
||||||
#include "clang/Rewrite/Core/Rewriter.h"
|
|
||||||
#include "clang/Tooling/CommonOptionsParser.h"
|
#include "clang/Tooling/CommonOptionsParser.h"
|
||||||
#include "clang/Tooling/Tooling.h"
|
#include "clang/Tooling/Tooling.h"
|
||||||
#include "clang-replace/Tooling/ApplyReplacements.h"
|
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
@ -127,12 +122,12 @@ static cl::opt<bool, /*ExternalStorage=*/true> EnableHeaderModifications(
|
||||||
cl::location(GlobalOptions.EnableHeaderModifications),
|
cl::location(GlobalOptions.EnableHeaderModifications),
|
||||||
cl::init(false));
|
cl::init(false));
|
||||||
|
|
||||||
static cl::opt<bool>
|
static cl::opt<bool> YAMLOnly("yaml-only",
|
||||||
SerializeReplacements("serialize-replacements",
|
cl::Hidden, // Associated with -headers
|
||||||
cl::Hidden, // Associated with -headers
|
cl::desc("Don't change headers on disk. Write "
|
||||||
cl::desc("Serialize translation unit replacements to "
|
"changes to change description files "
|
||||||
"disk instead of changing files."),
|
"only."),
|
||||||
cl::init(false));
|
cl::init(false));
|
||||||
|
|
||||||
cl::opt<std::string> SupportedCompilers(
|
cl::opt<std::string> SupportedCompilers(
|
||||||
"for-compilers", cl::value_desc("string"),
|
"for-compilers", cl::value_desc("string"),
|
||||||
|
@ -230,68 +225,6 @@ static Reformatter *handleFormatStyle(const char *ProgName, bool &Error) {
|
||||||
return 0;
|
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.
|
|
||||||
bool reformat(Reformatter &ChangesReformatter, const 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 false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rewriter DestRewriter(SM, LangOptions());
|
|
||||||
if (!replace::applyReplacements(GroupedReplacements, DestRewriter)) {
|
|
||||||
llvm::errs() << "Warning: Failed to apply reformatting conflicts!\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return replace::writeFiles(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, const char **argv) {
|
int main(int argc, const char **argv) {
|
||||||
llvm::sys::PrintStackTraceOnErrorSignal();
|
llvm::sys::PrintStackTraceOnErrorSignal();
|
||||||
Transforms TransformManager;
|
Transforms TransformManager;
|
||||||
|
@ -347,15 +280,6 @@ int main(int argc, const char **argv) {
|
||||||
|
|
||||||
TransformManager.createSelectedTransforms(GlobalOptions, RequiredVersions);
|
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 (TransformManager.begin() == TransformManager.end()) {
|
||||||
if (SupportedCompilers.empty())
|
if (SupportedCompilers.empty())
|
||||||
llvm::errs() << argv[0] << ": no selected transforms\n";
|
llvm::errs() << argv[0] << ": no selected transforms\n";
|
||||||
|
@ -365,22 +289,21 @@ int main(int argc, const char **argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If SerializeReplacements is requested, then change reformatting must be
|
if (std::distance(TransformManager.begin(), TransformManager.end()) > 1 &&
|
||||||
// turned off and only one transform should be requested. Reformatting is
|
YAMLOnly) {
|
||||||
// basically another transform so even if there's only one other transform,
|
llvm::errs() << "Header change description files requested for multiple "
|
||||||
// the reformatting pass would make two.
|
|
||||||
if (SerializeReplacements &&
|
|
||||||
(std::distance(TransformManager.begin(), TransformManager.end()) > 1 ||
|
|
||||||
ChangesReformatter)) {
|
|
||||||
llvm::errs() << "Serialization of replacements requested for multiple "
|
|
||||||
"transforms.\nChanges from only one transform can be "
|
"transforms.\nChanges from only one transform can be "
|
||||||
"serialized.\n";
|
"recorded in a change description file.\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if reformatting is enabled we wants to track file changes so that it's
|
||||||
|
// possible to reformat them.
|
||||||
|
bool TrackReplacements = static_cast<bool>(ChangesReformatter);
|
||||||
|
FileOverrides FileStates(TrackReplacements);
|
||||||
SourcePerfData PerfData;
|
SourcePerfData PerfData;
|
||||||
FileOverrides FileStates;
|
|
||||||
|
|
||||||
|
// Apply transforms.
|
||||||
for (Transforms::const_iterator I = TransformManager.begin(),
|
for (Transforms::const_iterator I = TransformManager.begin(),
|
||||||
E = TransformManager.end();
|
E = TransformManager.end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
|
@ -403,67 +326,79 @@ int main(int argc, const char **argv) {
|
||||||
}
|
}
|
||||||
llvm::outs() << "\n";
|
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
|
// Reformat changes if a reformatter is provided.
|
||||||
// replacements. Otherwise reformat changes if reformatting is enabled. If
|
if (ChangesReformatter)
|
||||||
// not enabled or if reformatting fails write un-formated changes to disk
|
for (FileOverrides::const_iterator I = FileStates.begin(),
|
||||||
// instead. reformat() takes care of writing successfully formatted changes.
|
E = FileStates.end();
|
||||||
if (!SerializeReplacements &&
|
I != E; ++I) {
|
||||||
(!ChangesReformatter ||
|
SourceOverrides &Overrides = *I->second;
|
||||||
!reformat(*ChangesReformatter, FileStates, Diagnostics)))
|
ChangesReformatter->reformatChanges(Overrides);
|
||||||
FileStates.writeToDisk(Diagnostics);
|
}
|
||||||
|
|
||||||
if (FinalSyntaxCheck)
|
if (FinalSyntaxCheck)
|
||||||
if (!doSyntaxCheck(*Compilations, SourcePaths, FileStates))
|
if (!doSyntaxCheck(*Compilations, SourcePaths, FileStates))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
// Write results to file.
|
||||||
|
for (FileOverrides::const_iterator I = FileStates.begin(),
|
||||||
|
E = FileStates.end();
|
||||||
|
I != E; ++I) {
|
||||||
|
const SourceOverrides &Overrides = *I->second;
|
||||||
|
if (Overrides.isSourceOverriden()) {
|
||||||
|
std::string ErrorInfo;
|
||||||
|
std::string MainFileName = I->getKey();
|
||||||
|
llvm::raw_fd_ostream FileStream(MainFileName.c_str(), ErrorInfo,
|
||||||
|
llvm::sys::fs::F_Binary);
|
||||||
|
FileStream << Overrides.getMainFileContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (HeaderOverrides::const_iterator HeaderI = Overrides.headers_begin(),
|
||||||
|
HeaderE = Overrides.headers_end();
|
||||||
|
HeaderI != HeaderE; ++HeaderI) {
|
||||||
|
std::string ErrorInfo;
|
||||||
|
if (YAMLOnly) {
|
||||||
|
// Replacements for header files need to be written in a YAML file for
|
||||||
|
// every transform and will be merged together with an external tool.
|
||||||
|
llvm::SmallString<128> ReplacementsHeaderName;
|
||||||
|
llvm::SmallString<64> Error;
|
||||||
|
bool Result =
|
||||||
|
generateReplacementsFileName(I->getKey(), HeaderI->getKey().data(),
|
||||||
|
ReplacementsHeaderName, Error);
|
||||||
|
if (!Result) {
|
||||||
|
llvm::errs() << "Failed to generate replacements filename:" << Error
|
||||||
|
<< "\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::raw_fd_ostream ReplacementsFile(
|
||||||
|
ReplacementsHeaderName.c_str(), ErrorInfo, llvm::sys::fs::F_Binary);
|
||||||
|
if (!ErrorInfo.empty()) {
|
||||||
|
llvm::errs() << "Error opening file: " << ErrorInfo << "\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
llvm::yaml::Output YAML(ReplacementsFile);
|
||||||
|
YAML << const_cast<TranslationUnitReplacements &>(
|
||||||
|
HeaderI->getValue().getReplacements());
|
||||||
|
} else {
|
||||||
|
// If -yaml-only was not specified, then change headers on disk.
|
||||||
|
// FIXME: This is transitional behaviour. Remove this functionality
|
||||||
|
// when header change description tool is ready.
|
||||||
|
assert(!HeaderI->second.getContentOverride().empty() &&
|
||||||
|
"A header override should not be empty");
|
||||||
|
std::string HeaderFileName = HeaderI->getKey();
|
||||||
|
llvm::raw_fd_ostream HeaderStream(HeaderFileName.c_str(), ErrorInfo,
|
||||||
|
llvm::sys::fs::F_Binary);
|
||||||
|
if (!ErrorInfo.empty()) {
|
||||||
|
llvm::errs() << "Error opening file: " << ErrorInfo << "\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
HeaderStream << HeaderI->second.getContentOverride();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Report execution times.
|
// Report execution times.
|
||||||
if (GlobalOptions.EnableTiming && !PerfData.empty()) {
|
if (GlobalOptions.EnableTiming && !PerfData.empty()) {
|
||||||
std::string DirectoryName = TimingDirectoryName;
|
std::string DirectoryName = TimingDirectoryName;
|
||||||
|
|
|
@ -36,14 +36,14 @@ SOURCES += $(addprefix ../ReplaceAutoPtr/,$(notdir $(wildcard $(PROJ_SRC_DIR)/..
|
||||||
BUILT_SOURCES += $(ObjDir)/../ReplaceAutoPtr/.objdir
|
BUILT_SOURCES += $(ObjDir)/../ReplaceAutoPtr/.objdir
|
||||||
|
|
||||||
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc mcparser option
|
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc mcparser option
|
||||||
USEDLIBS = migrateCore.a clangFormat.a clangReplace.a clangTooling.a clangFrontend.a \
|
USEDLIBS = migrateCore.a clangFormat.a clangTooling.a clangFrontend.a \
|
||||||
clangSerialization.a clangDriver.a clangRewriteFrontend.a \
|
clangSerialization.a clangDriver.a clangRewriteFrontend.a \
|
||||||
clangRewriteCore.a clangParse.a clangSema.a clangAnalysis.a \
|
clangRewriteCore.a clangParse.a clangSema.a clangAnalysis.a \
|
||||||
clangAST.a clangASTMatchers.a clangEdit.a clangLex.a clangBasic.a
|
clangAST.a clangASTMatchers.a clangEdit.a clangLex.a clangBasic.a
|
||||||
|
|
||||||
include $(CLANG_LEVEL)/Makefile
|
include $(CLANG_LEVEL)/Makefile
|
||||||
|
|
||||||
CPP.Flags += -I$(PROJ_SRC_DIR)/.. -I$(PROJ_SRC_DIR)/../../clang-replace/include
|
CPP.Flags += -I$(PROJ_SRC_DIR)/..
|
||||||
|
|
||||||
# BUILT_SOURCES gets used as a prereq for many top-level targets. However, at
|
# 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
|
# the point those targets are defined, $(ObjDir) hasn't been defined and so the
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
void update(int (&arr)[10]) {
|
|
||||||
int val = 1;
|
|
||||||
for (unsigned i = 0; i < sizeof(arr)/sizeof(int); ++i) {
|
|
||||||
arr[i] = val++;
|
|
||||||
// CHECK: for (auto & elem : arr) {
|
|
||||||
// CHECK-NEXT: elem = val++;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,12 @@
|
||||||
---
|
---
|
||||||
MainSourceFile: "$(path)/main.cpp"
|
MainSourceFile: "$(path)/main.cpp"
|
||||||
Replacements:
|
Replacements:
|
||||||
- FilePath: "$(path)/common.h"
|
|
||||||
Offset: 506
|
|
||||||
Length: 2
|
|
||||||
ReplacementText: "elem"
|
|
||||||
- FilePath: "$(path)/common.h"
|
- FilePath: "$(path)/common.h"
|
||||||
Offset: 432
|
Offset: 432
|
||||||
Length: 61
|
Length: 61
|
||||||
ReplacementText: "(auto & elem : C)"
|
ReplacementText: "(auto & elem : C)"
|
||||||
|
- FilePath: "$(path)/common.h"
|
||||||
|
Offset: 506
|
||||||
|
Length: 2
|
||||||
|
ReplacementText: "elem"
|
||||||
...
|
...
|
|
@ -1,20 +0,0 @@
|
||||||
---
|
|
||||||
MainSourceFile: "$(path)/common.cpp"
|
|
||||||
Replacements:
|
|
||||||
- FilePath: "$(path)/common.h"
|
|
||||||
Offset: 506
|
|
||||||
Length: 2
|
|
||||||
ReplacementText: "elem"
|
|
||||||
- FilePath: "$(path)/common.h"
|
|
||||||
Offset: 432
|
|
||||||
Length: 61
|
|
||||||
ReplacementText: "(auto & elem : C)"
|
|
||||||
- FilePath: "$(path)/common.cpp"
|
|
||||||
Offset: 289
|
|
||||||
Length: 2
|
|
||||||
ReplacementText: "elem"
|
|
||||||
- FilePath: "$(path)/common.cpp"
|
|
||||||
Offset: 206
|
|
||||||
Length: 63
|
|
||||||
ReplacementText: "(auto & elem : C1)"
|
|
||||||
...
|
|
|
@ -1,30 +1,44 @@
|
||||||
// The following block tests the following:
|
// The following block tests the following:
|
||||||
// - Only 1 file is generated per translation unit
|
// - Only 1 file is generated per translation unit and header file
|
||||||
// - Replacements are written in YAML that matches the expected YAML file
|
// - Replacements are written in YAML that matches the expected YAML file
|
||||||
// The test is run in %T/SerializeTest so it's easy to create a clean test
|
// RUN: rm -rf %t/Test
|
||||||
// directory.
|
// RUN: mkdir -p %t/Test
|
||||||
//
|
// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %t/Test
|
||||||
// RUN: rm -rf %T/SerializeTest
|
// RUN: cpp11-migrate -loop-convert -headers -yaml-only -include=%t/Test %t/Test/main.cpp %t/Test/common.cpp --
|
||||||
// RUN: mkdir -p %T/SerializeTest
|
// Check that only 1 file is generated per translation unit and header file.
|
||||||
// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %T/SerializeTest
|
// RUN: ls -1 %t/Test | FileCheck %s --check-prefix=MAIN_CPP
|
||||||
// RUN: cpp11-migrate -loop-convert -headers -serialize-replacements -include=%T/SerializeTest %T/SerializeTest/main.cpp %T/SerializeTest/common.cpp --
|
// RUN: ls -1 %t/Test | FileCheck %s --check-prefix=COMMON_CPP
|
||||||
// Check that only 1 file is generated per translation unit
|
// RUN: cp %S/common.h.yaml %t/Test/main.cpp_common.h.yaml
|
||||||
// RUN: ls -1 %T/SerializeTest | FileCheck %s --check-prefix=MAIN_CPP
|
|
||||||
// RUN: ls -1 %T/SerializeTest | FileCheck %s --check-prefix=COMMON_CPP
|
|
||||||
// We need to put the build path to the expected YAML file to diff against the generated one.
|
// We need to put the build path to the expected YAML file to diff against the generated one.
|
||||||
// RUN: sed -e 's#$(path)#%/T/SerializeTest#g' %S/main_expected.yaml > %T/SerializeTest/main_expected.yaml
|
// RUN: sed -e 's#$(path)#%/t/Test#g' %S/common.h.yaml > %t/Test/main.cpp_common.h.yaml
|
||||||
// RUN: sed -i -e 's#\\#/#g' %T/SerializeTest/main.cpp_*.yaml
|
// RUN: sed -i -e 's#\\#/#g' %t/Test/main.cpp_common.h_*.yaml
|
||||||
// RUN: diff -b %T/SerializeTest/main_expected.yaml %T/SerializeTest/main.cpp_*.yaml
|
// RUN: diff -b %t/Test/main.cpp_common.h.yaml %t/Test/main.cpp_common.h_*.yaml
|
||||||
// RUN: sed -e 's#$(path)#%/T/SerializeTest#g' %S/common_expected.yaml > %T/SerializeTest/common_expected.yaml
|
// RUN: sed -e 's#$(path)#%/t/Test#g' -e 's#main.cpp"#common.cpp"#g' %S/common.h.yaml > %t/Test/common.cpp_common.h.yaml
|
||||||
// RUN: sed -i -e 's#\\#/#g' %T/SerializeTest/common.cpp_*.yaml
|
// RUN: sed -i -e 's#\\#/#g' %t/Test/common.cpp_common.h_*.yaml
|
||||||
// RUN: diff -b %T/SerializeTest/common_expected.yaml %T/SerializeTest/common.cpp_*.yaml
|
// RUN: diff -b %t/Test/common.cpp_common.h.yaml %t/Test/common.cpp_common.h_*.yaml
|
||||||
//
|
//
|
||||||
// The following are for FileCheck when used on output of 'ls'. See above.
|
// The following block tests the following:
|
||||||
// MAIN_CPP: {{^main.cpp_.*.yaml$}}
|
// - YAML files are written only when -headers is used
|
||||||
// MAIN_CPP-NOT: {{main.cpp_.*.yaml}}
|
// RUN: rm -rf %t/Test
|
||||||
|
// RUN: mkdir -p %t/Test
|
||||||
|
// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %t/Test
|
||||||
|
// RUN: cpp11-migrate -loop-convert -headers -yaml-only -include=%t/Test %t/Test/main.cpp --
|
||||||
|
// RUN: cpp11-migrate -loop-convert %t/Test/common.cpp --
|
||||||
|
// Check that only one YAML file is generated from main.cpp and common.h and not from common.cpp and common.h since -header is not specified
|
||||||
|
// RUN: ls -1 %t/Test | FileCheck %s --check-prefix=MAIN_CPP
|
||||||
|
// RUN: ls -1 %t/Test | FileCheck %s --check-prefix=NO_COMMON
|
||||||
|
// We need to put the build path to the expected YAML file to diff against the generated one.
|
||||||
|
// RUN: sed -e 's#$(path)#%/t/Test#g' %S/common.h.yaml > %t/Test/main.cpp_common.h.yaml
|
||||||
|
// RUN: sed -i -e 's#\\#/#g' %t/Test/main.cpp_common.h_*.yaml
|
||||||
|
// RUN: diff -b %t/Test/main.cpp_common.h.yaml %t/Test/main.cpp_common.h_*.yaml
|
||||||
//
|
//
|
||||||
// COMMON_CPP: {{^common.cpp_.*.yaml$}}
|
// MAIN_CPP: {{^main.cpp_common.h_.*.yaml$}}
|
||||||
// COMMON_CPP-NOT: {{common.cpp_.*.yaml}}
|
// MAIN_CPP-NOT: {{main.cpp_common.h_.*.yaml}}
|
||||||
|
//
|
||||||
|
// COMMON_CPP: {{^common.cpp_common.h_.*.yaml$}}
|
||||||
|
// COMMON_CPP-NOT: {{common.cpp_common.h_.*.yaml}}
|
||||||
|
//
|
||||||
|
// NO_COMMON-NOT: {{common.cpp_common.h_.*.yaml}}
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
// Ensure that if -serialize-replacements is not provided, no serialized
|
|
||||||
// replacement files should be generated and the changes are made directly.
|
|
||||||
//
|
|
||||||
// RUN: mkdir -p %T/Inputs
|
|
||||||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
|
|
||||||
// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/no_yaml.h > %T/Inputs/no_yaml.h
|
|
||||||
// RUN: cpp11-migrate -loop-convert %t.cpp -headers -include=%T/Inputs -- -I %T/Inputs/no_yaml.h
|
|
||||||
// RUN: FileCheck --input-file=%t.cpp %s
|
|
||||||
// RUN: FileCheck --input-file=%T/Inputs/no_yaml.h %S/Inputs/no_yaml.h
|
|
||||||
// RUN: ls -1 %T | FileCheck %s --check-prefix=NO_YAML
|
|
||||||
//
|
|
||||||
// NO_YAML-NOT: {{no_yaml.cpp_.*.yaml}}
|
|
||||||
#include "Inputs/no_yaml.h"
|
|
||||||
|
|
||||||
void func() {
|
|
||||||
int arr[10];
|
|
||||||
for (unsigned i = 0; i < sizeof(arr)/sizeof(int); ++i) {
|
|
||||||
arr[i] = 0;
|
|
||||||
// CHECK: for (auto & elem : arr) {
|
|
||||||
// CHECK-NEXT: elem = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
update(arr);
|
|
||||||
}
|
|
|
@ -1,31 +1,26 @@
|
||||||
set(LLVM_LINK_COMPONENTS
|
set(LLVM_LINK_COMPONENTS
|
||||||
support
|
support
|
||||||
)
|
)
|
||||||
|
|
||||||
get_filename_component(CPP11_MIGRATE_SOURCE_DIR
|
get_filename_component(CPP11_MIGRATE_SOURCE_DIR
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../cpp11-migrate REALPATH)
|
${CMAKE_CURRENT_SOURCE_DIR}/../../cpp11-migrate REALPATH)
|
||||||
get_filename_component(ClangReplaceLocation
|
include_directories(${CPP11_MIGRATE_SOURCE_DIR})
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../clang-replace/include" REALPATH)
|
|
||||||
include_directories(
|
add_extra_unittest(Cpp11MigrateTests
|
||||||
${CPP11_MIGRATE_SOURCE_DIR}
|
FileOverridesTest.cpp
|
||||||
${ClangReplaceLocation}
|
ReformattingTest.cpp
|
||||||
)
|
IncludeExcludeTest.cpp
|
||||||
|
PerfSupportTest.cpp
|
||||||
add_extra_unittest(Cpp11MigrateTests
|
TransformTest.cpp
|
||||||
FileOverridesTest.cpp
|
UniqueHeaderNameTest.cpp
|
||||||
ReformattingTest.cpp
|
IncludeDirectivesTest.cpp
|
||||||
IncludeExcludeTest.cpp
|
)
|
||||||
PerfSupportTest.cpp
|
|
||||||
TransformTest.cpp
|
target_link_libraries(Cpp11MigrateTests
|
||||||
UniqueHeaderNameTest.cpp
|
migrateCore
|
||||||
IncludeDirectivesTest.cpp
|
clangFormat
|
||||||
)
|
clangTooling
|
||||||
|
clangBasic
|
||||||
target_link_libraries(Cpp11MigrateTests
|
clangASTMatchers
|
||||||
migrateCore
|
clangRewriteFrontend
|
||||||
clangFormat
|
)
|
||||||
clangTooling
|
|
||||||
clangBasic
|
|
||||||
clangASTMatchers
|
|
||||||
clangRewriteFrontend
|
|
||||||
)
|
|
||||||
|
|
|
@ -8,34 +8,56 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "Core/FileOverrides.h"
|
#include "Core/FileOverrides.h"
|
||||||
#include "Core/Refactoring.h"
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "VirtualFileHelper.h"
|
#include "VirtualFileHelper.h"
|
||||||
#include "clang/Rewrite/Core/Rewriter.h"
|
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace clang::tooling;
|
using namespace clang::tooling;
|
||||||
|
|
||||||
static Replacement makeReplacement(unsigned Offset, unsigned Length,
|
TEST(SourceOverridesTest, Interface) {
|
||||||
unsigned ReplacementLength,
|
llvm::StringRef FileName = "<test-file>";
|
||||||
llvm::StringRef FilePath) {
|
VirtualFileHelper VFHelper;
|
||||||
return Replacement(FilePath, Offset, Length,
|
VFHelper.mapFile(
|
||||||
std::string(ReplacementLength, '~'));
|
FileName,
|
||||||
|
"std::vector<such_a_long_name_for_a_type>::const_iterator long_type =\n"
|
||||||
|
" vec.begin();\n");
|
||||||
|
SourceOverrides Overrides(FileName, /*TrackFileChanges=*/false);
|
||||||
|
|
||||||
|
EXPECT_EQ(FileName, Overrides.getMainFileName());
|
||||||
|
EXPECT_FALSE(Overrides.isSourceOverriden());
|
||||||
|
EXPECT_FALSE(Overrides.isTrackingFileChanges());
|
||||||
|
|
||||||
|
Replacements Replaces;
|
||||||
|
unsigned ReplacementLength =
|
||||||
|
strlen("std::vector<such_a_long_name_for_a_type>::const_iterator");
|
||||||
|
Replaces.insert(
|
||||||
|
Replacement(FileName, 0, ReplacementLength, "auto"));
|
||||||
|
Overrides.applyReplacements(Replaces, VFHelper.getNewSourceManager());
|
||||||
|
EXPECT_TRUE(Overrides.isSourceOverriden());
|
||||||
|
|
||||||
|
std::string ExpectedContent = "auto long_type =\n"
|
||||||
|
" vec.begin();\n";
|
||||||
|
EXPECT_EQ(ExpectedContent, Overrides.getMainFileContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
Replacement makeReplacement(unsigned Offset, unsigned Length,
|
||||||
|
unsigned ReplacementLength) {
|
||||||
|
return Replacement("", Offset, Length, std::string(ReplacementLength, '~'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a set of replacements containing one element
|
// generate a set of replacements containing one element
|
||||||
static ReplacementsVec makeReplacements(unsigned Offset, unsigned Length,
|
Replacements makeReplacements(unsigned Offset, unsigned Length,
|
||||||
unsigned ReplacementLength,
|
unsigned ReplacementLength) {
|
||||||
llvm::StringRef FilePath = "~") {
|
Replacements Replaces;
|
||||||
ReplacementsVec Replaces;
|
Replaces.insert(makeReplacement(Offset, Length, ReplacementLength));
|
||||||
Replaces.push_back(
|
|
||||||
makeReplacement(Offset, Length, ReplacementLength, FilePath));
|
|
||||||
return Replaces;
|
return Replaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool equalRanges(Range A, Range B) {
|
bool equalRanges(Range A, Range B) {
|
||||||
return A.getOffset() == B.getOffset() && A.getLength() == B.getLength();
|
return A.getOffset() == B.getOffset() && A.getLength() == B.getLength();
|
||||||
}
|
}
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
TEST(ChangedRangesTest, adjustChangedRangesShrink) {
|
TEST(ChangedRangesTest, adjustChangedRangesShrink) {
|
||||||
ChangedRanges Changes;
|
ChangedRanges Changes;
|
||||||
|
@ -117,71 +139,3 @@ TEST(ChangedRangesTest, adjustChangedRangesRangeResized) {
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
|
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());
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ include $(CLANG_LEVEL)/../../Makefile.config
|
||||||
TESTNAME = Cpp11MigrateTests
|
TESTNAME = Cpp11MigrateTests
|
||||||
LINK_COMPONENTS := asmparser bitreader support MC MCParser option \
|
LINK_COMPONENTS := asmparser bitreader support MC MCParser option \
|
||||||
TransformUtils
|
TransformUtils
|
||||||
USEDLIBS = migrateCore.a clangFormat.a clangReplace.a clangTooling.a clangFrontend.a \
|
USEDLIBS = migrateCore.a clangFormat.a clangTooling.a clangFrontend.a \
|
||||||
clangSerialization.a clangDriver.a clangRewriteFrontend.a \
|
clangSerialization.a clangDriver.a clangRewriteFrontend.a \
|
||||||
clangRewriteCore.a clangParse.a clangSema.a clangAnalysis.a \
|
clangRewriteCore.a clangParse.a clangSema.a clangAnalysis.a \
|
||||||
clangAST.a clangASTMatchers.a clangEdit.a clangLex.a \
|
clangAST.a clangASTMatchers.a clangEdit.a clangLex.a \
|
||||||
|
@ -21,5 +21,5 @@ USEDLIBS = migrateCore.a clangFormat.a clangReplace.a clangTooling.a clangFronte
|
||||||
|
|
||||||
include $(CLANG_LEVEL)/Makefile
|
include $(CLANG_LEVEL)/Makefile
|
||||||
MAKEFILE_UNITTEST_NO_INCLUDE_COMMON := 1
|
MAKEFILE_UNITTEST_NO_INCLUDE_COMMON := 1
|
||||||
CPP.Flags += -I$(PROJ_SRC_DIR)/../../cpp11-migrate -I$(PROJ_SRC_DIR)/../../clang-replace/include
|
CPP.Flags += -I$(PROJ_SRC_DIR)/../../cpp11-migrate
|
||||||
include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
|
include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
|
||||||
|
|
|
@ -18,7 +18,7 @@ public:
|
||||||
TransformA(const TransformOptions &Options)
|
TransformA(const TransformOptions &Options)
|
||||||
: Transform("TransformA", Options) {}
|
: Transform("TransformA", Options) {}
|
||||||
|
|
||||||
virtual int apply(const FileOverrides &,
|
virtual int apply(FileOverrides &,
|
||||||
const tooling::CompilationDatabase &,
|
const tooling::CompilationDatabase &,
|
||||||
const std::vector<std::string> &) {
|
const std::vector<std::string> &) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -34,7 +34,7 @@ public:
|
||||||
TransformB(const TransformOptions &Options)
|
TransformB(const TransformOptions &Options)
|
||||||
: Transform("TransformB", Options) {}
|
: Transform("TransformB", Options) {}
|
||||||
|
|
||||||
virtual int apply(const FileOverrides &,
|
virtual int apply(FileOverrides &,
|
||||||
const tooling::CompilationDatabase &,
|
const tooling::CompilationDatabase &,
|
||||||
const std::vector<std::string> &) {
|
const std::vector<std::string> &) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#include "Core/Reformatting.h"
|
#include "Core/Reformatting.h"
|
||||||
#include "Core/FileOverrides.h"
|
#include "Core/FileOverrides.h"
|
||||||
#include "Core/Refactoring.h"
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "VirtualFileHelper.h"
|
#include "VirtualFileHelper.h"
|
||||||
|
|
||||||
|
@ -20,9 +19,9 @@ namespace {
|
||||||
// convenience function to create a ChangedRanges containing one Range
|
// convenience function to create a ChangedRanges containing one Range
|
||||||
ChangedRanges makeChangedRanges(unsigned Offset, unsigned Length) {
|
ChangedRanges makeChangedRanges(unsigned Offset, unsigned Length) {
|
||||||
ChangedRanges Changes;
|
ChangedRanges Changes;
|
||||||
ReplacementsVec Replaces;
|
Replacements Replaces;
|
||||||
|
|
||||||
Replaces.push_back(Replacement("", Offset, 0, std::string(Length, '~')));
|
Replaces.insert(Replacement("", Offset, 0, std::string(Length, '~')));
|
||||||
Changes.adjustChangedRanges(Replaces);
|
Changes.adjustChangedRanges(Replaces);
|
||||||
return Changes;
|
return Changes;
|
||||||
}
|
}
|
||||||
|
@ -36,20 +35,16 @@ TEST(Reformatter, SingleReformat) {
|
||||||
|
|
||||||
Reformatter ChangesReformatter(format::getLLVMStyle());
|
Reformatter ChangesReformatter(format::getLLVMStyle());
|
||||||
ChangedRanges Changes = makeChangedRanges(0, 6);
|
ChangedRanges Changes = makeChangedRanges(0, 6);
|
||||||
tooling::ReplacementsVec Replaces;
|
tooling::Replacements Replaces = ChangesReformatter.reformatSingleFile(
|
||||||
ChangesReformatter.reformatSingleFile(
|
FileName, Changes, VFHelper.getNewSourceManager());
|
||||||
FileName, Changes, VFHelper.getNewSourceManager(), Replaces);
|
|
||||||
|
|
||||||
// We expect the code above to reformatted like so:
|
SourceOverrides Overrides(FileName, /*TrackChanges=*/false);
|
||||||
//
|
Overrides.applyReplacements(Replaces, VFHelper.getNewSourceManager());
|
||||||
// int a;
|
|
||||||
// int b;
|
std::string Expected, Result;
|
||||||
//
|
|
||||||
// This test is slightly fragile since there's more than one Replacement that
|
Expected = "int a;\n"
|
||||||
// results in the above change. However, testing the result of applying the
|
"int b;\n";
|
||||||
// replacement is more trouble than it's worth in this context.
|
Result = Overrides.getMainFileContent();
|
||||||
ASSERT_EQ(1u, Replaces.size());
|
EXPECT_EQ(Expected, Result);
|
||||||
EXPECT_EQ(3u, Replaces[0].getOffset());
|
|
||||||
EXPECT_EQ(2u, Replaces[0].getLength());
|
|
||||||
EXPECT_EQ(" ", Replaces[0].getReplacementText());
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
DummyTransform(llvm::StringRef Name, const TransformOptions &Options)
|
DummyTransform(llvm::StringRef Name, const TransformOptions &Options)
|
||||||
: Transform(Name, Options) {}
|
: Transform(Name, Options) {}
|
||||||
|
|
||||||
virtual int apply(const FileOverrides &,
|
virtual int apply(FileOverrides &,
|
||||||
const tooling::CompilationDatabase &,
|
const tooling::CompilationDatabase &,
|
||||||
const std::vector<std::string> &) { return 0; }
|
const std::vector<std::string> &) { return 0; }
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ TEST(Transform, Timings) {
|
||||||
|
|
||||||
// Transform's handle* functions require FileOverrides to be set, even if
|
// Transform's handle* functions require FileOverrides to be set, even if
|
||||||
// there aren't any.
|
// there aren't any.
|
||||||
FileOverrides Overrides;
|
FileOverrides Overrides(/*TrackFileChanges=*/false);
|
||||||
T.setOverrides(Overrides);
|
T.setOverrides(Overrides);
|
||||||
|
|
||||||
Tool.run(clang::tooling::newFrontendActionFactory(&Factory, &Callbacks));
|
Tool.run(clang::tooling::newFrontendActionFactory(&Factory, &Callbacks));
|
||||||
|
|
|
@ -28,31 +28,34 @@ TEST(UniqueHeaderName, testUniqueHeaderName) {
|
||||||
append(SourceFile, "project/lib/feature.cpp");
|
append(SourceFile, "project/lib/feature.cpp");
|
||||||
native(SourceFile.str().str(), SourceFile);
|
native(SourceFile.str().str(), SourceFile);
|
||||||
|
|
||||||
llvm::SmallString<128> FullActualPath;
|
llvm::SmallString<128> HeaderFile(TmpDir);
|
||||||
|
append(HeaderFile, "project/include/feature.h");
|
||||||
|
native(HeaderFile.str().str(), HeaderFile);
|
||||||
|
|
||||||
|
llvm::SmallString<128> ExpectedName("^feature.cpp_feature.h_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}.yaml$");
|
||||||
|
|
||||||
|
llvm::SmallString<128> ActualName;
|
||||||
llvm::SmallString<128> Error;
|
llvm::SmallString<128> Error;
|
||||||
bool Result =
|
bool Result =
|
||||||
generateReplacementsFileName(SourceFile, FullActualPath, Error);
|
generateReplacementsFileName(SourceFile, HeaderFile, ActualName, Error);
|
||||||
|
|
||||||
ASSERT_TRUE(Result);
|
ASSERT_TRUE(Result);
|
||||||
EXPECT_TRUE(Error.empty());
|
EXPECT_TRUE(Error.empty());
|
||||||
|
|
||||||
// We need to check the directory name and filename separately since on
|
// We need to check the directory name and filename separately since on
|
||||||
// Windows, the path separator is '\' which is a regex escape character.
|
// Windows, the path separator is '\' which is a regex escape character.
|
||||||
llvm::SmallString<128> ExpectedPath =
|
llvm::SmallString<128> ExpectedHeaderPath =
|
||||||
llvm::sys::path::parent_path(SourceFile);
|
llvm::sys::path::parent_path(HeaderFile);
|
||||||
llvm::SmallString<128> ActualPath =
|
llvm::SmallString<128> ActualHeaderPath =
|
||||||
llvm::sys::path::parent_path(FullActualPath);
|
llvm::sys::path::parent_path(ActualName);
|
||||||
llvm::SmallString<128> ActualName =
|
llvm::SmallString<128> ActualHeaderName =
|
||||||
llvm::sys::path::filename(FullActualPath);
|
llvm::sys::path::filename(ActualName);
|
||||||
|
|
||||||
EXPECT_STREQ(ExpectedPath.c_str(), ActualPath.c_str());
|
EXPECT_STREQ(ExpectedHeaderPath.c_str(), ActualHeaderPath.c_str());
|
||||||
|
|
||||||
llvm::StringRef ExpectedName =
|
|
||||||
"^feature.cpp_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_["
|
|
||||||
"0-9a-f]{2}_[0-9a-f]{2}.yaml$";
|
|
||||||
llvm::Regex R(ExpectedName);
|
llvm::Regex R(ExpectedName);
|
||||||
ASSERT_TRUE(R.match(ActualName))
|
ASSERT_TRUE(R.match(ActualHeaderName))
|
||||||
<< "ExpectedName: " << ExpectedName.data()
|
<< "ExpectedName: " << ExpectedName.c_str()
|
||||||
<< "\nActualName: " << ActualName.c_str();
|
<< "\nActualName: " << ActualName.c_str();
|
||||||
ASSERT_TRUE(Error.empty()) << "Error: " << Error.c_str();
|
ASSERT_TRUE(Error.empty()) << "Error: " << Error.c_str();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue