123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===--- 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_REFACTORING_ATOMICCHANGE_H
- #define LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H
- #include "clang/Basic/SourceManager.h"
- #include "clang/Format/Format.h"
- #include "clang/Tooling/Core/Replacement.h"
- #include "llvm/ADT/Any.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);
- AtomicChange(const SourceManager &SM, SourceLocation KeyPosition,
- llvm::Any Metadata);
- /// 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 = std::string(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; }
- Replacements &getReplacements() { return Replaces; }
- llvm::ArrayRef<std::string> getInsertedHeaders() const {
- return InsertedHeaders;
- }
- llvm::ArrayRef<std::string> getRemovedHeaders() const {
- return RemovedHeaders;
- }
- const llvm::Any &getMetadata() const { return Metadata; }
- 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;
- // This field stores metadata which is ignored for the purposes of applying
- // edits to source, but may be useful for other consumers of AtomicChanges. In
- // particular, consumers can use this to direct how they want to consume each
- // edit.
- llvm::Any Metadata;
- };
- 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_REFACTORING_ATOMICCHANGE_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|