summaryrefslogtreecommitdiff
path: root/clang-r353983e/include/clang/Tooling/Refactoring/AtomicChange.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang-r353983e/include/clang/Tooling/Refactoring/AtomicChange.h')
-rw-r--r--clang-r353983e/include/clang/Tooling/Refactoring/AtomicChange.h178
1 files changed, 178 insertions, 0 deletions
diff --git a/clang-r353983e/include/clang/Tooling/Refactoring/AtomicChange.h b/clang-r353983e/include/clang/Tooling/Refactoring/AtomicChange.h
new file mode 100644
index 00000000..32e4624f
--- /dev/null
+++ b/clang-r353983e/include/clang/Tooling/Refactoring/AtomicChange.h
@@ -0,0 +1,178 @@
+//===--- AtomicChange.h - AtomicChange class --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines AtomicChange which is used to create a set of source
+// changes, e.g. replacements and header insertions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H
+#define LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Format/Format.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace tooling {
+
+/// An atomic change is used to create and group a set of source edits,
+/// e.g. replacements or header insertions. Edits in an AtomicChange should be
+/// related, e.g. replacements for the same type reference and the corresponding
+/// header insertion/deletion.
+///
+/// An AtomicChange is uniquely identified by a key and will either be fully
+/// applied or not applied at all.
+///
+/// Calling setError on an AtomicChange stores the error message and marks it as
+/// bad, i.e. none of its source edits will be applied.
+class AtomicChange {
+public:
+ /// Creates an atomic change around \p KeyPosition with the key being a
+ /// concatenation of the file name and the offset of \p KeyPosition.
+ /// \p KeyPosition should be the location of the key syntactical element that
+ /// is being changed, e.g. the call to a refactored method.
+ AtomicChange(const SourceManager &SM, SourceLocation KeyPosition);
+
+ /// Creates an atomic change for \p FilePath with a customized key.
+ AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key)
+ : Key(Key), FilePath(FilePath) {}
+
+ AtomicChange(AtomicChange &&) = default;
+ AtomicChange(const AtomicChange &) = default;
+
+ AtomicChange &operator=(AtomicChange &&) = default;
+ AtomicChange &operator=(const AtomicChange &) = default;
+
+ bool operator==(const AtomicChange &Other) const;
+
+ /// Returns the atomic change as a YAML string.
+ std::string toYAMLString();
+
+ /// Converts a YAML-encoded automic change to AtomicChange.
+ static AtomicChange convertFromYAML(llvm::StringRef YAMLContent);
+
+ /// Returns the key of this change, which is a concatenation of the
+ /// file name and offset of the key position.
+ const std::string &getKey() const { return Key; }
+
+ /// Returns the path of the file containing this atomic change.
+ const std::string &getFilePath() const { return FilePath; }
+
+ /// If this change could not be created successfully, e.g. because of
+ /// conflicts among replacements, use this to set an error description.
+ /// Thereby, places that cannot be fixed automatically can be gathered when
+ /// applying changes.
+ void setError(llvm::StringRef Error) { this->Error = Error; }
+
+ /// Returns whether an error has been set on this list.
+ bool hasError() const { return !Error.empty(); }
+
+ /// Returns the error message or an empty string if it does not exist.
+ const std::string &getError() const { return Error; }
+
+ /// Adds a replacement that replaces the given Range with
+ /// ReplacementText.
+ /// \returns An llvm::Error carrying ReplacementError on error.
+ llvm::Error replace(const SourceManager &SM, const CharSourceRange &Range,
+ llvm::StringRef ReplacementText);
+
+ /// Adds a replacement that replaces range [Loc, Loc+Length) with
+ /// \p Text.
+ /// \returns An llvm::Error carrying ReplacementError on error.
+ llvm::Error replace(const SourceManager &SM, SourceLocation Loc,
+ unsigned Length, llvm::StringRef Text);
+
+ /// Adds a replacement that inserts \p Text at \p Loc. If this
+ /// insertion conflicts with an existing insertion (at the same position),
+ /// this will be inserted before/after the existing insertion depending on
+ /// \p InsertAfter. Users should use `replace` with `Length=0` instead if they
+ /// do not want conflict resolving by default. If the conflicting replacement
+ /// is not an insertion, an error is returned.
+ ///
+ /// \returns An llvm::Error carrying ReplacementError on error.
+ llvm::Error insert(const SourceManager &SM, SourceLocation Loc,
+ llvm::StringRef Text, bool InsertAfter = true);
+
+ /// Adds a header into the file that contains the key position.
+ /// Header can be in angle brackets or double quotation marks. By default
+ /// (header is not quoted), header will be surrounded with double quotes.
+ void addHeader(llvm::StringRef Header);
+
+ /// Removes a header from the file that contains the key position.
+ void removeHeader(llvm::StringRef Header);
+
+ /// Returns a const reference to existing replacements.
+ const Replacements &getReplacements() const { return Replaces; }
+
+ llvm::ArrayRef<std::string> getInsertedHeaders() const {
+ return InsertedHeaders;
+ }
+
+ llvm::ArrayRef<std::string> getRemovedHeaders() const {
+ return RemovedHeaders;
+ }
+
+private:
+ AtomicChange() {}
+
+ AtomicChange(std::string Key, std::string FilePath, std::string Error,
+ std::vector<std::string> InsertedHeaders,
+ std::vector<std::string> RemovedHeaders,
+ clang::tooling::Replacements Replaces);
+
+ // This uniquely identifies an AtomicChange.
+ std::string Key;
+ std::string FilePath;
+ std::string Error;
+ std::vector<std::string> InsertedHeaders;
+ std::vector<std::string> RemovedHeaders;
+ tooling::Replacements Replaces;
+};
+
+using AtomicChanges = std::vector<AtomicChange>;
+
+// Defines specs for applying changes.
+struct ApplyChangesSpec {
+ // If true, cleans up redundant/erroneous code around changed code with
+ // clang-format's cleanup functionality, e.g. redundant commas around deleted
+ // parameter or empty namespaces introduced by deletions.
+ bool Cleanup = true;
+
+ format::FormatStyle Style = format::getNoStyle();
+
+ // Options for selectively formatting changes with clang-format:
+ // kAll: Format all changed lines.
+ // kNone: Don't format anything.
+ // kViolations: Format lines exceeding the `ColumnLimit` in `Style`.
+ enum FormatOption { kAll, kNone, kViolations };
+
+ FormatOption Format = kNone;
+};
+
+/// Applies all AtomicChanges in \p Changes to the \p Code.
+///
+/// This completely ignores the file path in each change and replaces them with
+/// \p FilePath, i.e. callers are responsible for ensuring all changes are for
+/// the same file.
+///
+/// \returns The changed code if all changes are applied successfully;
+/// otherwise, an llvm::Error carrying llvm::StringError is returned (the Error
+/// message can be converted to string with `llvm::toString()` and the
+/// error_code should be ignored).
+llvm::Expected<std::string>
+applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code,
+ llvm::ArrayRef<AtomicChange> Changes,
+ const ApplyChangesSpec &Spec);
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_ATOMICCHANGE_H