Home | History | Annotate | Download | only in Refactoring
      1 //===--- AtomicChange.h - AtomicChange class --------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file defines AtomicChange which is used to create a set of source
     11 //  changes, e.g. replacements and header insertions.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H
     16 #define LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H
     17 
     18 #include "clang/Basic/SourceManager.h"
     19 #include "clang/Tooling/Core/Replacement.h"
     20 #include "llvm/ADT/StringRef.h"
     21 #include "llvm/Support/Error.h"
     22 
     23 namespace clang {
     24 namespace tooling {
     25 
     26 /// \brief An atomic change is used to create and group a set of source edits,
     27 /// e.g. replacements or header insertions. Edits in an AtomicChange should be
     28 /// related, e.g. replacements for the same type reference and the corresponding
     29 /// header insertion/deletion.
     30 ///
     31 /// An AtomicChange is uniquely identified by a key and will either be fully
     32 /// applied or not applied at all.
     33 ///
     34 /// Calling setError on an AtomicChange stores the error message and marks it as
     35 /// bad, i.e. none of its source edits will be applied.
     36 class AtomicChange {
     37 public:
     38   /// \brief Creates an atomic change around \p KeyPosition with the key being a
     39   /// concatenation of the file name and the offset of \p KeyPosition.
     40   /// \p KeyPosition should be the location of the key syntactical element that
     41   /// is being changed, e.g. the call to a refactored method.
     42   AtomicChange(const SourceManager &SM, SourceLocation KeyPosition);
     43 
     44   /// \brief Creates an atomic change for \p FilePath with a customized key.
     45   AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key)
     46       : Key(Key), FilePath(FilePath) {}
     47 
     48   /// \brief Returns the atomic change as a YAML string.
     49   std::string toYAMLString();
     50 
     51   /// \brief Converts a YAML-encoded automic change to AtomicChange.
     52   static AtomicChange convertFromYAML(llvm::StringRef YAMLContent);
     53 
     54   /// \brief Returns the key of this change, which is a concatenation of the
     55   /// file name and offset of the key position.
     56   const std::string &getKey() const { return Key; }
     57 
     58   /// \brief Returns the path of the file containing this atomic change.
     59   const std::string &getFilePath() const { return FilePath; }
     60 
     61   /// \brief If this change could not be created successfully, e.g. because of
     62   /// conflicts among replacements, use this to set an error description.
     63   /// Thereby, places that cannot be fixed automatically can be gathered when
     64   /// applying changes.
     65   void setError(llvm::StringRef Error) { this->Error = Error; }
     66 
     67   /// \brief Returns whether an error has been set on this list.
     68   bool hasError() const { return !Error.empty(); }
     69 
     70   /// \brief Returns the error message or an empty string if it does not exist.
     71   const std::string &getError() const { return Error; }
     72 
     73   /// \brief Adds a replacement that replaces the given Range with
     74   /// ReplacementText.
     75   /// \returns An llvm::Error carrying ReplacementError on error.
     76   llvm::Error replace(const SourceManager &SM, const CharSourceRange &Range,
     77                       llvm::StringRef ReplacementText);
     78 
     79   /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with
     80   /// \p Text.
     81   /// \returns An llvm::Error carrying ReplacementError on error.
     82   llvm::Error replace(const SourceManager &SM, SourceLocation Loc,
     83                       unsigned Length, llvm::StringRef Text);
     84 
     85   /// \brief Adds a replacement that inserts \p Text at \p Loc. If this
     86   /// insertion conflicts with an existing insertion (at the same position),
     87   /// this will be inserted before/after the existing insertion depending on
     88   /// \p InsertAfter. Users should use `replace` with `Length=0` instead if they
     89   /// do not want conflict resolving by default. If the conflicting replacement
     90   /// is not an insertion, an error is returned.
     91   ///
     92   /// \returns An llvm::Error carrying ReplacementError on error.
     93   llvm::Error insert(const SourceManager &SM, SourceLocation Loc,
     94                      llvm::StringRef Text, bool InsertAfter = true);
     95 
     96   /// \brief Adds a header into the file that contains the key position.
     97   /// Header can be in angle brackets or double quotation marks. By default
     98   /// (header is not quoted), header will be surrounded with double quotes.
     99   void addHeader(llvm::StringRef Header);
    100 
    101   /// \brief Removes a header from the file that contains the key position.
    102   void removeHeader(llvm::StringRef Header);
    103 
    104   /// \brief Returns a const reference to existing replacements.
    105   const Replacements &getReplacements() const { return Replaces; }
    106 
    107   llvm::ArrayRef<std::string> getInsertedHeaders() const {
    108     return InsertedHeaders;
    109   }
    110 
    111   llvm::ArrayRef<std::string> getRemovedHeaders() const {
    112     return RemovedHeaders;
    113   }
    114 
    115 private:
    116   AtomicChange() {}
    117 
    118   AtomicChange(std::string Key, std::string FilePath, std::string Error,
    119                std::vector<std::string> InsertedHeaders,
    120                std::vector<std::string> RemovedHeaders,
    121                clang::tooling::Replacements Replaces);
    122 
    123   // This uniquely identifies an AtomicChange.
    124   std::string Key;
    125   std::string FilePath;
    126   std::string Error;
    127   std::vector<std::string> InsertedHeaders;
    128   std::vector<std::string> RemovedHeaders;
    129   tooling::Replacements Replaces;
    130 };
    131 
    132 } // end namespace tooling
    133 } // end namespace clang
    134 
    135 #endif // LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H
    136