Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===--- AtomicChange.h - AtomicChange class --------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. //  This file defines AtomicChange which is used to create a set of source
  10. //  changes, e.g. replacements and header insertions.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H
  15. #define LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H
  16.  
  17. #include "clang/Basic/SourceManager.h"
  18. #include "clang/Format/Format.h"
  19. #include "clang/Tooling/Core/Replacement.h"
  20. #include "llvm/ADT/Any.h"
  21. #include "llvm/ADT/StringRef.h"
  22. #include "llvm/Support/Error.h"
  23.  
  24. namespace clang {
  25. namespace tooling {
  26.  
  27. /// An atomic change is used to create and group a set of source edits,
  28. /// e.g. replacements or header insertions. Edits in an AtomicChange should be
  29. /// related, e.g. replacements for the same type reference and the corresponding
  30. /// header insertion/deletion.
  31. ///
  32. /// An AtomicChange is uniquely identified by a key and will either be fully
  33. /// applied or not applied at all.
  34. ///
  35. /// Calling setError on an AtomicChange stores the error message and marks it as
  36. /// bad, i.e. none of its source edits will be applied.
  37. class AtomicChange {
  38. public:
  39.   /// Creates an atomic change around \p KeyPosition with the key being a
  40.   /// concatenation of the file name and the offset of \p KeyPosition.
  41.   /// \p KeyPosition should be the location of the key syntactical element that
  42.   /// is being changed, e.g. the call to a refactored method.
  43.   AtomicChange(const SourceManager &SM, SourceLocation KeyPosition);
  44.  
  45.   AtomicChange(const SourceManager &SM, SourceLocation KeyPosition,
  46.                llvm::Any Metadata);
  47.  
  48.   /// Creates an atomic change for \p FilePath with a customized key.
  49.   AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key)
  50.       : Key(Key), FilePath(FilePath) {}
  51.  
  52.   AtomicChange(AtomicChange &&) = default;
  53.   AtomicChange(const AtomicChange &) = default;
  54.  
  55.   AtomicChange &operator=(AtomicChange &&) = default;
  56.   AtomicChange &operator=(const AtomicChange &) = default;
  57.  
  58.   bool operator==(const AtomicChange &Other) const;
  59.  
  60.   /// Returns the atomic change as a YAML string.
  61.   std::string toYAMLString();
  62.  
  63.   /// Converts a YAML-encoded automic change to AtomicChange.
  64.   static AtomicChange convertFromYAML(llvm::StringRef YAMLContent);
  65.  
  66.   /// Returns the key of this change, which is a concatenation of the
  67.   /// file name and offset of the key position.
  68.   const std::string &getKey() const { return Key; }
  69.  
  70.   /// Returns the path of the file containing this atomic change.
  71.   const std::string &getFilePath() const { return FilePath; }
  72.  
  73.   /// If this change could not be created successfully, e.g. because of
  74.   /// conflicts among replacements, use this to set an error description.
  75.   /// Thereby, places that cannot be fixed automatically can be gathered when
  76.   /// applying changes.
  77.   void setError(llvm::StringRef Error) { this->Error = std::string(Error); }
  78.  
  79.   /// Returns whether an error has been set on this list.
  80.   bool hasError() const { return !Error.empty(); }
  81.  
  82.   /// Returns the error message or an empty string if it does not exist.
  83.   const std::string &getError() const { return Error; }
  84.  
  85.   /// Adds a replacement that replaces the given Range with
  86.   /// ReplacementText.
  87.   /// \returns An llvm::Error carrying ReplacementError on error.
  88.   llvm::Error replace(const SourceManager &SM, const CharSourceRange &Range,
  89.                       llvm::StringRef ReplacementText);
  90.  
  91.   /// Adds a replacement that replaces range [Loc, Loc+Length) with
  92.   /// \p Text.
  93.   /// \returns An llvm::Error carrying ReplacementError on error.
  94.   llvm::Error replace(const SourceManager &SM, SourceLocation Loc,
  95.                       unsigned Length, llvm::StringRef Text);
  96.  
  97.   /// Adds a replacement that inserts \p Text at \p Loc. If this
  98.   /// insertion conflicts with an existing insertion (at the same position),
  99.   /// this will be inserted before/after the existing insertion depending on
  100.   /// \p InsertAfter. Users should use `replace` with `Length=0` instead if they
  101.   /// do not want conflict resolving by default. If the conflicting replacement
  102.   /// is not an insertion, an error is returned.
  103.   ///
  104.   /// \returns An llvm::Error carrying ReplacementError on error.
  105.   llvm::Error insert(const SourceManager &SM, SourceLocation Loc,
  106.                      llvm::StringRef Text, bool InsertAfter = true);
  107.  
  108.   /// Adds a header into the file that contains the key position.
  109.   /// Header can be in angle brackets or double quotation marks. By default
  110.   /// (header is not quoted), header will be surrounded with double quotes.
  111.   void addHeader(llvm::StringRef Header);
  112.  
  113.   /// Removes a header from the file that contains the key position.
  114.   void removeHeader(llvm::StringRef Header);
  115.  
  116.   /// Returns a const reference to existing replacements.
  117.   const Replacements &getReplacements() const { return Replaces; }
  118.  
  119.   Replacements &getReplacements() { return Replaces; }
  120.  
  121.   llvm::ArrayRef<std::string> getInsertedHeaders() const {
  122.     return InsertedHeaders;
  123.   }
  124.  
  125.   llvm::ArrayRef<std::string> getRemovedHeaders() const {
  126.     return RemovedHeaders;
  127.   }
  128.  
  129.   const llvm::Any &getMetadata() const { return Metadata; }
  130.  
  131. private:
  132.   AtomicChange() {}
  133.  
  134.   AtomicChange(std::string Key, std::string FilePath, std::string Error,
  135.                std::vector<std::string> InsertedHeaders,
  136.                std::vector<std::string> RemovedHeaders,
  137.                clang::tooling::Replacements Replaces);
  138.  
  139.   // This uniquely identifies an AtomicChange.
  140.   std::string Key;
  141.   std::string FilePath;
  142.   std::string Error;
  143.   std::vector<std::string> InsertedHeaders;
  144.   std::vector<std::string> RemovedHeaders;
  145.   tooling::Replacements Replaces;
  146.  
  147.   // This field stores metadata which is ignored for the purposes of applying
  148.   // edits to source, but may be useful for other consumers of AtomicChanges. In
  149.   // particular, consumers can use this to direct how they want to consume each
  150.   // edit.
  151.   llvm::Any Metadata;
  152. };
  153.  
  154. using AtomicChanges = std::vector<AtomicChange>;
  155.  
  156. // Defines specs for applying changes.
  157. struct ApplyChangesSpec {
  158.   // If true, cleans up redundant/erroneous code around changed code with
  159.   // clang-format's cleanup functionality, e.g. redundant commas around deleted
  160.   // parameter or empty namespaces introduced by deletions.
  161.   bool Cleanup = true;
  162.  
  163.   format::FormatStyle Style = format::getNoStyle();
  164.  
  165.   // Options for selectively formatting changes with clang-format:
  166.   // kAll: Format all changed lines.
  167.   // kNone: Don't format anything.
  168.   // kViolations: Format lines exceeding the `ColumnLimit` in `Style`.
  169.   enum FormatOption { kAll, kNone, kViolations };
  170.  
  171.   FormatOption Format = kNone;
  172. };
  173.  
  174. /// Applies all AtomicChanges in \p Changes to the \p Code.
  175. ///
  176. /// This completely ignores the file path in each change and replaces them with
  177. /// \p FilePath, i.e. callers are responsible for ensuring all changes are for
  178. /// the same file.
  179. ///
  180. /// \returns The changed code if all changes are applied successfully;
  181. /// otherwise, an llvm::Error carrying llvm::StringError is returned (the Error
  182. /// message can be converted to string with `llvm::toString()` and the
  183. /// error_code should be ignored).
  184. llvm::Expected<std::string>
  185. applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code,
  186.                    llvm::ArrayRef<AtomicChange> Changes,
  187.                    const ApplyChangesSpec &Spec);
  188.  
  189. } // end namespace tooling
  190. } // end namespace clang
  191.  
  192. #endif // LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H
  193.