summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/cpp11-migrate/Core
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/cpp11-migrate/Core')
-rw-r--r--clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp227
-rw-r--r--clang-tools-extra/cpp11-migrate/Core/FileOverrides.h202
-rw-r--r--clang-tools-extra/cpp11-migrate/Core/Makefile2
-rw-r--r--clang-tools-extra/cpp11-migrate/Core/Refactoring.h31
-rw-r--r--clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp46
-rw-r--r--clang-tools-extra/cpp11-migrate/Core/Reformatting.h40
-rw-r--r--clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp4
-rw-r--r--clang-tools-extra/cpp11-migrate/Core/Transform.cpp28
-rw-r--r--clang-tools-extra/cpp11-migrate/Core/Transform.h31
9 files changed, 396 insertions, 215 deletions
diff --git a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp
index 7ab7e91c30c..d8d4b3f27e1 100644
--- a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp
+++ b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp
@@ -29,14 +29,157 @@
using namespace clang;
using namespace clang::tooling;
-bool generateReplacementsFileName(const llvm::StringRef MainSourceFile,
- llvm::SmallVectorImpl<char> &Result,
- llvm::SmallVectorImpl<char> &Error) {
+void HeaderOverride::recordReplacements(
+ const clang::tooling::Replacements &Replaces) {
+ 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;
+ 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();
- if (llvm::error_code EC = fs::createUniqueFile(
- MainSourceFile + "_%%_%%_%%_%%_%%_%%.yaml", Result)) {
+ if (llvm::error_code EC =
+ fs::createUniqueFile(HeaderPath.c_str(), Result)) {
Error.append(EC.message().begin(), EC.message().end());
return false;
}
@@ -44,6 +187,20 @@ bool generateReplacementsFileName(const llvm::StringRef MainSourceFile,
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 {
/// \brief Comparator to be able to order tooling::Range based on their offset.
@@ -90,11 +247,10 @@ struct RangeReplacedAdjuster {
} // end anonymous namespace
-void
-ChangedRanges::adjustChangedRanges(const tooling::ReplacementsVec &Replaces) {
+void ChangedRanges::adjustChangedRanges(const tooling::Replacements &Replaces) {
// first adjust existing ranges in case they overlap with the replacements
- for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end();
- I != E; ++I) {
+ for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E;
+ ++I) {
const tooling::Replacement &Replace = *I;
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
- for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end();
- I != E; ++I) {
+ for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E;
+ ++I) {
const tooling::Replacement &R = *I;
unsigned Offset = tooling::shiftedCodePosition(Replaces, R.getOffset());
unsigned Length = R.getReplacementText().size();
@@ -147,52 +303,3 @@ void ChangedRanges::coalesceRanges() {
std::mem_fun_ref(&Range::contains)),
Ranges.end());
}
-
-void FileOverrides::applyOverrides(clang::SourceManager &SM) const {
- FileManager &FM = SM.getFileManager();
-
- for (FileStateMap::const_iterator I = FileStates.begin(),
- E = FileStates.end();
- I != E; ++I) {
- SM.overrideFileContents(FM.getFile(I->getKey()),
- llvm::MemoryBuffer::getMemBuffer(I->getValue()));
- }
-}
-
-void FileOverrides::adjustChangedRanges(
- const clang::replace::FileToReplacementsMap &Replaces) {
-
- for (replace::FileToReplacementsMap::const_iterator I = Replaces.begin(),
- E = Replaces.end(); I != E; ++I) {
- ChangeTracking[I->getKey()].adjustChangedRanges(I->getValue());
- }
-}
-
-void FileOverrides::updateState(const clang::Rewriter &Rewrites) {
- for (Rewriter::const_buffer_iterator BufferI = Rewrites.buffer_begin(),
- BufferE = Rewrites.buffer_end();
- BufferI != BufferE; ++BufferI) {
- const char *FileName =
- Rewrites.getSourceMgr().getFileEntryForID(BufferI->first)->getName();
- const RewriteBuffer &RewriteBuf = BufferI->second;
- FileStates[FileName].assign(RewriteBuf.begin(), RewriteBuf.end());
- }
-}
-
-bool FileOverrides::writeToDisk(DiagnosticsEngine &Diagnostics) const {
- bool Errors = false;
- for (FileStateMap::const_iterator I = FileStates.begin(),
- E = FileStates.end();
- I != E; ++I) {
- std::string ErrorInfo;
- // The extra transform through std::string is to ensure null-termination
- // of the filename stored as the key of the StringMap.
- llvm::raw_fd_ostream FileStream(I->getKey().str().c_str(), ErrorInfo);
- if (!ErrorInfo.empty()) {
- llvm::errs() << "Failed to write new state for " << I->getKey() << ".\n";
- Errors = true;
- }
- FileStream << I->getValue();
- }
- return !Errors;
-}
diff --git a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h
index 8cde7591303..3e81abc6d34 100644
--- a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h
+++ b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h
@@ -16,8 +16,7 @@
#ifndef CPP11_MIGRATE_FILE_OVERRIDES_H
#define CPP11_MIGRATE_FILE_OVERRIDES_H
-#include "Core/Refactoring.h"
-#include "clang-replace/Tooling/ApplyReplacements.h"
+#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/ReplacementsYaml.h"
#include "llvm/ADT/StringMap.h"
@@ -45,13 +44,13 @@ public:
/// to remove replaced parts.
///
/// 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.
- /// \{
+ /// @{
const_iterator begin() const { return Ranges.begin(); }
const_iterator end() const { return Ranges.end(); }
- /// \}
+ /// @}
private:
void coalesceRanges();
@@ -59,71 +58,178 @@ private:
RangeVec Ranges;
};
-/// \brief Maintains current state of transformed files and tracks source ranges
-/// where changes have been made.
-class FileOverrides {
+/// \brief Container for storing override information for a single headers.
+class HeaderOverride {
public:
- /// \brief Maps file names to file contents.
- typedef llvm::StringMap<std::string> FileStateMap;
+ /// \brief Constructors.
+ /// @{
+ HeaderOverride() {}
+ HeaderOverride(llvm::StringRef HeaderPath,
+ llvm::StringRef MainSourceFile) : HeaderPath(HeaderPath) {
+ Replacements.MainSourceFile = MainSourceFile;
+ }
+ /// @}
- /// \brief Maps file names to change tracking info for a file.
- typedef llvm::StringMap<ChangedRanges> ChangeMap;
+ /// \brief Getter for HeaderPath.
+ llvm::StringRef getHeaderPath() const {
+ return HeaderPath;
+ }
+ /// \brief Accessor for ContentOverride.
+ /// @{
+ llvm::StringRef getContentOverride() const { return ContentOverride; }
+ void setContentOverride(const llvm::StringRef S) { ContentOverride = S; }
+ /// @}
- /// \brief Override file contents seen by \c SM for all files stored by this
- /// object.
- void applyOverrides(clang::SourceManager &SM) const;
+ /// \brief Getter for Changes.
+ const ChangedRanges &getChanges() const { return Changes; }
- /// \brief Update change tracking information based on replacements stored in
- /// \c Replaces.
- void
- adjustChangedRanges(const clang::replace::FileToReplacementsMap &Replaces);
+ /// \brief Swaps the content of ContentOverride with \p S.
+ void swapContentOverride(std::string &S) { ContentOverride.swap(S); }
- /// \brief Accessor for change tracking information.
- const ChangeMap &getChangedRanges() const {
- return ChangeTracking;
+ /// \brief Getter for Replacements.
+ const clang::tooling::TranslationUnitReplacements &getReplacements() const {
+ return Replacements;
}
- /// \brief Coalesce changes stored in \c Rewrites and replace file contents
- /// overrides stored in this object.
+ /// \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:
+ std::string ContentOverride;
+ 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?
///
- /// \param Rewrites Rewriter containing changes to files.
- void updateState(const clang::Rewriter &Rewrites);
+ /// Tracking file changes can be useful to reformat the code for example.
+ bool isTrackingFileChanges() const { return TrackChanges; }
+ /// @}
- /// \brief Accessor for current file state.
- const FileStateMap &getState() const { return FileStates; }
+ /// \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 Write all file contents overrides to disk.
+ /// \brief Override the file contents by applying all the replacements.
///
- /// \param Diagnostics DiagnosticsEngine for error output.
+ /// \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.
///
- /// \returns \li true if all files with overridden file contents were written
- /// to disk successfully.
- /// \li false if any failure occurred.
- bool writeToDisk(clang::DiagnosticsEngine &Diagnostics) const;
+ /// \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:
- FileStateMap FileStates;
- ChangeMap ChangeTracking;
+ 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.
///
-/// Generates a unique filename in the same directory as \c MainSourceFile. The
-/// filename is generated following this pattern:
+/// Generates a unique filename in the same directory as the header file. The
+/// 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.
///
-/// \param[in] MainSourceFile Full path to the source file.
-/// \param[out] Result The resulting unique filename in the same directory as
-/// the \c MainSourceFile.
-/// \param[out] Error If an error occurs a description of that error is
-/// placed in this string.
-/// \returns true on success, false if a unique file name could not be created.
-bool generateReplacementsFileName(const llvm::StringRef MainSourceFile,
- llvm::SmallVectorImpl<char> &Result,
- llvm::SmallVectorImpl<char> &Error);
+/// @param SourceFile Full path to the source file.
+/// @param HeaderFile Full path to the header file.
+/// @param Result The resulting unique filename in the same directory as the
+/// header file.
+/// @param Error Description of the error if there is any.
+/// @returns true if succeeded, false otherwise.
+bool generateReplacementsFileName(llvm::StringRef SourceFile,
+ llvm::StringRef HeaderFile,
+ llvm::SmallVectorImpl<char> &Result,
+ llvm::SmallVectorImpl<char> &Error);
#endif // CPP11_MIGRATE_FILE_OVERRIDES_H
diff --git a/clang-tools-extra/cpp11-migrate/Core/Makefile b/clang-tools-extra/cpp11-migrate/Core/Makefile
index 51bc98defee..5da4cec8481 100644
--- a/clang-tools-extra/cpp11-migrate/Core/Makefile
+++ b/clang-tools-extra/cpp11-migrate/Core/Makefile
@@ -11,4 +11,4 @@ LIBRARYNAME := migrateCore
include $(CLANG_LEVEL)/Makefile
-CPP.Flags += -I$(PROJ_SRC_DIR)/.. -I$(PROJ_SRC_DIR)/../../clang-replace/include
+CPP.Flags += -I$(PROJ_SRC_DIR)/..
diff --git a/clang-tools-extra/cpp11-migrate/Core/Refactoring.h b/clang-tools-extra/cpp11-migrate/Core/Refactoring.h
deleted file mode 100644
index a15634a3704..00000000000
--- a/clang-tools-extra/cpp11-migrate/Core/Refactoring.h
+++ /dev/null
@@ -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
diff --git a/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp b/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp
index 50ba1f19f7a..4e14ea5784e 100644
--- a/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp
+++ b/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp
@@ -22,23 +22,39 @@
using namespace clang;
-void Reformatter::reformatChanges(const FileOverrides &FileStates,
- clang::SourceManager &SM,
- clang::tooling::ReplacementsVec &Replaces) {
- FileStates.applyOverrides(SM);
-
- for (FileOverrides::ChangeMap::const_iterator
- I = FileStates.getChangedRanges().begin(),
- E = FileStates.getChangedRanges().end();
+void Reformatter::reformatChanges(SourceOverrides &Overrides) {
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
+ new DiagnosticOptions());
+ DiagnosticsEngine Diagnostics(
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
+ DiagOpts.getPtr());
+ FileManager Files((FileSystemOptions()));
+ SourceManager SM(Diagnostics, Files);
+
+ reformatChanges(Overrides, SM);
+}
+
+void Reformatter::reformatChanges(SourceOverrides &Overrides,
+ clang::SourceManager &SM) {
+ 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) {
- reformatSingleFile(I->getKey(), I->getValue(), SM, Replaces);
+ 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);
}
-void Reformatter::reformatSingleFile(
- const llvm::StringRef FileName, const ChangedRanges &Changes,
- SourceManager &SM, clang::tooling::ReplacementsVec &FormatReplacements) {
-
+tooling::Replacements Reformatter::reformatSingleFile(
+ llvm::StringRef FileName, const ChangedRanges &Changes, SourceManager &SM) {
const clang::FileEntry *Entry = SM.getFileManager().getFile(FileName);
assert(Entry && "expected an existing file");
@@ -56,7 +72,5 @@ void Reformatter::reformatSingleFile(
}
Lexer Lex(ID, SM.getBuffer(ID), SM, getFormattingLangOpts(Style.Standard));
- const tooling::Replacements &R =
- format::reformat(Style, Lex, SM, ReformatRanges);
- std::copy(R.begin(), R.end(), std::back_inserter(FormatReplacements));
+ return format::reformat(Style, Lex, SM, ReformatRanges);
}
diff --git a/clang-tools-extra/cpp11-migrate/Core/Reformatting.h b/clang-tools-extra/cpp11-migrate/Core/Reformatting.h
index 9a10171a742..e63e51d2160 100644
--- a/clang-tools-extra/cpp11-migrate/Core/Reformatting.h
+++ b/clang-tools-extra/cpp11-migrate/Core/Reformatting.h
@@ -16,10 +16,9 @@
#ifndef CPP11_MIGRATE_REFORMATTING_H
#define CPP11_MIGRATE_REFORMATTING_H
-#include "Core/Refactoring.h"
#include "clang/Format/Format.h"
-class FileOverrides;
+class SourceOverrides;
class ChangedRanges;
class Reformatter {
@@ -28,30 +27,31 @@ public:
/// \brief Reformat the changes made to the file overrides.
///
- /// This function will apply the state of files stored in \c FileState to \c
- /// SM.
+ /// \param Overrides Overriden source files to reformat. Note that since only
+ /// 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.
- /// \param[in] SM SourceManager for access to source files.
- /// \param[out] Replaces Container to store all reformatting replacements.
- void reformatChanges(const FileOverrides &FileState, clang::SourceManager &SM,
- clang::tooling::ReplacementsVec &Replaces);
+ /// \sa \c SourceOverrides::isTrackingFileChanges()
+ void reformatChanges(SourceOverrides &Overrides, clang::SourceManager &SM);
+
+ /// \brief Overload of \c reformatChanges() providing it's own
+ /// \c SourceManager.
+ void reformatChanges(SourceOverrides &Overrides);
/// \brief Produce a list of replacements to apply on \p FileName, only the
/// ranges in \p Changes are replaced.
///
- /// Since this routine use \c clang::format::reformat() the rules that
- /// function applies to ranges also apply here.
+ /// Since this routine use \c clang::format::reformat() the rules that applies
+ /// on the ranges are identical:
///
- /// \param[in] FileName Name of file to reformat.
- /// \param[in] Changes Description of where changes were made to the file.
- /// \param[in] SM SourceManager required to create replacements.
- /// \param[out] FormatReplacements New reformatting replacements are appended
- /// to this container.
- void reformatSingleFile(const llvm::StringRef FileName,
- const ChangedRanges &Changes,
- clang::SourceManager &SM,
- clang::tooling::ReplacementsVec &FormatReplacements);
+ /// \par
+ /// Each range is extended on either end to its next bigger logic
+ /// unit, i.e. everything that might influence its formatting or might be
+ /// influenced by its formatting.
+ /// -- \c clang::format::reformat()
+ clang::tooling::Replacements reformatSingleFile(llvm::StringRef FileName,
+ const ChangedRanges &Changes,
+ clang::SourceManager &SM);
private:
clang::format::FormatStyle Style;
diff --git a/clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp b/clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp
index bd2eb63044f..7315768f360 100644
--- a/clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp
+++ b/clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp
@@ -30,7 +30,9 @@ public:
if (!SyntaxOnlyAction::BeginSourceFileAction(CI, Filename))
return false;
- Overrides.applyOverrides(CI.getSourceManager());
+ FileOverrides::const_iterator I = Overrides.find(Filename);
+ if (I != Overrides.end())
+ I->second->applyOverrides(CI.getSourceManager());
return true;
}
diff --git a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp
index cd76723d316..4354df2987e 100644
--- a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp
+++ b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp
@@ -100,8 +100,13 @@ bool Transform::isFileModifiable(const SourceManager &SM,
bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
assert(Overrides != 0 && "Subclass transform didn't provide InputState");
- Overrides->applyOverrides(CI.getSourceManager());
- CurrentSource = Filename;
+ CurrentSource = Filename.str();
+
+ FileOverrides::const_iterator I = Overrides->find(CurrentSource);
+ if (I != Overrides->end())
+ I->second->applyOverrides(CI.getSourceManager());
+
+ Replace.clear();
if (Options().EnableTiming) {
Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord()));
@@ -111,7 +116,11 @@ bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
}
void Transform::handleEndSource() {
- CurrentSource.clear();
+ if (!getReplacements().empty()) {
+ SourceOverrides &SO = Overrides->getOrCreate(CurrentSource);
+ SO.applyReplacements(getReplacements());
+ }
+
if (Options().EnableTiming)
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));
}
-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) {
return new ActionFactory(Finder, /*Owner=*/ *this);
}
diff --git a/clang-tools-extra/cpp11-migrate/Core/Transform.h b/clang-tools-extra/cpp11-migrate/Core/Transform.h
index 45e470d64e4..43082111d54 100644
--- a/clang-tools-extra/cpp11-migrate/Core/Transform.h
+++ b/clang-tools-extra/cpp11-migrate/Core/Transform.h
@@ -17,7 +17,7 @@
#define CPP11_MIGRATE_TRANSFORM_H
#include "Core/IncludeExcludeInfo.h"
-#include "Core/Refactoring.h"
+#include "clang/Tooling/Refactoring.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Registry.h"
@@ -52,12 +52,6 @@ class MatchFinder;
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.
extern llvm::cl::OptionCategory TransformsOptionsCategory;
@@ -105,7 +99,7 @@ public:
/// SourcePaths and should take precedence over content of files on disk.
/// Upon return, \p ResultStates shall contain the result of performing this
/// transform on the files listed in \p SourcePaths.
- virtual int apply(const FileOverrides &InputStates,
+ virtual int apply(FileOverrides &InputStates,
const clang::tooling::CompilationDatabase &Database,
const std::vector<std::string> &SourcePaths) = 0;
@@ -178,17 +172,6 @@ public:
/// \brief Return an iterator to the start of collected timing data.
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:
void setAcceptedChanges(unsigned Changes) {
@@ -212,12 +195,16 @@ protected:
/// created with.
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
/// applying frontend actions.
///
/// It is an error not to call this function before calling ClangTool::run()
/// with the factory provided by createActionFactory().
- void setOverrides(const FileOverrides &Overrides) {
+ void setOverrides(FileOverrides &Overrides) {
this->Overrides = &Overrides;
}
@@ -232,8 +219,8 @@ protected:
private:
const std::string Name;
const TransformOptions &GlobalOptions;
- const FileOverrides *Overrides;
- TUReplacementsMap Replacements;
+ FileOverrides *Overrides;
+ clang::tooling::Replacements Replace;
std::string CurrentSource;
TimingVec Timings;
unsigned AcceptedChanges;
OpenPOWER on IntegriCloud