diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Tooling/Refactoring/Extract.cpp | 115 | ||||
-rw-r--r-- | clang/lib/Tooling/Refactoring/RefactoringActions.cpp | 71 | ||||
-rw-r--r-- | clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp | 86 |
3 files changed, 126 insertions, 146 deletions
diff --git a/clang/lib/Tooling/Refactoring/Extract.cpp b/clang/lib/Tooling/Refactoring/Extract.cpp index 616900c1819..b1000b60ee0 100644 --- a/clang/lib/Tooling/Refactoring/Extract.cpp +++ b/clang/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/clang/lib/Tooling/Refactoring/RefactoringActions.cpp b/clang/lib/Tooling/Refactoring/RefactoringActions.cpp index 25f055b7270..73a31183962 100644 --- a/clang/lib/Tooling/Refactoring/RefactoringActions.cpp +++ b/clang/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/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp b/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp index 28912c3e139..210b45b79ef 100644 --- a/clang/lib/Tooling/Refactoring/Rename/RenamingAction.cpp +++ b/clang/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>> |