aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Tooling
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Tooling')
-rw-r--r--include/clang/Tooling/ASTDiff/ASTDiff.h127
-rw-r--r--include/clang/Tooling/ASTDiff/ASTDiffInternal.h48
-rw-r--r--include/clang/Tooling/CommonOptionsParser.h50
-rw-r--r--include/clang/Tooling/CompilationDatabase.h39
-rw-r--r--include/clang/Tooling/Core/QualTypeNames.h79
-rw-r--r--include/clang/Tooling/Core/Replacement.h2
-rw-r--r--include/clang/Tooling/Execution.h175
-rw-r--r--include/clang/Tooling/Refactoring/ASTSelection.h155
-rw-r--r--include/clang/Tooling/Refactoring/AtomicChange.h44
-rw-r--r--include/clang/Tooling/Refactoring/Extract/Extract.h53
-rw-r--r--include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h12
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringAction.h64
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringActionRule.h74
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h123
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringActionRules.h94
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h158
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringDiagnostic.h30
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringOption.h64
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h62
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringOptions.h58
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringResultConsumer.h52
-rw-r--r--include/clang/Tooling/Refactoring/RefactoringRuleContext.h90
-rw-r--r--include/clang/Tooling/Refactoring/Rename/RenamingAction.h52
-rw-r--r--include/clang/Tooling/Refactoring/Rename/SymbolName.h49
-rw-r--r--include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h91
-rw-r--r--include/clang/Tooling/Refactoring/Rename/USRFindingAction.h14
-rw-r--r--include/clang/Tooling/Refactoring/Rename/USRLocFinder.h12
-rw-r--r--include/clang/Tooling/StandaloneExecution.h97
-rw-r--r--include/clang/Tooling/ToolExecutorPluginRegistry.h24
-rw-r--r--include/clang/Tooling/Tooling.h6
30 files changed, 1889 insertions, 109 deletions
diff --git a/include/clang/Tooling/ASTDiff/ASTDiff.h b/include/clang/Tooling/ASTDiff/ASTDiff.h
new file mode 100644
index 000000000000..dd11c91ac0dd
--- /dev/null
+++ b/include/clang/Tooling/ASTDiff/ASTDiff.h
@@ -0,0 +1,127 @@
+//===- ASTDiff.h - AST differencing API -----------------------*- C++ -*- -===//
+//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file specifies an interface that can be used to compare C++ syntax
+// trees.
+//
+// We use the gumtree algorithm which combines a heuristic top-down search that
+// is able to match large subtrees that are equivalent, with an optimal
+// algorithm to match small subtrees.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFF_H
+#define LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFF_H
+
+#include "clang/Tooling/ASTDiff/ASTDiffInternal.h"
+
+namespace clang {
+namespace diff {
+
+enum ChangeKind {
+ None,
+ Delete, // (Src): delete node Src.
+ Update, // (Src, Dst): update the value of node Src to match Dst.
+ Insert, // (Src, Dst, Pos): insert Src as child of Dst at offset Pos.
+ Move, // (Src, Dst, Pos): move Src to be a child of Dst at offset Pos.
+ UpdateMove // Same as Move plus Update.
+};
+
+/// Represents a Clang AST node, alongside some additional information.
+struct Node {
+ NodeId Parent, LeftMostDescendant, RightMostDescendant;
+ int Depth, Height, Shift = 0;
+ ast_type_traits::DynTypedNode ASTNode;
+ SmallVector<NodeId, 4> Children;
+ ChangeKind Change = None;
+
+ ast_type_traits::ASTNodeKind getType() const;
+ StringRef getTypeLabel() const;
+ bool isLeaf() const { return Children.empty(); }
+ llvm::Optional<StringRef> getIdentifier() const;
+ llvm::Optional<std::string> getQualifiedIdentifier() const;
+};
+
+class ASTDiff {
+public:
+ ASTDiff(SyntaxTree &Src, SyntaxTree &Dst, const ComparisonOptions &Options);
+ ~ASTDiff();
+
+ // Returns the ID of the node that is mapped to the given node in SourceTree.
+ NodeId getMapped(const SyntaxTree &SourceTree, NodeId Id) const;
+
+ class Impl;
+
+private:
+ std::unique_ptr<Impl> DiffImpl;
+};
+
+/// SyntaxTree objects represent subtrees of the AST.
+/// They can be constructed from any Decl or Stmt.
+class SyntaxTree {
+public:
+ /// Constructs a tree from a translation unit.
+ SyntaxTree(ASTContext &AST);
+ /// Constructs a tree from any AST node.
+ template <class T>
+ SyntaxTree(T *Node, ASTContext &AST)
+ : TreeImpl(llvm::make_unique<Impl>(this, Node, AST)) {}
+ SyntaxTree(SyntaxTree &&Other) = default;
+ ~SyntaxTree();
+
+ const ASTContext &getASTContext() const;
+ StringRef getFilename() const;
+
+ int getSize() const;
+ NodeId getRootId() const;
+ using PreorderIterator = NodeId;
+ PreorderIterator begin() const;
+ PreorderIterator end() const;
+
+ const Node &getNode(NodeId Id) const;
+ int findPositionInParent(NodeId Id) const;
+
+ // Returns the starting and ending offset of the node in its source file.
+ std::pair<unsigned, unsigned> getSourceRangeOffsets(const Node &N) const;
+
+ /// Serialize the node attributes to a string representation. This should
+ /// uniquely distinguish nodes of the same kind. Note that this function just
+ /// returns a representation of the node value, not considering descendants.
+ std::string getNodeValue(NodeId Id) const;
+ std::string getNodeValue(const Node &Node) const;
+
+ class Impl;
+ std::unique_ptr<Impl> TreeImpl;
+};
+
+struct ComparisonOptions {
+ /// During top-down matching, only consider nodes of at least this height.
+ int MinHeight = 2;
+
+ /// During bottom-up matching, match only nodes with at least this value as
+ /// the ratio of their common descendants.
+ double MinSimilarity = 0.5;
+
+ /// Whenever two subtrees are matched in the bottom-up phase, the optimal
+ /// mapping is computed, unless the size of either subtrees exceeds this.
+ int MaxSize = 100;
+
+ bool StopAfterTopDown = false;
+
+ /// Returns false if the nodes should never be matched.
+ bool isMatchingAllowed(const Node &N1, const Node &N2) const {
+ return N1.getType().isSame(N2.getType());
+ }
+};
+
+} // end namespace diff
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Tooling/ASTDiff/ASTDiffInternal.h b/include/clang/Tooling/ASTDiff/ASTDiffInternal.h
new file mode 100644
index 000000000000..a76ad37336a6
--- /dev/null
+++ b/include/clang/Tooling/ASTDiff/ASTDiffInternal.h
@@ -0,0 +1,48 @@
+//===- ASTDiffInternal.h --------------------------------------*- C++ -*- -===//
+//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFFINTERNAL_H
+#define LLVM_CLANG_TOOLING_ASTDIFF_ASTDIFFINTERNAL_H
+
+#include "clang/AST/ASTTypeTraits.h"
+
+namespace clang {
+namespace diff {
+
+using DynTypedNode = ast_type_traits::DynTypedNode;
+
+class SyntaxTree;
+class SyntaxTreeImpl;
+struct ComparisonOptions;
+
+/// Within a tree, this identifies a node by its preorder offset.
+struct NodeId {
+private:
+ static constexpr int InvalidNodeId = -1;
+
+public:
+ int Id;
+
+ NodeId() : Id(InvalidNodeId) {}
+ NodeId(int Id) : Id(Id) {}
+
+ operator int() const { return Id; }
+ NodeId &operator++() { return ++Id, *this; }
+ NodeId &operator--() { return --Id, *this; }
+ // Support defining iterators on NodeId.
+ NodeId &operator*() { return *this; }
+
+ bool isValid() const { return Id != InvalidNodeId; }
+ bool isInvalid() const { return Id == InvalidNodeId; }
+};
+
+} // end namespace diff
+} // end namespace clang
+#endif
diff --git a/include/clang/Tooling/CommonOptionsParser.h b/include/clang/Tooling/CommonOptionsParser.h
index 3d630c5f7609..15e8161dd76f 100644
--- a/include/clang/Tooling/CommonOptionsParser.h
+++ b/include/clang/Tooling/CommonOptionsParser.h
@@ -27,8 +27,10 @@
#ifndef LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H
#define LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H
+#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
namespace clang {
namespace tooling {
@@ -84,14 +86,19 @@ public:
///
/// All options not belonging to \p Category become hidden.
///
- /// I also allows calls to set the required number of positional parameters.
- ///
- /// This constructor exits program in case of error.
+ /// It also allows calls to set the required number of positional parameters.
CommonOptionsParser(int &argc, const char **argv,
llvm::cl::OptionCategory &Category,
llvm::cl::NumOccurrencesFlag OccurrencesFlag,
const char *Overview = nullptr);
+ /// \brief A factory method that is similar to the above constructor, except
+ /// this returns an error instead exiting the program on error.
+ static llvm::Expected<CommonOptionsParser>
+ create(int &argc, const char **argv, llvm::cl::OptionCategory &Category,
+ llvm::cl::NumOccurrencesFlag OccurrencesFlag,
+ const char *Overview = nullptr);
+
/// Returns a reference to the loaded compilations database.
CompilationDatabase &getCompilations() {
return *Compilations;
@@ -102,13 +109,46 @@ public:
return SourcePathList;
}
+ /// Returns the argument adjuster calculated from "--extra-arg" and
+ //"--extra-arg-before" options.
+ ArgumentsAdjuster getArgumentsAdjuster() { return Adjuster; }
+
static const char *const HelpMessage;
private:
+ CommonOptionsParser() = default;
+
+ llvm::Error init(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ llvm::cl::NumOccurrencesFlag OccurrencesFlag,
+ const char *Overview);
+
std::unique_ptr<CompilationDatabase> Compilations;
std::vector<std::string> SourcePathList;
- std::vector<std::string> ExtraArgsBefore;
- std::vector<std::string> ExtraArgsAfter;
+ ArgumentsAdjuster Adjuster;
+};
+
+class ArgumentsAdjustingCompilations : public CompilationDatabase {
+public:
+ ArgumentsAdjustingCompilations(
+ std::unique_ptr<CompilationDatabase> Compilations)
+ : Compilations(std::move(Compilations)) {}
+
+ void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster);
+
+ std::vector<CompileCommand>
+ getCompileCommands(StringRef FilePath) const override;
+
+ std::vector<std::string> getAllFiles() const override;
+
+ std::vector<CompileCommand> getAllCompileCommands() const override;
+
+private:
+ std::unique_ptr<CompilationDatabase> Compilations;
+ std::vector<ArgumentsAdjuster> Adjusters;
+
+ std::vector<CompileCommand>
+ adjustCommands(std::vector<CompileCommand> Commands) const;
};
} // namespace tooling
diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h
index e988b84b6eae..bc3e67b77de2 100644
--- a/include/clang/Tooling/CompilationDatabase.h
+++ b/include/clang/Tooling/CompilationDatabase.h
@@ -64,10 +64,12 @@ struct CompileCommand {
/// \brief Interface for compilation databases.
///
-/// A compilation database allows the user to retrieve all compile command lines
-/// that a specified file is compiled with in a project.
-/// The retrieved compile command lines can be used to run clang tools over
-/// a subset of the files in a project.
+/// A compilation database allows the user to retrieve compile command lines
+/// for the files in a project.
+///
+/// Many implementations are enumerable, allowing all command lines to be
+/// retrieved. These can be used to run clang tools over a subset of the files
+/// in a project.
class CompilationDatabase {
public:
virtual ~CompilationDatabase();
@@ -104,7 +106,7 @@ public:
/// \brief Returns all compile commands in which the specified file was
/// compiled.
///
- /// This includes compile comamnds that span multiple source files.
+ /// This includes compile commands that span multiple source files.
/// For example, consider a project with the following compilations:
/// $ clang++ -o test a.cc b.cc t.cc
/// $ clang++ -o production a.cc b.cc -DPRODUCTION
@@ -114,7 +116,10 @@ public:
StringRef FilePath) const = 0;
/// \brief Returns the list of all files available in the compilation database.
- virtual std::vector<std::string> getAllFiles() const = 0;
+ ///
+ /// By default, returns nothing. Implementations should override this if they
+ /// can enumerate their source files.
+ virtual std::vector<std::string> getAllFiles() const { return {}; }
/// \brief Returns all compile commands for all the files in the compilation
/// database.
@@ -122,7 +127,10 @@ public:
/// FIXME: Add a layer in Tooling that provides an interface to run a tool
/// over all files in a compilation database. Not all build systems have the
/// ability to provide a feasible implementation for \c getAllCompileCommands.
- virtual std::vector<CompileCommand> getAllCompileCommands() const = 0;
+ ///
+ /// By default, this is implemented in terms of getAllFiles() and
+ /// getCompileCommands(). Subclasses may override this for efficiency.
+ virtual std::vector<CompileCommand> getAllCompileCommands() const;
};
/// \brief Interface for compilation database plugins.
@@ -149,6 +157,7 @@ public:
/// \brief A compilation database that returns a single compile command line.
///
/// Useful when we want a tool to behave more like a compiler invocation.
+/// This compilation database is not enumerable: getAllFiles() returns {}.
class FixedCompilationDatabase : public CompilationDatabase {
public:
/// \brief Creates a FixedCompilationDatabase from the arguments after "--".
@@ -182,6 +191,11 @@ public:
int &Argc, const char *const *Argv, std::string &ErrorMsg,
Twine Directory = ".");
+ /// Reads flags from the given file, one-per line.
+ /// Returns nullptr and sets ErrorMessage if we can't read the file.
+ static std::unique_ptr<FixedCompilationDatabase>
+ loadFromFile(StringRef Path, std::string &ErrorMsg);
+
/// \brief Constructs a compilation data base from a specified directory
/// and command line.
FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine);
@@ -194,17 +208,6 @@ public:
std::vector<CompileCommand>
getCompileCommands(StringRef FilePath) const override;
- /// \brief Returns the list of all files available in the compilation database.
- ///
- /// Note: This is always an empty list for the fixed compilation database.
- std::vector<std::string> getAllFiles() const override;
-
- /// \brief Returns all compile commands for all the files in the compilation
- /// database.
- ///
- /// Note: This is always an empty list for the fixed compilation database.
- std::vector<CompileCommand> getAllCompileCommands() const override;
-
private:
/// This is built up to contain a single entry vector to be returned from
/// getCompileCommands after adding the positional argument.
diff --git a/include/clang/Tooling/Core/QualTypeNames.h b/include/clang/Tooling/Core/QualTypeNames.h
deleted file mode 100644
index 7248356e748e..000000000000
--- a/include/clang/Tooling/Core/QualTypeNames.h
+++ /dev/null
@@ -1,79 +0,0 @@
-//===--- QualTypeNames.h - Generate Complete QualType Names ----*- C++ -*-===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-// ===----------------------------------------------------------------------===//
-//
-// \file
-// Functionality to generate the fully-qualified names of QualTypes,
-// including recursively expanding any subtypes and template
-// parameters.
-//
-// More precisely: Generates a name that can be used to name the same
-// type if used at the end of the current translation unit--with
-// certain limitations. See below.
-//
-// This code desugars names only very minimally, so in this code:
-//
-// namespace A {
-// struct X {};
-// }
-// using A::X;
-// namespace B {
-// using std::tuple;
-// typedef tuple<X> TX;
-// TX t;
-// }
-//
-// B::t's type is reported as "B::TX", rather than std::tuple<A::X>.
-//
-// Also, this code replaces types found via using declarations with
-// their more qualified name, so for the code:
-//
-// using std::tuple;
-// tuple<int> TInt;
-//
-// TInt's type will be named, "std::tuple<int>".
-//
-// Limitations:
-//
-// Some types have ambiguous names at the end of a translation unit,
-// are not namable at all there, or are special cases in other ways.
-//
-// 1) Types with only local scope will have their local names:
-//
-// void foo() {
-// struct LocalType {} LocalVar;
-// }
-//
-// LocalVar's type will be named, "struct LocalType", without any
-// qualification.
-//
-// 2) Types that have been shadowed are reported normally, but a
-// client using that name at the end of the translation unit will be
-// referring to a different type.
-//
-// ===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H
-#define LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H
-
-#include "clang/AST/ASTContext.h"
-
-namespace clang {
-namespace TypeName {
-/// \brief Get the fully qualified name for a type. This includes full
-/// qualification of all template parameters etc.
-///
-/// \param[in] QT - the type for which the fully qualified name will be
-/// returned.
-/// \param[in] Ctx - the ASTContext to be used.
-/// \param[in] WithGlobalNsPrefix - If true, then the global namespace
-/// specifier "::" will be prepended to the fully qualified name.
-std::string getFullyQualifiedName(QualType QT,
- const ASTContext &Ctx,
- bool WithGlobalNsPrefix = false);
-} // end namespace TypeName
-} // end namespace clang
-#endif // LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H
diff --git a/include/clang/Tooling/Core/Replacement.h b/include/clang/Tooling/Core/Replacement.h
index 8d4a22adf368..3fea9aee604c 100644
--- a/include/clang/Tooling/Core/Replacement.h
+++ b/include/clang/Tooling/Core/Replacement.h
@@ -255,7 +255,7 @@ class Replacements {
/// \brief Merges \p Replaces into the current replacements. \p Replaces
/// refers to code after applying the current replacements.
- Replacements merge(const Replacements &Replaces) const;
+ LLVM_NODISCARD Replacements merge(const Replacements &Replaces) const;
// Returns the affected ranges in the changed code.
std::vector<Range> getAffectedRanges() const;
diff --git a/include/clang/Tooling/Execution.h b/include/clang/Tooling/Execution.h
new file mode 100644
index 000000000000..1a44c4788c49
--- /dev/null
+++ b/include/clang/Tooling/Execution.h
@@ -0,0 +1,175 @@
+//===--- Execution.h - Executing clang frontend actions -*- C++ ---------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines framework for executing clang frontend actions.
+//
+// The framework can be extended to support different execution plans including
+// standalone execution on the given TUs or parallel execution on all TUs in
+// the codebase.
+//
+// In order to enable multiprocessing execution, tool actions are expected to
+// output result into the ToolResults provided by the executor. The
+// `ToolResults` is an interface that abstracts how results are stored e.g.
+// in-memory for standalone execution or on-disk for large-scale execution.
+//
+// New executors can be registered as ToolExecutorPlugins via the
+// `ToolExecutorPluginRegistry`. CLI tools can use
+// `createExecutorFromCommandLineArgs` to create a specific registered executor
+// according to the command-line arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_EXECUTION_H
+#define LLVM_CLANG_TOOLING_EXECUTION_H
+
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang {
+namespace tooling {
+
+/// \brief An abstraction for the result of a tool execution. For example, the
+/// underlying result can be in-memory or on-disk.
+///
+/// Results should be string key-value pairs. For example, a refactoring tool
+/// can use source location as key and a replacement in YAML format as value.
+class ToolResults {
+public:
+ virtual ~ToolResults() = default;
+ virtual void addResult(StringRef Key, StringRef Value) = 0;
+ virtual std::vector<std::pair<std::string, std::string>> AllKVResults() = 0;
+ virtual void forEachResult(
+ llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) = 0;
+};
+
+class InMemoryToolResults : public ToolResults {
+public:
+ void addResult(StringRef Key, StringRef Value) override;
+ std::vector<std::pair<std::string, std::string>> AllKVResults() override;
+ void forEachResult(llvm::function_ref<void(StringRef Key, StringRef Value)>
+ Callback) override;
+
+private:
+ std::vector<std::pair<std::string, std::string>> KVResults;
+};
+
+/// \brief The context of an execution, including the information about
+/// compilation and results.
+class ExecutionContext {
+public:
+ virtual ~ExecutionContext() {}
+
+ /// \brief Initializes a context. This does not take ownership of `Results`.
+ explicit ExecutionContext(ToolResults *Results) : Results(Results) {}
+
+ /// \brief Adds a KV pair to the result container of this execution.
+ void reportResult(StringRef Key, StringRef Value);
+
+ // Returns the source control system's revision number if applicable.
+ // Otherwise returns an empty string.
+ virtual std::string getRevision() { return ""; }
+
+ // Returns the corpus being analyzed, e.g. "llvm" for the LLVM codebase, if
+ // applicable.
+ virtual std::string getCorpus() { return ""; }
+
+ // Returns the currently processed compilation unit if available.
+ virtual std::string getCurrentCompilationUnit() { return ""; }
+
+private:
+ ToolResults *Results;
+};
+
+/// \brief Interface for executing clang frontend actions.
+///
+/// This can be extended to support running tool actions in different
+/// execution mode, e.g. on a specific set of TUs or many TUs in parallel.
+///
+/// New executors can be registered as ToolExecutorPlugins via the
+/// `ToolExecutorPluginRegistry`. CLI tools can use
+/// `createExecutorFromCommandLineArgs` to create a specific registered
+/// executor according to the command-line arguments.
+class ToolExecutor {
+public:
+ virtual ~ToolExecutor() {}
+
+ /// \brief Returns the name of a specific executor.
+ virtual StringRef getExecutorName() const = 0;
+
+ /// \brief Executes each action with a corresponding arguments adjuster.
+ virtual llvm::Error
+ execute(llvm::ArrayRef<
+ std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
+ Actions) = 0;
+
+ /// \brief Convenient functions for the above `execute`.
+ llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action);
+ /// Executes an action with an argument adjuster.
+ llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action,
+ ArgumentsAdjuster Adjuster);
+
+ /// \brief Returns a reference to the execution context.
+ ///
+ /// This should be passed to tool callbacks, and tool callbacks should report
+ /// results via the returned context.
+ virtual ExecutionContext *getExecutionContext() = 0;
+
+ /// \brief Returns a reference to the result container.
+ ///
+ /// NOTE: This should only be used after the execution finishes. Tool
+ /// callbacks should report results via `ExecutionContext` instead.
+ virtual ToolResults *getToolResults() = 0;
+
+ /// \brief Map a virtual file to be used while running the tool.
+ ///
+ /// \param FilePath The path at which the content will be mapped.
+ /// \param Content A buffer of the file's content.
+ virtual void mapVirtualFile(StringRef FilePath, StringRef Content) = 0;
+};
+
+/// \brief Interface for factories that create specific executors. This is also
+/// used as a plugin to be registered into ToolExecutorPluginRegistry.
+class ToolExecutorPlugin {
+public:
+ virtual ~ToolExecutorPlugin() {}
+
+ /// \brief Create an `ToolExecutor`.
+ ///
+ /// `OptionsParser` can be consumed (e.g. moved) if the creation succeeds.
+ virtual llvm::Expected<std::unique_ptr<ToolExecutor>>
+ create(CommonOptionsParser &OptionsParser) = 0;
+};
+
+/// \brief This creates a ToolExecutor that is in the global registry based on
+/// commandline arguments.
+///
+/// This picks the right executor based on the `--executor` option. This parses
+/// the commandline arguments with `CommonOptionsParser`, so caller does not
+/// need to parse again.
+///
+/// By default, this creates a `StandaloneToolExecutor` ("standalone") if
+/// `--executor` is not provided.
+llvm::Expected<std::unique_ptr<ToolExecutor>>
+createExecutorFromCommandLineArgs(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ const char *Overview = nullptr);
+
+namespace internal {
+llvm::Expected<std::unique_ptr<ToolExecutor>>
+createExecutorFromCommandLineArgsImpl(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ const char *Overview = nullptr);
+} // end namespace internal
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_EXECUTION_H
diff --git a/include/clang/Tooling/Refactoring/ASTSelection.h b/include/clang/Tooling/Refactoring/ASTSelection.h
new file mode 100644
index 000000000000..aa02a6899e8f
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/ASTSelection.h
@@ -0,0 +1,155 @@
+//===--- ASTSelection.h - Clang refactoring library -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H
+#define LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H
+
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include <vector>
+
+namespace clang {
+
+class ASTContext;
+
+namespace tooling {
+
+enum class SourceSelectionKind {
+ /// A node that's not selected.
+ None,
+
+ /// A node that's considered to be selected because the whole selection range
+ /// is inside of its source range.
+ ContainsSelection,
+ /// A node that's considered to be selected because the start of the selection
+ /// range is inside its source range.
+ ContainsSelectionStart,
+ /// A node that's considered to be selected because the end of the selection
+ /// range is inside its source range.
+ ContainsSelectionEnd,
+
+ /// A node that's considered to be selected because the node is entirely in
+ /// the selection range.
+ InsideSelection,
+};
+
+/// Represents a selected AST node.
+///
+/// AST selection is represented using a tree of \c SelectedASTNode. The tree
+/// follows the top-down shape of the actual AST. Each selected node has
+/// a selection kind. The kind might be none as the node itself might not
+/// actually be selected, e.g. a statement in macro whose child is in a macro
+/// argument.
+struct SelectedASTNode {
+ ast_type_traits::DynTypedNode Node;
+ SourceSelectionKind SelectionKind;
+ std::vector<SelectedASTNode> Children;
+
+ SelectedASTNode(const ast_type_traits::DynTypedNode &Node,
+ SourceSelectionKind SelectionKind)
+ : Node(Node), SelectionKind(SelectionKind) {}
+ SelectedASTNode(SelectedASTNode &&) = default;
+ SelectedASTNode &operator=(SelectedASTNode &&) = default;
+
+ void dump(llvm::raw_ostream &OS = llvm::errs()) const;
+
+ using ReferenceType = std::reference_wrapper<const SelectedASTNode>;
+};
+
+/// Traverses the given ASTContext and creates a tree of selected AST nodes.
+///
+/// \returns None if no nodes are selected in the AST, or a selected AST node
+/// that corresponds to the TranslationUnitDecl otherwise.
+Optional<SelectedASTNode> findSelectedASTNodes(const ASTContext &Context,
+ SourceRange SelectionRange);
+
+/// An AST selection value that corresponds to a selection of a set of
+/// statements that belong to one body of code (like one function).
+///
+/// For example, the following selection in the source.
+///
+/// \code
+/// void function() {
+/// // selection begin:
+/// int x = 0;
+/// {
+/// // selection end
+/// x = 1;
+/// }
+/// x = 2;
+/// }
+/// \endcode
+///
+/// Would correspond to a code range selection of statements "int x = 0"
+/// and the entire compound statement that follows it.
+///
+/// A \c CodeRangeASTSelection value stores references to the full
+/// \c SelectedASTNode tree and should not outlive it.
+class CodeRangeASTSelection {
+public:
+ CodeRangeASTSelection(CodeRangeASTSelection &&) = default;
+ CodeRangeASTSelection &operator=(CodeRangeASTSelection &&) = default;
+
+ /// Returns the parent hierarchy (top to bottom) for the selected nodes.
+ ArrayRef<SelectedASTNode::ReferenceType> getParents() { return Parents; }
+
+ /// Returns the number of selected statements.
+ size_t size() const {
+ if (!AreChildrenSelected)
+ return 1;
+ return SelectedNode.get().Children.size();
+ }
+
+ const Stmt *operator[](size_t I) const {
+ if (!AreChildrenSelected) {
+ assert(I == 0 && "Invalid index");
+ return SelectedNode.get().Node.get<Stmt>();
+ }
+ return SelectedNode.get().Children[I].Node.get<Stmt>();
+ }
+
+ /// Returns true when a selected code range is in a function-like body
+ /// of code, like a function, method or a block.
+ ///
+ /// This function can be used to test against selected expressions that are
+ /// located outside of a function, e.g. global variable initializers, default
+ /// argument values, or even template arguments.
+ ///
+ /// Use the \c getFunctionLikeNearestParent to get the function-like parent
+ /// declaration.
+ bool isInFunctionLikeBodyOfCode() const;
+
+ /// Returns the nearest function-like parent declaration or null if such
+ /// declaration doesn't exist.
+ const Decl *getFunctionLikeNearestParent() const;
+
+ static Optional<CodeRangeASTSelection>
+ create(SourceRange SelectionRange, const SelectedASTNode &ASTSelection);
+
+private:
+ CodeRangeASTSelection(SelectedASTNode::ReferenceType SelectedNode,
+ ArrayRef<SelectedASTNode::ReferenceType> Parents,
+ bool AreChildrenSelected)
+ : SelectedNode(SelectedNode), Parents(Parents.begin(), Parents.end()),
+ AreChildrenSelected(AreChildrenSelected) {}
+
+ /// The reference to the selected node (or reference to the selected
+ /// child nodes).
+ SelectedASTNode::ReferenceType SelectedNode;
+ /// The parent hierarchy (top to bottom) for the selected noe.
+ llvm::SmallVector<SelectedASTNode::ReferenceType, 8> Parents;
+ /// True only when the children of the selected node are actually selected.
+ bool AreChildrenSelected;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_AST_SELECTION_H
diff --git a/include/clang/Tooling/Refactoring/AtomicChange.h b/include/clang/Tooling/Refactoring/AtomicChange.h
index 9cccd78677b1..8a468a6de84e 100644
--- a/include/clang/Tooling/Refactoring/AtomicChange.h
+++ b/include/clang/Tooling/Refactoring/AtomicChange.h
@@ -16,6 +16,7 @@
#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"
@@ -45,6 +46,14 @@ public:
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;
+
/// \brief Returns the atomic change as a YAML string.
std::string toYAMLString();
@@ -129,6 +138,41 @@ private:
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;
+};
+
+/// \brief 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
diff --git a/include/clang/Tooling/Refactoring/Extract/Extract.h b/include/clang/Tooling/Refactoring/Extract/Extract.h
new file mode 100644
index 000000000000..2fd76d252c62
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/Extract/Extract.h
@@ -0,0 +1,53 @@
+//===--- Extract.h - Clang refactoring library ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_EXTRACT_EXTRACT_H
+#define LLVM_CLANG_TOOLING_REFACTOR_EXTRACT_EXTRACT_H
+
+#include "clang/Tooling/Refactoring/ASTSelection.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRules.h"
+
+namespace clang {
+namespace tooling {
+
+/// An "Extract Function" refactoring moves code into a new function that's
+/// then called from the place where the original code was.
+class ExtractFunction final : public SourceChangeRefactoringRule {
+public:
+ /// Initiates the extract function refactoring operation.
+ ///
+ /// \param Code The selected set of statements.
+ /// \param DeclName The name name of the extract function. If None,
+ /// "extracted" is used.
+ static Expected<ExtractFunction> initiate(RefactoringRuleContext &Context,
+ CodeRangeASTSelection Code,
+ Optional<std::string> DeclName);
+
+ static const RefactoringDescriptor &describe();
+
+private:
+ ExtractFunction(CodeRangeASTSelection Code, Optional<std::string> DeclName)
+ : Code(std::move(Code)),
+ DeclName(DeclName ? std::move(*DeclName) : "extracted") {}
+
+ Expected<AtomicChanges>
+ createSourceReplacements(RefactoringRuleContext &Context) override;
+
+ CodeRangeASTSelection Code;
+
+ // FIXME: Account for naming collisions:
+ // - error when name is specified by user.
+ // - rename to "extractedN" when name is implicit.
+ std::string DeclName;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_EXTRACT_EXTRACT_H
diff --git a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
index 8b01a61256f6..d96ad78ad876 100644
--- a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
+++ b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
@@ -70,6 +70,18 @@ public:
return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc());
}
+ bool VisitOffsetOfExpr(const OffsetOfExpr *S) {
+ for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
+ const OffsetOfNode &Component = S->getComponent(I);
+ if (Component.getKind() == OffsetOfNode::Field) {
+ if (!visit(Component.getField(), Component.getLocEnd()))
+ return false;
+ }
+ // FIXME: Try to resolve dependent field references.
+ }
+ return true;
+ }
+
// Other visitors:
bool VisitTypeLoc(const TypeLoc Loc) {
diff --git a/include/clang/Tooling/Refactoring/RefactoringAction.h b/include/clang/Tooling/Refactoring/RefactoringAction.h
new file mode 100644
index 000000000000..c4080237f1c3
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringAction.h
@@ -0,0 +1,64 @@
+//===--- RefactoringAction.h - Clang refactoring library ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRules.h"
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+/// A refactoring action is a class that defines a set of related refactoring
+/// action rules. These rules get grouped under a common umbrella - a single
+/// clang-refactor subcommand.
+///
+/// A subclass of \c RefactoringAction is responsible for creating the set of
+/// grouped refactoring action rules that represent one refactoring operation.
+/// Although the rules in one action may have a number of different
+/// implementations, they should strive to produce a similar result. It should
+/// be easy for users to identify which refactoring action produced the result
+/// regardless of which refactoring action rule was used.
+///
+/// The distinction between actions and rules enables the creation of action
+/// that uses very different rules, for example:
+/// - local vs global: a refactoring operation like
+/// "add missing switch cases" can be applied to one switch when it's
+/// selected in an editor, or to all switches in a project when an enum
+/// constant is added to an enum.
+/// - tool vs editor: some refactoring operation can be initiated in the
+/// editor when a declaration is selected, or in a tool when the name of
+/// the declaration is passed using a command-line argument.
+class RefactoringAction {
+public:
+ virtual ~RefactoringAction() {}
+
+ /// Returns the name of the subcommand that's used by clang-refactor for this
+ /// action.
+ virtual StringRef getCommand() const = 0;
+
+ virtual StringRef getDescription() const = 0;
+
+ RefactoringActionRules createActiveActionRules();
+
+protected:
+ /// Returns a set of refactoring actions rules that are defined by this
+ /// action.
+ virtual RefactoringActionRules createActionRules() const = 0;
+};
+
+/// Returns the list of all the available refactoring actions.
+std::vector<std::unique_ptr<RefactoringAction>> createRefactoringActions();
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_H
diff --git a/include/clang/Tooling/Refactoring/RefactoringActionRule.h b/include/clang/Tooling/Refactoring/RefactoringActionRule.h
new file mode 100644
index 000000000000..4130e29d8dea
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringActionRule.h
@@ -0,0 +1,74 @@
+//===--- RefactoringActionRule.h - Clang refactoring library -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+class RefactoringOptionVisitor;
+class RefactoringResultConsumer;
+class RefactoringRuleContext;
+
+struct RefactoringDescriptor {
+ /// A unique identifier for the specific refactoring.
+ StringRef Name;
+ /// A human readable title for the refactoring.
+ StringRef Title;
+ /// A human readable description of what the refactoring does.
+ StringRef Description;
+};
+
+/// A common refactoring action rule interface that defines the 'invoke'
+/// function that performs the refactoring operation (either fully or
+/// partially).
+class RefactoringActionRuleBase {
+public:
+ virtual ~RefactoringActionRuleBase() {}
+
+ /// Initiates and performs a specific refactoring action.
+ ///
+ /// The specific rule will invoke an appropriate \c handle method on a
+ /// consumer to propagate the result of the refactoring action.
+ virtual void invoke(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context) = 0;
+
+ /// Returns the structure that describes the refactoring.
+ // static const RefactoringDescriptor &describe() = 0;
+};
+
+/// A refactoring action rule is a wrapper class around a specific refactoring
+/// action rule (SourceChangeRefactoringRule, etc) that, in addition to invoking
+/// the action, describes the requirements that determine when the action can be
+/// initiated.
+class RefactoringActionRule : public RefactoringActionRuleBase {
+public:
+ /// Returns true when the rule has a source selection requirement that has
+ /// to be fullfilled before refactoring can be performed.
+ virtual bool hasSelectionRequirement() = 0;
+
+ /// Traverses each refactoring option used by the rule and invokes the
+ /// \c visit callback in the consumer for each option.
+ ///
+ /// Options are visited in the order of use, e.g. if a rule has two
+ /// requirements that use options, the options from the first requirement
+ /// are visited before the options in the second requirement.
+ virtual void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) = 0;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_H
diff --git a/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h b/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h
new file mode 100644
index 000000000000..355a6a55f22f
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h
@@ -0,0 +1,123 @@
+//===--- RefactoringActionRuleRequirements.h - Clang refactoring library --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_REQUIREMENTS_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_REQUIREMENTS_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/ASTSelection.h"
+#include "clang/Tooling/Refactoring/RefactoringDiagnostic.h"
+#include "clang/Tooling/Refactoring/RefactoringOption.h"
+#include "clang/Tooling/Refactoring/RefactoringRuleContext.h"
+#include "llvm/Support/Error.h"
+#include <type_traits>
+
+namespace clang {
+namespace tooling {
+
+/// A refactoring action rule requirement determines when a refactoring action
+/// rule can be invoked. The rule can be invoked only when all of the
+/// requirements are satisfied.
+///
+/// Subclasses must implement the
+/// 'Expected<T> evaluate(RefactoringRuleContext &) const' member function.
+/// \c T is used to determine the return type that is passed to the
+/// refactoring rule's constructor.
+/// For example, the \c SourceRangeSelectionRequirement subclass defines
+/// 'Expected<SourceRange> evaluate(RefactoringRuleContext &Context) const'
+/// function. When this function returns a non-error value, the resulting
+/// source range is passed to the specific refactoring action rule
+/// constructor (provided all other requirements are satisfied).
+class RefactoringActionRuleRequirement {
+ // Expected<T> evaluate(RefactoringRuleContext &Context) const;
+};
+
+/// A base class for any requirement that expects some part of the source to be
+/// selected in an editor (or the refactoring tool with the -selection option).
+class SourceSelectionRequirement : public RefactoringActionRuleRequirement {};
+
+/// A selection requirement that is satisfied when any portion of the source
+/// text is selected.
+class SourceRangeSelectionRequirement : public SourceSelectionRequirement {
+public:
+ Expected<SourceRange> evaluate(RefactoringRuleContext &Context) const {
+ if (Context.getSelectionRange().isValid())
+ return Context.getSelectionRange();
+ return Context.createDiagnosticError(diag::err_refactor_no_selection);
+ }
+};
+
+/// An AST selection requirement is satisfied when any portion of the AST
+/// overlaps with the selection range.
+///
+/// The requirement will be evaluated only once during the initiation and
+/// search of matching refactoring action rules.
+class ASTSelectionRequirement : public SourceRangeSelectionRequirement {
+public:
+ Expected<SelectedASTNode> evaluate(RefactoringRuleContext &Context) const;
+};
+
+/// A selection requirement that is satisfied when the selection range overlaps
+/// with a number of neighbouring statements in the AST. The statemenst must be
+/// contained in declaration like a function. The selection range must be a
+/// non-empty source selection (i.e. cursors won't be accepted).
+///
+/// The requirement will be evaluated only once during the initiation and search
+/// of matching refactoring action rules.
+///
+/// \see CodeRangeASTSelection
+class CodeRangeASTSelectionRequirement : public ASTSelectionRequirement {
+public:
+ Expected<CodeRangeASTSelection>
+ evaluate(RefactoringRuleContext &Context) const;
+};
+
+/// A base class for any requirement that requires some refactoring options.
+class RefactoringOptionsRequirement : public RefactoringActionRuleRequirement {
+public:
+ virtual ~RefactoringOptionsRequirement() {}
+
+ /// Returns the set of refactoring options that are used when evaluating this
+ /// requirement.
+ virtual ArrayRef<std::shared_ptr<RefactoringOption>>
+ getRefactoringOptions() const = 0;
+};
+
+/// A requirement that evaluates to the value of the given \c OptionType when
+/// the \c OptionType is a required option. When the \c OptionType is an
+/// optional option, the requirement will evaluate to \c None if the option is
+/// not specified or to an appropriate value otherwise.
+template <typename OptionType>
+class OptionRequirement : public RefactoringOptionsRequirement {
+public:
+ OptionRequirement() : Opt(createRefactoringOption<OptionType>()) {}
+
+ ArrayRef<std::shared_ptr<RefactoringOption>>
+ getRefactoringOptions() const final override {
+ return Opt;
+ }
+
+ Expected<typename OptionType::ValueType>
+ evaluate(RefactoringRuleContext &) const {
+ return static_cast<OptionType *>(Opt.get())->getValue();
+ }
+
+private:
+ /// The partially-owned option.
+ ///
+ /// The ownership of the option is shared among the different requirements
+ /// because the same option can be used by multiple rules in one refactoring
+ /// action.
+ std::shared_ptr<RefactoringOption> Opt;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_REQUIREMENTS_H
diff --git a/include/clang/Tooling/Refactoring/RefactoringActionRules.h b/include/clang/Tooling/Refactoring/RefactoringActionRules.h
new file mode 100644
index 000000000000..33206d9a5dd1
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringActionRules.h
@@ -0,0 +1,94 @@
+//===--- RefactoringActionRules.h - Clang refactoring library -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_H
+
+#include "clang/Tooling/Refactoring/RefactoringActionRule.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRulesInternal.h"
+
+namespace clang {
+namespace tooling {
+
+/// Creates a new refactoring action rule that constructs and invokes the
+/// \c RuleType rule when all of the requirements are satisfied.
+///
+/// This function takes in a list of values whose type derives from
+/// \c RefactoringActionRuleRequirement. These values describe the initiation
+/// requirements that have to be satisfied by the refactoring engine before
+/// the provided action rule can be constructed and invoked. The engine
+/// verifies that the requirements are satisfied by evaluating them (using the
+/// 'evaluate' member function) and checking that the results don't contain
+/// any errors. Once all requirements are satisfied, the provided refactoring
+/// rule is constructed by passing in the values returned by the requirements'
+/// evaluate functions as arguments to the constructor. The rule is then invoked
+/// immediately after construction.
+///
+/// The separation of requirements, their evaluation and the invocation of the
+/// refactoring action rule allows the refactoring clients to:
+/// - Disable refactoring action rules whose requirements are not supported.
+/// - Gather the set of options and define a command-line / visual interface
+/// that allows users to input these options without ever invoking the
+/// action.
+template <typename RuleType, typename... RequirementTypes>
+std::unique_ptr<RefactoringActionRule>
+createRefactoringActionRule(const RequirementTypes &... Requirements);
+
+/// A set of refactoring action rules that should have unique initiation
+/// requirements.
+using RefactoringActionRules =
+ std::vector<std::unique_ptr<RefactoringActionRule>>;
+
+/// A type of refactoring action rule that produces source replacements in the
+/// form of atomic changes.
+///
+/// This action rule is typically used for local refactorings that replace
+/// source in a single AST unit.
+class SourceChangeRefactoringRule : public RefactoringActionRuleBase {
+public:
+ void invoke(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context) final override {
+ Expected<AtomicChanges> Changes = createSourceReplacements(Context);
+ if (!Changes)
+ Consumer.handleError(Changes.takeError());
+ else
+ Consumer.handle(std::move(*Changes));
+ }
+
+private:
+ virtual Expected<AtomicChanges>
+ createSourceReplacements(RefactoringRuleContext &Context) = 0;
+};
+
+/// A type of refactoring action rule that finds a set of symbol occurrences
+/// that reference a particular symbol.
+///
+/// This action rule is typically used for an interactive rename that allows
+/// users to specify the new name and the set of selected occurrences during
+/// the refactoring.
+class FindSymbolOccurrencesRefactoringRule : public RefactoringActionRuleBase {
+public:
+ void invoke(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context) final override {
+ Expected<SymbolOccurrences> Occurrences = findSymbolOccurrences(Context);
+ if (!Occurrences)
+ Consumer.handleError(Occurrences.takeError());
+ else
+ Consumer.handle(std::move(*Occurrences));
+ }
+
+private:
+ virtual Expected<SymbolOccurrences>
+ findSymbolOccurrences(RefactoringRuleContext &Context) = 0;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_H
diff --git a/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h b/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
new file mode 100644
index 000000000000..75b6c8f70d17
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
@@ -0,0 +1,158 @@
+//===--- RefactoringActionRulesInternal.h - Clang refactoring library -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRule.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h"
+#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
+#include "clang/Tooling/Refactoring/RefactoringRuleContext.h"
+#include "llvm/Support/Error.h"
+#include <type_traits>
+
+namespace clang {
+namespace tooling {
+namespace internal {
+
+inline llvm::Error findError() { return llvm::Error::success(); }
+
+inline void ignoreError() {}
+
+template <typename FirstT, typename... RestT>
+void ignoreError(Expected<FirstT> &First, Expected<RestT> &... Rest) {
+ if (!First)
+ llvm::consumeError(First.takeError());
+ ignoreError(Rest...);
+}
+
+/// Scans the tuple and returns a valid \c Error if any of the values are
+/// invalid.
+template <typename FirstT, typename... RestT>
+llvm::Error findError(Expected<FirstT> &First, Expected<RestT> &... Rest) {
+ if (!First) {
+ ignoreError(Rest...);
+ return First.takeError();
+ }
+ return findError(Rest...);
+}
+
+template <typename RuleType, typename... RequirementTypes, size_t... Is>
+void invokeRuleAfterValidatingRequirements(
+ RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context,
+ const std::tuple<RequirementTypes...> &Requirements,
+ llvm::index_sequence<Is...>) {
+ // Check if the requirements we're interested in can be evaluated.
+ auto Values =
+ std::make_tuple(std::get<Is>(Requirements).evaluate(Context)...);
+ auto Err = findError(std::get<Is>(Values)...);
+ if (Err)
+ return Consumer.handleError(std::move(Err));
+ // Construct the target action rule by extracting the evaluated
+ // requirements from Expected<> wrappers and then run it.
+ auto Rule =
+ RuleType::initiate(Context, std::move((*std::get<Is>(Values)))...);
+ if (!Rule)
+ return Consumer.handleError(Rule.takeError());
+ Rule->invoke(Consumer, Context);
+}
+
+inline void visitRefactoringOptionsImpl(RefactoringOptionVisitor &) {}
+
+/// Scans the list of requirements in a rule and visits all the refactoring
+/// options that are used by all the requirements.
+template <typename FirstT, typename... RestT>
+void visitRefactoringOptionsImpl(RefactoringOptionVisitor &Visitor,
+ const FirstT &First, const RestT &... Rest) {
+ struct OptionGatherer {
+ RefactoringOptionVisitor &Visitor;
+
+ void operator()(const RefactoringOptionsRequirement &Requirement) {
+ for (const auto &Option : Requirement.getRefactoringOptions())
+ Option->passToVisitor(Visitor);
+ }
+ void operator()(const RefactoringActionRuleRequirement &) {}
+ };
+ (OptionGatherer{Visitor})(First);
+ return visitRefactoringOptionsImpl(Visitor, Rest...);
+}
+
+template <typename... RequirementTypes, size_t... Is>
+void visitRefactoringOptions(
+ RefactoringOptionVisitor &Visitor,
+ const std::tuple<RequirementTypes...> &Requirements,
+ llvm::index_sequence<Is...>) {
+ visitRefactoringOptionsImpl(Visitor, std::get<Is>(Requirements)...);
+}
+
+/// A type trait that returns true when the given type list has at least one
+/// type whose base is the given base type.
+template <typename Base, typename First, typename... Rest>
+struct HasBaseOf : std::conditional<HasBaseOf<Base, First>::value ||
+ HasBaseOf<Base, Rest...>::value,
+ std::true_type, std::false_type>::type {};
+
+template <typename Base, typename T>
+struct HasBaseOf<Base, T> : std::is_base_of<Base, T> {};
+
+/// A type trait that returns true when the given type list contains types that
+/// derive from Base.
+template <typename Base, typename First, typename... Rest>
+struct AreBaseOf : std::conditional<AreBaseOf<Base, First>::value &&
+ AreBaseOf<Base, Rest...>::value,
+ std::true_type, std::false_type>::type {};
+
+template <typename Base, typename T>
+struct AreBaseOf<Base, T> : std::is_base_of<Base, T> {};
+
+} // end namespace internal
+
+template <typename RuleType, typename... RequirementTypes>
+std::unique_ptr<RefactoringActionRule>
+createRefactoringActionRule(const RequirementTypes &... Requirements) {
+ static_assert(std::is_base_of<RefactoringActionRuleBase, RuleType>::value,
+ "Expected a refactoring action rule type");
+ static_assert(internal::AreBaseOf<RefactoringActionRuleRequirement,
+ RequirementTypes...>::value,
+ "Expected a list of refactoring action rules");
+
+ class Rule final : public RefactoringActionRule {
+ public:
+ Rule(std::tuple<RequirementTypes...> Requirements)
+ : Requirements(Requirements) {}
+
+ void invoke(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context) override {
+ internal::invokeRuleAfterValidatingRequirements<RuleType>(
+ Consumer, Context, Requirements,
+ llvm::index_sequence_for<RequirementTypes...>());
+ }
+
+ bool hasSelectionRequirement() override {
+ return internal::HasBaseOf<SourceSelectionRequirement,
+ RequirementTypes...>::value;
+ }
+
+ void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override {
+ internal::visitRefactoringOptions(
+ Visitor, Requirements,
+ llvm::index_sequence_for<RequirementTypes...>());
+ }
+ private:
+ std::tuple<RequirementTypes...> Requirements;
+ };
+
+ return llvm::make_unique<Rule>(std::make_tuple(Requirements...));
+}
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
diff --git a/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h b/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h
new file mode 100644
index 000000000000..6767dc708e01
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringDiagnostic.h
@@ -0,0 +1,30 @@
+//===--- RefactoringDiagnostic.h - ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H
+#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/PartialDiagnostic.h"
+
+namespace clang {
+namespace diag {
+enum {
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ ENUM,
+#define REFACTORINGSTART
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_REFACTORING_DIAGNOSTICS
+};
+} // end namespace diag
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGDIAGNOSTIC_H
diff --git a/include/clang/Tooling/Refactoring/RefactoringOption.h b/include/clang/Tooling/Refactoring/RefactoringOption.h
new file mode 100644
index 000000000000..5011223cce69
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringOption.h
@@ -0,0 +1,64 @@
+//===--- RefactoringOption.h - Clang refactoring library ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H
+
+#include "clang/Basic/LLVM.h"
+#include <memory>
+#include <type_traits>
+
+namespace clang {
+namespace tooling {
+
+class RefactoringOptionVisitor;
+
+/// A refactoring option is an interface that describes a value that
+/// has an impact on the outcome of a refactoring.
+///
+/// Refactoring options can be specified using command-line arguments when
+/// the clang-refactor tool is used.
+class RefactoringOption {
+public:
+ virtual ~RefactoringOption() {}
+
+ /// Returns the name of the refactoring option.
+ ///
+ /// Each refactoring option must have a unique name.
+ virtual StringRef getName() const = 0;
+
+ virtual StringRef getDescription() const = 0;
+
+ /// True when this option must be specified before invoking the refactoring
+ /// action.
+ virtual bool isRequired() const = 0;
+
+ /// Invokes the \c visit method in the option consumer that's appropriate
+ /// for the option's value type.
+ ///
+ /// For example, if the option stores a string value, this method will
+ /// invoke the \c visit method with a reference to an std::string value.
+ virtual void passToVisitor(RefactoringOptionVisitor &Visitor) = 0;
+};
+
+/// Constructs a refactoring option of the given type.
+///
+/// The ownership of options is shared among requirements that use it because
+/// one option can be used by multiple rules in a refactoring action.
+template <typename OptionType>
+std::shared_ptr<OptionType> createRefactoringOption() {
+ static_assert(std::is_base_of<RefactoringOption, OptionType>::value,
+ "invalid option type");
+ return std::make_shared<OptionType>();
+}
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_H
diff --git a/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h b/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h
new file mode 100644
index 000000000000..aea8fa549392
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringOptionVisitor.h
@@ -0,0 +1,62 @@
+//===--- RefactoringOptionVisitor.h - Clang refactoring library -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H
+
+#include "clang/Basic/LLVM.h"
+#include <type_traits>
+
+namespace clang {
+namespace tooling {
+
+class RefactoringOption;
+
+/// An interface that declares functions that handle different refactoring
+/// option types.
+///
+/// A valid refactoring option type must have a corresponding \c visit
+/// declaration in this interface.
+class RefactoringOptionVisitor {
+public:
+ virtual ~RefactoringOptionVisitor() {}
+
+ virtual void visit(const RefactoringOption &Opt,
+ Optional<std::string> &Value) = 0;
+};
+
+namespace traits {
+namespace internal {
+
+template <typename T> struct HasHandle {
+private:
+ template <typename ClassT>
+ static auto check(ClassT *) -> typename std::is_same<
+ decltype(std::declval<RefactoringOptionVisitor>().visit(
+ std::declval<RefactoringOption>(), *std::declval<Optional<T> *>())),
+ void>::type;
+
+ template <typename> static std::false_type check(...);
+
+public:
+ using Type = decltype(check<RefactoringOptionVisitor>(nullptr));
+};
+
+} // end namespace internal
+
+/// A type trait that returns true iff the given type is a type that can be
+/// stored in a refactoring option.
+template <typename T>
+struct IsValidOptionType : internal::HasHandle<T>::Type {};
+
+} // end namespace traits
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTION_VISITOR_H
diff --git a/include/clang/Tooling/Refactoring/RefactoringOptions.h b/include/clang/Tooling/Refactoring/RefactoringOptions.h
new file mode 100644
index 000000000000..e45c0a09fd67
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringOptions.h
@@ -0,0 +1,58 @@
+//===--- RefactoringOptions.h - Clang refactoring library -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h"
+#include "clang/Tooling/Refactoring/RefactoringOption.h"
+#include "clang/Tooling/Refactoring/RefactoringOptionVisitor.h"
+#include "llvm/Support/Error.h"
+#include <type_traits>
+
+namespace clang {
+namespace tooling {
+
+/// A refactoring option that stores a value of type \c T.
+template <typename T, typename = typename std::enable_if<
+ traits::IsValidOptionType<T>::value>::type>
+class OptionalRefactoringOption : public RefactoringOption {
+public:
+ void passToVisitor(RefactoringOptionVisitor &Visitor) final override {
+ Visitor.visit(*this, Value);
+ }
+
+ bool isRequired() const override { return false; }
+
+ using ValueType = Optional<T>;
+
+ const ValueType &getValue() const { return Value; }
+
+protected:
+ Optional<T> Value;
+};
+
+/// A required refactoring option that stores a value of type \c T.
+template <typename T, typename = typename std::enable_if<
+ traits::IsValidOptionType<T>::value>::type>
+class RequiredRefactoringOption : public OptionalRefactoringOption<T> {
+public:
+ using ValueType = T;
+
+ const ValueType &getValue() const {
+ return *OptionalRefactoringOption<T>::Value;
+ }
+ bool isRequired() const final override { return true; }
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_OPTIONS_H
diff --git a/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h b/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
new file mode 100644
index 000000000000..fe7738e73499
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
@@ -0,0 +1,52 @@
+//===--- RefactoringResultConsumer.h - Clang refactoring library ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace tooling {
+
+/// An abstract interface that consumes the various refactoring results that can
+/// be produced by refactoring actions.
+///
+/// A valid refactoring result must be handled by a \c handle method.
+class RefactoringResultConsumer {
+public:
+ virtual ~RefactoringResultConsumer() {}
+
+ /// Handles an initation or an invication error. An initiation error typically
+ /// has a \c DiagnosticError payload that describes why initation failed.
+ virtual void handleError(llvm::Error Err) = 0;
+
+ /// Handles the source replacements that are produced by a refactoring action.
+ virtual void handle(AtomicChanges SourceReplacements) {
+ defaultResultHandler();
+ }
+
+ /// Handles the symbol occurrences that are found by an interactive
+ /// refactoring action.
+ virtual void handle(SymbolOccurrences Occurrences) { defaultResultHandler(); }
+
+private:
+ void defaultResultHandler() {
+ handleError(llvm::make_error<llvm::StringError>(
+ "unsupported refactoring result", llvm::inconvertibleErrorCode()));
+ }
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H
diff --git a/include/clang/Tooling/Refactoring/RefactoringRuleContext.h b/include/clang/Tooling/Refactoring/RefactoringRuleContext.h
new file mode 100644
index 000000000000..882ab824b639
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/RefactoringRuleContext.h
@@ -0,0 +1,90 @@
+//===--- RefactoringRuleContext.h - Clang refactoring library -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RULE_CONTEXT_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RULE_CONTEXT_H
+
+#include "clang/Basic/DiagnosticError.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Tooling/Refactoring/ASTSelection.h"
+
+namespace clang {
+
+class ASTContext;
+
+namespace tooling {
+
+/// The refactoring rule context stores all of the inputs that might be needed
+/// by a refactoring action rule. It can create the specialized
+/// \c ASTRefactoringOperation or \c PreprocessorRefactoringOperation values
+/// that can be used by the refactoring action rules.
+///
+/// The following inputs are stored by the operation:
+///
+/// - SourceManager: a reference to a valid source manager.
+///
+/// - SelectionRange: an optional source selection ranges that can be used
+/// to represent a selection in an editor.
+class RefactoringRuleContext {
+public:
+ RefactoringRuleContext(const SourceManager &SM) : SM(SM) {}
+
+ const SourceManager &getSources() const { return SM; }
+
+ /// Returns the current source selection range as set by the
+ /// refactoring engine. Can be invalid.
+ SourceRange getSelectionRange() const { return SelectionRange; }
+
+ void setSelectionRange(SourceRange R) { SelectionRange = R; }
+
+ bool hasASTContext() const { return AST; }
+
+ ASTContext &getASTContext() const {
+ assert(AST && "no AST!");
+ return *AST;
+ }
+
+ void setASTContext(ASTContext &Context) { AST = &Context; }
+
+ /// Creates an llvm::Error value that contains a diagnostic.
+ ///
+ /// The errors should not outlive the context.
+ llvm::Error createDiagnosticError(SourceLocation Loc, unsigned DiagID) {
+ return DiagnosticError::create(Loc, PartialDiagnostic(DiagID, DiagStorage));
+ }
+
+ llvm::Error createDiagnosticError(unsigned DiagID) {
+ return createDiagnosticError(SourceLocation(), DiagID);
+ }
+
+ void setASTSelection(std::unique_ptr<SelectedASTNode> Node) {
+ ASTNodeSelection = std::move(Node);
+ }
+
+private:
+ /// The source manager for the translation unit / file on which a refactoring
+ /// action might operate on.
+ const SourceManager &SM;
+ /// An optional source selection range that's commonly used to represent
+ /// a selection in an editor.
+ SourceRange SelectionRange;
+ /// An optional AST for the translation unit on which a refactoring action
+ /// might operate on.
+ ASTContext *AST = nullptr;
+ /// The allocator for diagnostics.
+ PartialDiagnostic::StorageAllocator DiagStorage;
+
+ // FIXME: Remove when memoized.
+ std::unique_ptr<SelectedASTNode> ASTNodeSelection;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RULE_CONTEXT_H
diff --git a/include/clang/Tooling/Refactoring/Rename/RenamingAction.h b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
index 099eaca6c42a..734b624d777b 100644
--- a/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
+++ b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
@@ -16,6 +16,11 @@
#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_RENAMING_ACTION_H
#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "clang/Tooling/Refactoring/RefactoringActionRules.h"
+#include "clang/Tooling/Refactoring/RefactoringOptions.h"
+#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h"
+#include "llvm/Support/Error.h"
namespace clang {
class ASTConsumer;
@@ -42,6 +47,53 @@ private:
bool PrintLocations;
};
+class RenameOccurrences final : public SourceChangeRefactoringRule {
+public:
+ static Expected<RenameOccurrences> initiate(RefactoringRuleContext &Context,
+ SourceRange SelectionRange,
+ std::string NewName);
+
+ static const RefactoringDescriptor &describe();
+
+private:
+ RenameOccurrences(const NamedDecl *ND, std::string NewName)
+ : ND(ND), NewName(std::move(NewName)) {}
+
+ Expected<AtomicChanges>
+ createSourceReplacements(RefactoringRuleContext &Context) override;
+
+ const NamedDecl *ND;
+ std::string NewName;
+};
+
+class QualifiedRenameRule final : public SourceChangeRefactoringRule {
+public:
+ static Expected<QualifiedRenameRule> initiate(RefactoringRuleContext &Context,
+ std::string OldQualifiedName,
+ std::string NewQualifiedName);
+
+ static const RefactoringDescriptor &describe();
+
+private:
+ QualifiedRenameRule(const NamedDecl *ND,
+ std::string NewQualifiedName)
+ : ND(ND), NewQualifiedName(std::move(NewQualifiedName)) {}
+
+ Expected<AtomicChanges>
+ createSourceReplacements(RefactoringRuleContext &Context) override;
+
+ // A NamedDecl which indentifies the the symbol being renamed.
+ const NamedDecl *ND;
+ // The new qualified name to change the symbol to.
+ std::string NewQualifiedName;
+};
+
+/// Returns source replacements that correspond to the rename of the given
+/// symbol occurrences.
+llvm::Expected<std::vector<AtomicChange>>
+createRenameReplacements(const SymbolOccurrences &Occurrences,
+ const SourceManager &SM, const SymbolName &NewName);
+
/// Rename all symbols identified by the given USRs.
class QualifiedRenamingAction {
public:
diff --git a/include/clang/Tooling/Refactoring/Rename/SymbolName.h b/include/clang/Tooling/Refactoring/Rename/SymbolName.h
new file mode 100644
index 000000000000..e69d2908b5d3
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/Rename/SymbolName.h
@@ -0,0 +1,49 @@
+//===--- SymbolName.h - Clang refactoring library -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H
+#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace tooling {
+
+/// A name of a symbol.
+///
+/// Symbol's name can be composed of multiple strings. For example, Objective-C
+/// methods can contain multiple argument lables:
+///
+/// \code
+/// - (void) myMethodNamePiece: (int)x anotherNamePieces:(int)y;
+/// // ^~ string 0 ~~~~~ ^~ string 1 ~~~~~
+/// \endcode
+class SymbolName {
+public:
+ explicit SymbolName(StringRef Name) {
+ // While empty symbol names are valid (Objective-C selectors can have empty
+ // name pieces), occurrences Objective-C selectors are created using an
+ // array of strings instead of just one string.
+ assert(!Name.empty() && "Invalid symbol name!");
+ this->Name.push_back(Name.str());
+ }
+
+ ArrayRef<std::string> getNamePieces() const { return Name; }
+
+private:
+ llvm::SmallVector<std::string, 1> Name;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H
diff --git a/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h b/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h
new file mode 100644
index 000000000000..0f853011978f
--- /dev/null
+++ b/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h
@@ -0,0 +1,91 @@
+//===--- SymbolOccurrences.h - Clang refactoring library ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H
+#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+class SymbolName;
+
+/// An occurrence of a symbol in the source.
+///
+/// Occurrences can have difference kinds, that describe whether this occurrence
+/// is an exact semantic match, or whether this is a weaker textual match that's
+/// not guaranteed to represent the exact declaration.
+///
+/// A single occurrence of a symbol can span more than one source range. For
+/// example, Objective-C selectors can contain multiple argument labels:
+///
+/// \code
+/// [object selectorPiece1: ... selectorPiece2: ...];
+/// // ^~~ range 0 ~~ ^~~ range 1 ~~
+/// \endcode
+///
+/// We have to replace the text in both range 0 and range 1 when renaming the
+/// Objective-C method 'selectorPiece1:selectorPiece2'.
+class SymbolOccurrence {
+public:
+ enum OccurrenceKind {
+ /// This occurrence is an exact match and can be renamed automatically.
+ ///
+ /// Note:
+ /// Symbol occurrences in macro arguments that expand to different
+ /// declarations get marked as exact matches, and thus the renaming engine
+ /// will rename them e.g.:
+ ///
+ /// \code
+ /// #define MACRO(x) x + ns::x
+ /// int foo(int var) {
+ /// return MACRO(var); // var is renamed automatically here when
+ /// // either var or ns::var is renamed.
+ /// };
+ /// \endcode
+ ///
+ /// The user will have to fix their code manually after performing such a
+ /// rename.
+ /// FIXME: The rename verifier should notify user about this issue.
+ MatchingSymbol
+ };
+
+ SymbolOccurrence(const SymbolName &Name, OccurrenceKind Kind,
+ ArrayRef<SourceLocation> Locations);
+
+ SymbolOccurrence(SymbolOccurrence &&) = default;
+ SymbolOccurrence &operator=(SymbolOccurrence &&) = default;
+
+ OccurrenceKind getKind() const { return Kind; }
+
+ ArrayRef<SourceRange> getNameRanges() const {
+ if (MultipleRanges) {
+ return llvm::makeArrayRef(MultipleRanges.get(),
+ RangeOrNumRanges.getBegin().getRawEncoding());
+ }
+ return RangeOrNumRanges;
+ }
+
+private:
+ OccurrenceKind Kind;
+ std::unique_ptr<SourceRange[]> MultipleRanges;
+ SourceRange RangeOrNumRanges;
+};
+
+using SymbolOccurrences = std::vector<SymbolOccurrence>;
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H
diff --git a/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h
index 8aafee95bc09..f1c5ae60f875 100644
--- a/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h
+++ b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h
@@ -23,11 +23,25 @@
namespace clang {
class ASTConsumer;
+class ASTContext;
class CompilerInstance;
class NamedDecl;
namespace tooling {
+/// Returns the canonical declaration that best represents a symbol that can be
+/// renamed.
+///
+/// The following canonicalization rules are currently used:
+///
+/// - A constructor is canonicalized to its class.
+/// - A destructor is canonicalized to its class.
+const NamedDecl *getCanonicalSymbolDeclaration(const NamedDecl *FoundDecl);
+
+/// Returns the set of USRs that correspond to the given declaration.
+std::vector<std::string> getUSRsForDeclaration(const NamedDecl *ND,
+ ASTContext &Context);
+
struct USRFindingAction {
USRFindingAction(ArrayRef<unsigned> SymbolOffsets,
ArrayRef<std::string> QualifiedNames, bool Force)
diff --git a/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
index 733ea1a6ac9e..801a8ad9e99c 100644
--- a/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
+++ b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
@@ -19,6 +19,7 @@
#include "clang/AST/AST.h"
#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h"
#include "llvm/ADT/StringRef.h"
#include <string>
#include <vector>
@@ -38,10 +39,13 @@ std::vector<tooling::AtomicChange>
createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
llvm::StringRef NewName, Decl *TranslationUnitDecl);
-// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!
-std::vector<SourceLocation>
-getLocationsOfUSRs(const std::vector<std::string> &USRs,
- llvm::StringRef PrevName, Decl *Decl);
+/// Finds the symbol occurrences for the symbol that's identified by the given
+/// USR set.
+///
+/// \return SymbolOccurrences that can be converted to AtomicChanges when
+/// renaming.
+SymbolOccurrences getOccurrencesOfUSRs(ArrayRef<std::string> USRs,
+ StringRef PrevName, Decl *Decl);
} // end namespace tooling
} // end namespace clang
diff --git a/include/clang/Tooling/StandaloneExecution.h b/include/clang/Tooling/StandaloneExecution.h
new file mode 100644
index 000000000000..f5f32d737a45
--- /dev/null
+++ b/include/clang/Tooling/StandaloneExecution.h
@@ -0,0 +1,97 @@
+//===--- StandaloneExecution.h - Standalone execution. -*- C++ ----------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines standalone execution of clang tools.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H
+#define LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H
+
+#include "clang/Tooling/ArgumentsAdjusters.h"
+#include "clang/Tooling/Execution.h"
+
+namespace clang {
+namespace tooling {
+
+/// \brief A standalone executor that runs FrontendActions on a given set of
+/// TUs in sequence.
+///
+/// By default, this executor uses the following arguments adjusters (as defined
+/// in `clang/Tooling/ArgumentsAdjusters.h`):
+/// - `getClangStripOutputAdjuster()`
+/// - `getClangSyntaxOnlyAdjuster()`
+/// - `getClangStripDependencyFileAdjuster()`
+class StandaloneToolExecutor : public ToolExecutor {
+public:
+ static const char *ExecutorName;
+
+ /// \brief Init with \p CompilationDatabase and the paths of all files to be
+ /// proccessed.
+ StandaloneToolExecutor(
+ const CompilationDatabase &Compilations,
+ llvm::ArrayRef<std::string> SourcePaths,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+ /// \brief Init with \p CommonOptionsParser. This is expected to be used by
+ /// `createExecutorFromCommandLineArgs` based on commandline options.
+ ///
+ /// The executor takes ownership of \p Options.
+ StandaloneToolExecutor(
+ CommonOptionsParser Options,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+ StringRef getExecutorName() const override { return ExecutorName; }
+
+ using ToolExecutor::execute;
+
+ llvm::Error
+ execute(llvm::ArrayRef<
+ std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
+ Actions) override;
+
+ /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
+ Tool.setDiagnosticConsumer(DiagConsumer);
+ }
+
+ ExecutionContext *getExecutionContext() override { return &Context; };
+
+ ToolResults *getToolResults() override { return &Results; }
+
+ llvm::ArrayRef<std::string> getSourcePaths() const {
+ return Tool.getSourcePaths();
+ }
+
+ void mapVirtualFile(StringRef FilePath, StringRef Content) override {
+ Tool.mapVirtualFile(FilePath, Content);
+ }
+
+ /// \brief Returns the file manager used in the tool.
+ ///
+ /// The file manager is shared between all translation units.
+ FileManager &getFiles() { return Tool.getFiles(); }
+
+private:
+ // Used to store the parser when the executor is initialized with parser.
+ llvm::Optional<CommonOptionsParser> OptionsParser;
+ // FIXME: The standalone executor is currently just a wrapper of `ClangTool`.
+ // Merge `ClangTool` implementation into the this.
+ ClangTool Tool;
+ ExecutionContext Context;
+ InMemoryToolResults Results;
+ ArgumentsAdjuster ArgsAdjuster;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H
diff --git a/include/clang/Tooling/ToolExecutorPluginRegistry.h b/include/clang/Tooling/ToolExecutorPluginRegistry.h
new file mode 100644
index 000000000000..11ba89546e9e
--- /dev/null
+++ b/include/clang/Tooling/ToolExecutorPluginRegistry.h
@@ -0,0 +1,24 @@
+//===--- ToolExecutorPluginRegistry.h - -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
+#define LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
+
+#include "clang/Tooling/Execution.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang {
+namespace tooling {
+
+typedef llvm::Registry<ToolExecutorPlugin> ToolExecutorPluginRegistry;
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h
index 6f9bc9e1a150..e64be07d9ab4 100644
--- a/include/clang/Tooling/Tooling.h
+++ b/include/clang/Tooling/Tooling.h
@@ -31,12 +31,12 @@
#define LLVM_CLANG_TOOLING_TOOLING_H
#include "clang/AST/ASTConsumer.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/Util.h"
#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
@@ -337,7 +337,9 @@ class ClangTool {
/// The file manager is shared between all translation units.
FileManager &getFiles() { return *Files; }
- private:
+ llvm::ArrayRef<std::string> getSourcePaths() const { return SourcePaths; }
+
+private:
const CompilationDatabase &Compilations;
std::vector<std::string> SourcePaths;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;