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