1239313Sdim//===--- Refactoring.h - Framework for clang refactoring tools --*- C++ -*-===// 2239313Sdim// 3239313Sdim// The LLVM Compiler Infrastructure 4239313Sdim// 5239313Sdim// This file is distributed under the University of Illinois Open Source 6239313Sdim// License. See LICENSE.TXT for details. 7239313Sdim// 8239313Sdim//===----------------------------------------------------------------------===// 9239313Sdim// 10239313Sdim// Interfaces supporting refactorings that span multiple translation units. 11239313Sdim// While single translation unit refactorings are supported via the Rewriter, 12239313Sdim// when refactoring multiple translation units changes must be stored in a 13239313Sdim// SourceManager independent form, duplicate changes need to be removed, and 14239313Sdim// all changes must be applied at once at the end of the refactoring so that 15239313Sdim// the code is always parseable. 16239313Sdim// 17239313Sdim//===----------------------------------------------------------------------===// 18239313Sdim 19239313Sdim#ifndef LLVM_CLANG_TOOLING_REFACTORING_H 20239313Sdim#define LLVM_CLANG_TOOLING_REFACTORING_H 21239313Sdim 22239313Sdim#include "clang/Basic/SourceLocation.h" 23239313Sdim#include "clang/Tooling/Tooling.h" 24249423Sdim#include "llvm/ADT/StringRef.h" 25239313Sdim#include <set> 26239313Sdim#include <string> 27239313Sdim 28239313Sdimnamespace clang { 29239313Sdim 30239313Sdimclass Rewriter; 31239313Sdimclass SourceLocation; 32239313Sdim 33239313Sdimnamespace tooling { 34239313Sdim 35239313Sdim/// \brief A text replacement. 36239313Sdim/// 37239313Sdim/// Represents a SourceManager independent replacement of a range of text in a 38239313Sdim/// specific file. 39239313Sdimclass Replacement { 40239313Sdimpublic: 41239313Sdim /// \brief Creates an invalid (not applicable) replacement. 42239313Sdim Replacement(); 43239313Sdim 44239313Sdim /// \brief Creates a replacement of the range [Offset, Offset+Length) in 45239313Sdim /// FilePath with ReplacementText. 46239313Sdim /// 47239313Sdim /// \param FilePath A source file accessible via a SourceManager. 48239313Sdim /// \param Offset The byte offset of the start of the range in the file. 49239313Sdim /// \param Length The length of the range in bytes. 50249423Sdim Replacement(StringRef FilePath, unsigned Offset, 51249423Sdim unsigned Length, StringRef ReplacementText); 52239313Sdim 53239313Sdim /// \brief Creates a Replacement of the range [Start, Start+Length) with 54239313Sdim /// ReplacementText. 55239313Sdim Replacement(SourceManager &Sources, SourceLocation Start, unsigned Length, 56249423Sdim StringRef ReplacementText); 57239313Sdim 58239313Sdim /// \brief Creates a Replacement of the given range with ReplacementText. 59239313Sdim Replacement(SourceManager &Sources, const CharSourceRange &Range, 60249423Sdim StringRef ReplacementText); 61239313Sdim 62239313Sdim /// \brief Creates a Replacement of the node with ReplacementText. 63239313Sdim template <typename Node> 64239313Sdim Replacement(SourceManager &Sources, const Node &NodeToReplace, 65249423Sdim StringRef ReplacementText); 66239313Sdim 67239313Sdim /// \brief Returns whether this replacement can be applied to a file. 68239313Sdim /// 69239313Sdim /// Only replacements that are in a valid file can be applied. 70239313Sdim bool isApplicable() const; 71239313Sdim 72239313Sdim /// \brief Accessors. 73239313Sdim /// @{ 74239313Sdim StringRef getFilePath() const { return FilePath; } 75239313Sdim unsigned getOffset() const { return Offset; } 76239313Sdim unsigned getLength() const { return Length; } 77243830Sdim StringRef getReplacementText() const { return ReplacementText; } 78239313Sdim /// @} 79239313Sdim 80239313Sdim /// \brief Applies the replacement on the Rewriter. 81239313Sdim bool apply(Rewriter &Rewrite) const; 82239313Sdim 83239313Sdim /// \brief Returns a human readable string representation. 84239313Sdim std::string toString() const; 85239313Sdim 86239313Sdim /// \brief Comparator to be able to use Replacement in std::set for uniquing. 87239313Sdim class Less { 88239313Sdim public: 89239313Sdim bool operator()(const Replacement &R1, const Replacement &R2) const; 90239313Sdim }; 91239313Sdim 92239313Sdim private: 93239313Sdim void setFromSourceLocation(SourceManager &Sources, SourceLocation Start, 94249423Sdim unsigned Length, StringRef ReplacementText); 95239313Sdim void setFromSourceRange(SourceManager &Sources, const CharSourceRange &Range, 96249423Sdim StringRef ReplacementText); 97239313Sdim 98239313Sdim std::string FilePath; 99239313Sdim unsigned Offset; 100239313Sdim unsigned Length; 101239313Sdim std::string ReplacementText; 102239313Sdim}; 103239313Sdim 104239313Sdim/// \brief A set of Replacements. 105239313Sdim/// FIXME: Change to a vector and deduplicate in the RefactoringTool. 106239313Sdimtypedef std::set<Replacement, Replacement::Less> Replacements; 107239313Sdim 108249423Sdim/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite. 109239313Sdim/// 110249423Sdim/// Replacement applications happen independently of the success of 111249423Sdim/// other applications. 112249423Sdim/// 113249423Sdim/// \returns true if all replacements apply. false otherwise. 114239313Sdimbool applyAllReplacements(Replacements &Replaces, Rewriter &Rewrite); 115239313Sdim 116239313Sdim/// \brief A tool to run refactorings. 117239313Sdim/// 118249423Sdim/// This is a refactoring specific version of \see ClangTool. FrontendActions 119249423Sdim/// passed to run() and runAndSave() should add replacements to 120249423Sdim/// getReplacements(). 121249423Sdimclass RefactoringTool : public ClangTool { 122239313Sdimpublic: 123239313Sdim /// \see ClangTool::ClangTool. 124239313Sdim RefactoringTool(const CompilationDatabase &Compilations, 125239313Sdim ArrayRef<std::string> SourcePaths); 126239313Sdim 127249423Sdim /// \brief Returns the set of replacements to which replacements should 128249423Sdim /// be added during the run of the tool. 129239313Sdim Replacements &getReplacements(); 130239313Sdim 131249423Sdim /// \brief Call run(), apply all generated replacements, and immediately save 132249423Sdim /// the results to disk. 133249423Sdim /// 134249423Sdim /// \returns 0 upon success. Non-zero upon failure. 135249423Sdim int runAndSave(FrontendActionFactory *ActionFactory); 136239313Sdim 137249423Sdim /// \brief Apply all stored replacements to the given Rewriter. 138249423Sdim /// 139249423Sdim /// Replacement applications happen independently of the success of other 140249423Sdim /// applications. 141249423Sdim /// 142249423Sdim /// \returns true if all replacements apply. false otherwise. 143249423Sdim bool applyAllReplacements(Rewriter &Rewrite); 144249423Sdim 145239313Sdimprivate: 146249423Sdim /// \brief Write all refactored files to disk. 147249423Sdim int saveRewrittenFiles(Rewriter &Rewrite); 148249423Sdim 149249423Sdimprivate: 150239313Sdim Replacements Replace; 151239313Sdim}; 152239313Sdim 153239313Sdimtemplate <typename Node> 154239313SdimReplacement::Replacement(SourceManager &Sources, const Node &NodeToReplace, 155249423Sdim StringRef ReplacementText) { 156239313Sdim const CharSourceRange Range = 157239313Sdim CharSourceRange::getTokenRange(NodeToReplace->getSourceRange()); 158239313Sdim setFromSourceRange(Sources, Range, ReplacementText); 159239313Sdim} 160239313Sdim 161239313Sdim} // end namespace tooling 162239313Sdim} // end namespace clang 163239313Sdim 164239313Sdim#endif // end namespace LLVM_CLANG_TOOLING_REFACTORING_H 165