summaryrefslogtreecommitdiffstats
path: root/lib/Tooling
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-10-27 18:19:11 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-10-27 18:19:11 +0000
commit99af5f07de88d6757dedc7ee6a8197fab0fe8c0f (patch)
treeca6a9414b877de2816023fa16fd5188451eb4575 /lib/Tooling
parent1c09b76713c0a3521937e035b3ab4edef687e7ee (diff)
[refactor] Describe refactorings in the operation classes
This commit changes the way that the refactoring operation classes are structured: - Users have to call `initiate` instead of constructing an instance of the class. The `initiate` is now supposed to have custom initiation logic, and you don't need to subclass the builtin requirements. - A new `describe` function returns a structure with the id, title and the description of the refactoring operation. The refactoring action classes are now placed into one common place in RefactoringActions.cpp instead of being separate. Differential Revision: https://reviews.llvm.org/D38985 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@316780 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Tooling')
-rw-r--r--lib/Tooling/Refactoring/Extract.cpp115
-rw-r--r--lib/Tooling/Refactoring/RefactoringActions.cpp71
-rw-r--r--lib/Tooling/Refactoring/Rename/RenamingAction.cpp86
3 files changed, 126 insertions, 146 deletions
diff --git a/lib/Tooling/Refactoring/Extract.cpp b/lib/Tooling/Refactoring/Extract.cpp
index 616900c181..b1000b60ee 100644
--- a/lib/Tooling/Refactoring/Extract.cpp
+++ b/lib/Tooling/Refactoring/Extract.cpp
@@ -13,12 +13,10 @@
///
//===----------------------------------------------------------------------===//
+#include "clang/Tooling/Refactoring/Extract/Extract.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/Tooling/Refactoring/RefactoringAction.h"
-#include "clang/Tooling/Refactoring/RefactoringActionRules.h"
-#include "clang/Tooling/Refactoring/RefactoringOptions.h"
namespace clang {
namespace tooling {
@@ -44,58 +42,43 @@ bool isSimpleExpression(const Expr *E) {
}
}
-class ExtractableCodeSelectionRequirement final
- : public CodeRangeASTSelectionRequirement {
-public:
- Expected<CodeRangeASTSelection>
- evaluate(RefactoringRuleContext &Context) const {
- Expected<CodeRangeASTSelection> Selection =
- CodeRangeASTSelectionRequirement::evaluate(Context);
- if (!Selection)
- return Selection.takeError();
- CodeRangeASTSelection &Code = *Selection;
-
- // We would like to extract code out of functions/methods/blocks.
- // Prohibit extraction from things like global variable / field
- // initializers and other top-level expressions.
- if (!Code.isInFunctionLikeBodyOfCode())
- return Context.createDiagnosticError(
- diag::err_refactor_code_outside_of_function);
-
- // Avoid extraction of simple literals and references.
- if (Code.size() == 1 && isSimpleExpression(dyn_cast<Expr>(Code[0])))
- return Context.createDiagnosticError(
- diag::err_refactor_extract_simple_expression);
-
- // FIXME (Alex L): Prohibit extraction of Objective-C property setters.
- return Selection;
- }
-};
-
-class ExtractFunction final : public SourceChangeRefactoringRule {
-public:
- ExtractFunction(CodeRangeASTSelection Code, Optional<std::string> DeclName)
- : Code(std::move(Code)),
- DeclName(DeclName ? std::move(*DeclName) : "extracted") {}
-
- Expected<AtomicChanges>
- createSourceReplacements(RefactoringRuleContext &Context) override;
-
-private:
- CodeRangeASTSelection Code;
-
- // FIXME: Account for naming collisions:
- // - error when name is specified by user.
- // - rename to "extractedN" when name is implicit.
- std::string DeclName;
-};
-
SourceLocation computeFunctionExtractionLocation(const Decl *D) {
// FIXME (Alex L): Method -> function extraction should place function before
// C++ record if the method is defined inside the record.
return D->getLocStart();
}
+} // end anonymous namespace
+
+const RefactoringDescriptor &ExtractFunction::describe() {
+ static const RefactoringDescriptor Descriptor = {
+ "extract-function",
+ "Extract Function",
+ "(WIP action; use with caution!) Extracts code into a new function",
+ };
+ return Descriptor;
+}
+
+Expected<ExtractFunction>
+ExtractFunction::initiate(RefactoringRuleContext &Context,
+ CodeRangeASTSelection Code,
+ Optional<std::string> DeclName) {
+ // We would like to extract code out of functions/methods/blocks.
+ // Prohibit extraction from things like global variable / field
+ // initializers and other top-level expressions.
+ if (!Code.isInFunctionLikeBodyOfCode())
+ return Context.createDiagnosticError(
+ diag::err_refactor_code_outside_of_function);
+
+ // Avoid extraction of simple literals and references.
+ if (Code.size() == 1 && isSimpleExpression(dyn_cast<Expr>(Code[0])))
+ return Context.createDiagnosticError(
+ diag::err_refactor_extract_simple_expression);
+
+ // FIXME (Alex L): Prohibit extraction of Objective-C property setters.
+ return ExtractFunction(std::move(Code), DeclName);
+}
+
// FIXME: Support C++ method extraction.
// FIXME: Support Objective-C method extraction.
Expected<AtomicChanges>
@@ -194,39 +177,5 @@ ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) {
return AtomicChanges{std::move(Change)};
}
-class DeclNameOption final : public OptionalRefactoringOption<std::string> {
-public:
- StringRef getName() const { return "name"; }
- StringRef getDescription() const {
- return "Name of the extracted declaration";
- }
-};
-
-class ExtractRefactoring final : public RefactoringAction {
-public:
- StringRef getCommand() const override { return "extract"; }
-
- StringRef getDescription() const override {
- return "(WIP action; use with caution!) Extracts code into a new function "
- "/ method / variable";
- }
-
- /// Returns a set of refactoring actions rules that are defined by this
- /// action.
- RefactoringActionRules createActionRules() const override {
- RefactoringActionRules Rules;
- Rules.push_back(createRefactoringActionRule<ExtractFunction>(
- ExtractableCodeSelectionRequirement(),
- OptionRequirement<DeclNameOption>()));
- return Rules;
- }
-};
-
-} // end anonymous namespace
-
-std::unique_ptr<RefactoringAction> createExtractAction() {
- return llvm::make_unique<ExtractRefactoring>();
-}
-
} // end namespace tooling
} // end namespace clang
diff --git a/lib/Tooling/Refactoring/RefactoringActions.cpp b/lib/Tooling/Refactoring/RefactoringActions.cpp
index 25f055b727..73a3118396 100644
--- a/lib/Tooling/Refactoring/RefactoringActions.cpp
+++ b/lib/Tooling/Refactoring/RefactoringActions.cpp
@@ -7,21 +7,80 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Tooling/Refactoring/Extract/Extract.h"
#include "clang/Tooling/Refactoring/RefactoringAction.h"
+#include "clang/Tooling/Refactoring/RefactoringOptions.h"
+#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
namespace clang {
namespace tooling {
-// Forward declare the individual create*Action functions.
-#define REFACTORING_ACTION(Name) \
- std::unique_ptr<RefactoringAction> create##Name##Action();
-#include "clang/Tooling/Refactoring/RefactoringActionRegistry.def"
+namespace {
+
+class DeclNameOption final : public OptionalRefactoringOption<std::string> {
+public:
+ StringRef getName() const { return "name"; }
+ StringRef getDescription() const {
+ return "Name of the extracted declaration";
+ }
+};
+
+// FIXME: Rewrite the Actions to avoid duplication of descriptions/names with
+// rules.
+class ExtractRefactoring final : public RefactoringAction {
+public:
+ StringRef getCommand() const override { return "extract"; }
+
+ StringRef getDescription() const override {
+ return "(WIP action; use with caution!) Extracts code into a new function";
+ }
+
+ /// Returns a set of refactoring actions rules that are defined by this
+ /// action.
+ RefactoringActionRules createActionRules() const override {
+ RefactoringActionRules Rules;
+ Rules.push_back(createRefactoringActionRule<ExtractFunction>(
+ CodeRangeASTSelectionRequirement(),
+ OptionRequirement<DeclNameOption>()));
+ return Rules;
+ }
+};
+
+class NewNameOption : public RequiredRefactoringOption<std::string> {
+public:
+ StringRef getName() const override { return "new-name"; }
+ StringRef getDescription() const override {
+ return "The new name to change the symbol to";
+ }
+};
+
+// FIXME: Rewrite the Actions to avoid duplication of descriptions/names with
+// rules.
+class LocalRename final : public RefactoringAction {
+public:
+ StringRef getCommand() const override { return "local-rename"; }
+
+ StringRef getDescription() const override {
+ return "Finds and renames symbols in code with no indexer support";
+ }
+
+ /// Returns a set of refactoring actions rules that are defined by this
+ /// action.
+ RefactoringActionRules createActionRules() const override {
+ RefactoringActionRules Rules;
+ Rules.push_back(createRefactoringActionRule<RenameOccurrences>(
+ SourceRangeSelectionRequirement(), OptionRequirement<NewNameOption>()));
+ return Rules;
+ }
+};
+
+} // end anonymous namespace
std::vector<std::unique_ptr<RefactoringAction>> createRefactoringActions() {
std::vector<std::unique_ptr<RefactoringAction>> Actions;
-#define REFACTORING_ACTION(Name) Actions.push_back(create##Name##Action());
-#include "clang/Tooling/Refactoring/RefactoringActionRegistry.def"
+ Actions.push_back(llvm::make_unique<LocalRename>());
+ Actions.push_back(llvm::make_unique<ExtractRefactoring>());
return Actions;
}
diff --git a/lib/Tooling/Refactoring/Rename/RenamingAction.cpp b/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
index 28912c3e13..210b45b79e 100644
--- a/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
+++ b/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
@@ -41,22 +41,6 @@ namespace tooling {
namespace {
-class SymbolSelectionRequirement : public SourceRangeSelectionRequirement {
-public:
- Expected<const NamedDecl *> evaluate(RefactoringRuleContext &Context) const {
- Expected<SourceRange> Selection =
- SourceRangeSelectionRequirement::evaluate(Context);
- if (!Selection)
- return Selection.takeError();
- const NamedDecl *ND =
- getNamedDeclAt(Context.getASTContext(), Selection->getBegin());
- if (!ND)
- return Context.createDiagnosticError(
- Selection->getBegin(), diag::err_refactor_selection_no_symbol);
- return getCanonicalSymbolDeclaration(ND);
- }
-};
-
class OccurrenceFinder final : public FindSymbolOccurrencesRefactoringRule {
public:
OccurrenceFinder(const NamedDecl *ND) : ND(ND) {}
@@ -74,50 +58,38 @@ private:
const NamedDecl *ND;
};
-class RenameOccurrences final : public SourceChangeRefactoringRule {
-public:
- RenameOccurrences(const NamedDecl *ND, std::string NewName)
- : Finder(ND), NewName(std::move(NewName)) {}
-
- Expected<AtomicChanges>
- createSourceReplacements(RefactoringRuleContext &Context) override {
- Expected<SymbolOccurrences> Occurrences =
- Finder.findSymbolOccurrences(Context);
- if (!Occurrences)
- return Occurrences.takeError();
- // FIXME: Verify that the new name is valid.
- SymbolName Name(NewName);
- return createRenameReplacements(
- *Occurrences, Context.getASTContext().getSourceManager(), Name);
- }
-
-private:
- OccurrenceFinder Finder;
- std::string NewName;
-};
-
-class LocalRename final : public RefactoringAction {
-public:
- StringRef getCommand() const override { return "local-rename"; }
-
- StringRef getDescription() const override {
- return "Finds and renames symbols in code with no indexer support";
- }
+} // end anonymous namespace
- /// Returns a set of refactoring actions rules that are defined by this
- /// action.
- RefactoringActionRules createActionRules() const override {
- RefactoringActionRules Rules;
- Rules.push_back(createRefactoringActionRule<RenameOccurrences>(
- SymbolSelectionRequirement(), OptionRequirement<NewNameOption>()));
- return Rules;
- }
-};
+const RefactoringDescriptor &RenameOccurrences::describe() {
+ static const RefactoringDescriptor Descriptor = {
+ "local-rename",
+ "Rename",
+ "Finds and renames symbols in code with no indexer support",
+ };
+ return Descriptor;
+}
-} // end anonymous namespace
+Expected<RenameOccurrences>
+RenameOccurrences::initiate(RefactoringRuleContext &Context,
+ SourceRange SelectionRange, std::string NewName) {
+ const NamedDecl *ND =
+ getNamedDeclAt(Context.getASTContext(), SelectionRange.getBegin());
+ if (!ND)
+ return Context.createDiagnosticError(
+ SelectionRange.getBegin(), diag::err_refactor_selection_no_symbol);
+ return RenameOccurrences(getCanonicalSymbolDeclaration(ND), NewName);
+}
-std::unique_ptr<RefactoringAction> createLocalRenameAction() {
- return llvm::make_unique<LocalRename>();
+Expected<AtomicChanges>
+RenameOccurrences::createSourceReplacements(RefactoringRuleContext &Context) {
+ Expected<SymbolOccurrences> Occurrences =
+ OccurrenceFinder(ND).findSymbolOccurrences(Context);
+ if (!Occurrences)
+ return Occurrences.takeError();
+ // FIXME: Verify that the new name is valid.
+ SymbolName Name(NewName);
+ return createRenameReplacements(
+ *Occurrences, Context.getASTContext().getSourceManager(), Name);
}
Expected<std::vector<AtomicChange>>