//===- Replacement.h - Framework for clang refactoring tools ----*- 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 // //===----------------------------------------------------------------------===// // // Classes supporting refactorings that span multiple translation units. // While single translation unit refactorings are supported via the Rewriter, // when refactoring multiple translation units changes must be stored in a // SourceManager independent form, duplicate changes need to be removed, and // all changes must be applied at once at the end of the refactoring so that // the code is always parseable. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H #define LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" #include "llvm/Support/raw_ostream.h" #include <map> #include <optional> #include <set> #include <string> #include <system_error> #include <utility> #include <vector> namespace clang { class FileManager; class Rewriter; class SourceManager; namespace tooling { /// A source range independent of the \c SourceManager. class Range { … }; /// A text replacement. /// /// Represents a SourceManager independent replacement of a range of text in a /// specific file. class Replacement { … }; enum class replacement_error { … }; /// Carries extra error information in replacement-related llvm::Error, /// e.g. fail applying replacements and replacements conflict. class ReplacementError : public llvm::ErrorInfo<ReplacementError> { … }; /// Less-than operator between two Replacements. bool operator<(const Replacement &LHS, const Replacement &RHS); /// Equal-to operator between two Replacements. bool operator==(const Replacement &LHS, const Replacement &RHS); inline bool operator!=(const Replacement &LHS, const Replacement &RHS) { … } /// Maintains a set of replacements that are conflict-free. /// Two replacements are considered conflicts if they overlap or have the same /// offset (i.e. order-dependent). class Replacements { … }; /// Apply all replacements in \p Replaces to the Rewriter \p Rewrite. /// /// Replacement applications happen independently of the success of /// other applications. /// /// \returns true if all replacements apply. false otherwise. bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite); /// Applies all replacements in \p Replaces to \p Code. /// /// This completely ignores the path stored in each replacement. If all /// replacements are applied successfully, this returns the code with /// replacements applied; otherwise, an llvm::Error carrying llvm::StringError /// is returned (the Error message can be converted to string using /// `llvm::toString()` and 'std::error_code` in the `Error` should be ignored). llvm::Expected<std::string> applyAllReplacements(StringRef Code, const Replacements &Replaces); /// Collection of Replacements generated from a single translation unit. struct TranslationUnitReplacements { … }; /// Calculates the new ranges after \p Replaces are applied. These /// include both the original \p Ranges and the affected ranges of \p Replaces /// in the new code. /// /// \pre Replacements must be for the same file. /// /// \return The new ranges after \p Replaces are applied. The new ranges will be /// sorted and non-overlapping. std::vector<Range> calculateRangesAfterReplacements(const Replacements &Replaces, const std::vector<Range> &Ranges); /// If there are multiple <File, Replacements> pairs with the same file /// entry, we only keep one pair and discard the rest. /// If a file does not exist, its corresponding replacements will be ignored. std::map<std::string, Replacements> groupReplacementsByFile( FileManager &FileMgr, const std::map<std::string, Replacements> &FileToReplaces); template <typename Node> Replacement::Replacement(const SourceManager &Sources, const Node &NodeToReplace, StringRef ReplacementText, const LangOptions &LangOpts) { … } } // namespace tooling } // namespace clang #endif // LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H