1f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===--- Refactoring.h - Framework for clang refactoring tools --*- C++ -*-===// 2f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 3f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// The LLVM Compiler Infrastructure 4f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 5f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// This file is distributed under the University of Illinois Open Source 6f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// License. See LICENSE.TXT for details. 7f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 8f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===----------------------------------------------------------------------===// 9f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 10f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// Interfaces supporting refactorings that span multiple translation units. 11f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// While single translation unit refactorings are supported via the Rewriter, 12f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// when refactoring multiple translation units changes must be stored in a 13f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// SourceManager independent form, duplicate changes need to be removed, and 14f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// all changes must be applied at once at the end of the refactoring so that 15f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// the code is always parseable. 16f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 17f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===----------------------------------------------------------------------===// 18f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 195d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek#ifndef LLVM_CLANG_TOOLING_REFACTORING_H 205d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek#define LLVM_CLANG_TOOLING_REFACTORING_H 215d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek 22f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Basic/SourceLocation.h" 23f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Tooling/Tooling.h" 2430a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "llvm/ADT/StringRef.h" 25f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include <set> 26f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include <string> 27f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 28f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimeknamespace clang { 29f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 30f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass Rewriter; 31f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass SourceLocation; 32f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 33f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimeknamespace tooling { 34f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 358a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper/// \brief A source range independent of the \c SourceManager. 368a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasperclass Range { 378a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasperpublic: 388a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper Range() : Offset(0), Length(0) {} 398a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {} 408a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper 4146fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek /// \brief Accessors. 4246fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek /// @{ 438a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper unsigned getOffset() const { return Offset; } 448a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper unsigned getLength() const { return Length; } 4546fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek /// @} 4646fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek 4746fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek /// \name Range Predicates 4846fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek /// @{ 4946fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek /// \brief Whether this range overlaps with \p RHS or not. 5046fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek bool overlapsWith(Range RHS) const { 5146fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek if ((Offset + Length) <= RHS.Offset || Offset >= (RHS.Offset + RHS.Length)) 5246fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek return false; 5346fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek return true; 5446fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek } 5546fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek 5646fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek /// \brief Whether this range contains \p RHS or not. 5746fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek bool contains(Range RHS) const { 5846fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek return RHS.Offset >= Offset && 5946fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek (RHS.Offset + RHS.Length) <= (Offset + Length); 6046fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek } 6146fa4c355bd45197dff580b63240494a53b16c1dManuel Klimek /// @} 628a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper 638a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasperprivate: 648a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper unsigned Offset; 658a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper unsigned Length; 668a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper}; 678a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper 68f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek/// \brief A text replacement. 69f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek/// 70f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek/// Represents a SourceManager independent replacement of a range of text in a 71f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek/// specific file. 72f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekclass Replacement { 73f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekpublic: 74f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \brief Creates an invalid (not applicable) replacement. 75f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement(); 76f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 77f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \brief Creates a replacement of the range [Offset, Offset+Length) in 78f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// FilePath with ReplacementText. 79f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// 80f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \param FilePath A source file accessible via a SourceManager. 81f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \param Offset The byte offset of the start of the range in the file. 82f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \param Length The length of the range in bytes. 83cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko Replacement(StringRef FilePath, unsigned Offset, 84cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko unsigned Length, StringRef ReplacementText); 85f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 86f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \brief Creates a Replacement of the range [Start, Start+Length) with 87f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// ReplacementText. 88f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement(SourceManager &Sources, SourceLocation Start, unsigned Length, 89cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko StringRef ReplacementText); 90f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 91f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \brief Creates a Replacement of the given range with ReplacementText. 92f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement(SourceManager &Sources, const CharSourceRange &Range, 93cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko StringRef ReplacementText); 94f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 95f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \brief Creates a Replacement of the node with ReplacementText. 96f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek template <typename Node> 97f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacement(SourceManager &Sources, const Node &NodeToReplace, 98cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko StringRef ReplacementText); 99f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 100f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \brief Returns whether this replacement can be applied to a file. 101f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// 102f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// Only replacements that are in a valid file can be applied. 103f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek bool isApplicable() const; 104f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 105f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \brief Accessors. 106f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// @{ 107b53bf007307908ad1750956009d1f0b313ac985dManuel Klimek StringRef getFilePath() const { return FilePath; } 1088a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper unsigned getOffset() const { return ReplacementRange.getOffset(); } 1098a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper unsigned getLength() const { return ReplacementRange.getLength(); } 11030c8a1f79f6d0b61235f5c2762c9077af70d426dManuel Klimek StringRef getReplacementText() const { return ReplacementText; } 111f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// @} 112f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 113f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \brief Applies the replacement on the Rewriter. 114f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek bool apply(Rewriter &Rewrite) const; 115f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 1165d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek /// \brief Returns a human readable string representation. 1175d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek std::string toString() const; 1185d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek 119f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \brief Comparator to be able to use Replacement in std::set for uniquing. 120f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek class Less { 121f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek public: 122f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek bool operator()(const Replacement &R1, const Replacement &R2) const; 123f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek }; 124f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 125f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek private: 126f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek void setFromSourceLocation(SourceManager &Sources, SourceLocation Start, 127cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko unsigned Length, StringRef ReplacementText); 128f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek void setFromSourceRange(SourceManager &Sources, const CharSourceRange &Range, 129cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko StringRef ReplacementText); 130f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 131f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek std::string FilePath; 1328a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper Range ReplacementRange; 133f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek std::string ReplacementText; 134f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}; 135f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 136f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek/// \brief A set of Replacements. 137f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek/// FIXME: Change to a vector and deduplicate in the RefactoringTool. 138f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimektypedef std::set<Replacement, Replacement::Less> Replacements; 139f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 140d088a5f966c31462280d5ace29febc6889834611Edwin Vane/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite. 141f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek/// 142d088a5f966c31462280d5ace29febc6889834611Edwin Vane/// Replacement applications happen independently of the success of 143d088a5f966c31462280d5ace29febc6889834611Edwin Vane/// other applications. 144d088a5f966c31462280d5ace29febc6889834611Edwin Vane/// 145d088a5f966c31462280d5ace29febc6889834611Edwin Vane/// \returns true if all replacements apply. false otherwise. 14676a2ea3d8a0c3f3a54f293e305ae16f654eab04fDavid Blaikiebool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite); 147f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 1488a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper/// \brief Applies all replacements in \p Replaces to \p Code. 1498a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper/// 1508a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper/// This completely ignores the path stored in each replacement. If one or more 1518a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper/// replacements cannot be applied, this returns an empty \c string. 15276a2ea3d8a0c3f3a54f293e305ae16f654eab04fDavid Blaikiestd::string applyAllReplacements(StringRef Code, const Replacements &Replaces); 1538a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper 1546bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper/// \brief Calculates how a code \p Position is shifted when \p Replaces are 1556bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper/// applied. 1566bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasperunsigned shiftedCodePosition(const Replacements& Replaces, unsigned Position); 1576bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper 158f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek/// \brief A tool to run refactorings. 159f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek/// 160d088a5f966c31462280d5ace29febc6889834611Edwin Vane/// This is a refactoring specific version of \see ClangTool. FrontendActions 161d088a5f966c31462280d5ace29febc6889834611Edwin Vane/// passed to run() and runAndSave() should add replacements to 162d088a5f966c31462280d5ace29febc6889834611Edwin Vane/// getReplacements(). 163d088a5f966c31462280d5ace29febc6889834611Edwin Vaneclass RefactoringTool : public ClangTool { 164f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekpublic: 165f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek /// \see ClangTool::ClangTool. 166f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek RefactoringTool(const CompilationDatabase &Compilations, 167f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek ArrayRef<std::string> SourcePaths); 168f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 169d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// \brief Returns the set of replacements to which replacements should 170d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// be added during the run of the tool. 171f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacements &getReplacements(); 172f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 173d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// \brief Call run(), apply all generated replacements, and immediately save 174d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// the results to disk. 175d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// 176d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// \returns 0 upon success. Non-zero upon failure. 177d088a5f966c31462280d5ace29febc6889834611Edwin Vane int runAndSave(FrontendActionFactory *ActionFactory); 178d088a5f966c31462280d5ace29febc6889834611Edwin Vane 179d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// \brief Apply all stored replacements to the given Rewriter. 180d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// 181d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// Replacement applications happen independently of the success of other 182d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// applications. 183d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// 184d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// \returns true if all replacements apply. false otherwise. 185d088a5f966c31462280d5ace29febc6889834611Edwin Vane bool applyAllReplacements(Rewriter &Rewrite); 186d088a5f966c31462280d5ace29febc6889834611Edwin Vane 187d088a5f966c31462280d5ace29febc6889834611Edwin Vaneprivate: 188d088a5f966c31462280d5ace29febc6889834611Edwin Vane /// \brief Write all refactored files to disk. 189d088a5f966c31462280d5ace29febc6889834611Edwin Vane int saveRewrittenFiles(Rewriter &Rewrite); 190f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 191f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekprivate: 192f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Replacements Replace; 193f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek}; 194f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 195f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimektemplate <typename Node> 196f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekReplacement::Replacement(SourceManager &Sources, const Node &NodeToReplace, 197cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko StringRef ReplacementText) { 198f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek const CharSourceRange Range = 199f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek CharSourceRange::getTokenRange(NodeToReplace->getSourceRange()); 200f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek setFromSourceRange(Sources, Range, ReplacementText); 201f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 202f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 203f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace tooling 204f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace clang 2055d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek 2065d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek#endif // end namespace LLVM_CLANG_TOOLING_REFACTORING_H 207