1 //===--- RefactoringActionRuleRequirements.h - Clang refactoring library --===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULEREQUIREMENTS_H 10 #define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULEREQUIREMENTS_H 11 12 #include "clang/Basic/LLVM.h" 13 #include "clang/Tooling/Refactoring/ASTSelection.h" 14 #include "clang/Tooling/Refactoring/RefactoringDiagnostic.h" 15 #include "clang/Tooling/Refactoring/RefactoringOption.h" 16 #include "clang/Tooling/Refactoring/RefactoringRuleContext.h" 17 #include "llvm/Support/Error.h" 18 #include <type_traits> 19 20 namespace clang { 21 namespace tooling { 22 23 /// A refactoring action rule requirement determines when a refactoring action 24 /// rule can be invoked. The rule can be invoked only when all of the 25 /// requirements are satisfied. 26 /// 27 /// Subclasses must implement the 28 /// 'Expected<T> evaluate(RefactoringRuleContext &) const' member function. 29 /// \c T is used to determine the return type that is passed to the 30 /// refactoring rule's constructor. 31 /// For example, the \c SourceRangeSelectionRequirement subclass defines 32 /// 'Expected<SourceRange> evaluate(RefactoringRuleContext &Context) const' 33 /// function. When this function returns a non-error value, the resulting 34 /// source range is passed to the specific refactoring action rule 35 /// constructor (provided all other requirements are satisfied). 36 class RefactoringActionRuleRequirement { 37 // Expected<T> evaluate(RefactoringRuleContext &Context) const; 38 }; 39 40 /// A base class for any requirement that expects some part of the source to be 41 /// selected in an editor (or the refactoring tool with the -selection option). 42 class SourceSelectionRequirement : public RefactoringActionRuleRequirement {}; 43 44 /// A selection requirement that is satisfied when any portion of the source 45 /// text is selected. 46 class SourceRangeSelectionRequirement : public SourceSelectionRequirement { 47 public: evaluate(RefactoringRuleContext & Context)48 Expected<SourceRange> evaluate(RefactoringRuleContext &Context) const { 49 if (Context.getSelectionRange().isValid()) 50 return Context.getSelectionRange(); 51 return Context.createDiagnosticError(diag::err_refactor_no_selection); 52 } 53 }; 54 55 /// An AST selection requirement is satisfied when any portion of the AST 56 /// overlaps with the selection range. 57 /// 58 /// The requirement will be evaluated only once during the initiation and 59 /// search of matching refactoring action rules. 60 class ASTSelectionRequirement : public SourceRangeSelectionRequirement { 61 public: 62 Expected<SelectedASTNode> evaluate(RefactoringRuleContext &Context) const; 63 }; 64 65 /// A selection requirement that is satisfied when the selection range overlaps 66 /// with a number of neighbouring statements in the AST. The statemenst must be 67 /// contained in declaration like a function. The selection range must be a 68 /// non-empty source selection (i.e. cursors won't be accepted). 69 /// 70 /// The requirement will be evaluated only once during the initiation and search 71 /// of matching refactoring action rules. 72 /// 73 /// \see CodeRangeASTSelection 74 class CodeRangeASTSelectionRequirement : public ASTSelectionRequirement { 75 public: 76 Expected<CodeRangeASTSelection> 77 evaluate(RefactoringRuleContext &Context) const; 78 }; 79 80 /// A base class for any requirement that requires some refactoring options. 81 class RefactoringOptionsRequirement : public RefactoringActionRuleRequirement { 82 public: ~RefactoringOptionsRequirement()83 virtual ~RefactoringOptionsRequirement() {} 84 85 /// Returns the set of refactoring options that are used when evaluating this 86 /// requirement. 87 virtual ArrayRef<std::shared_ptr<RefactoringOption>> 88 getRefactoringOptions() const = 0; 89 }; 90 91 /// A requirement that evaluates to the value of the given \c OptionType when 92 /// the \c OptionType is a required option. When the \c OptionType is an 93 /// optional option, the requirement will evaluate to \c None if the option is 94 /// not specified or to an appropriate value otherwise. 95 template <typename OptionType> 96 class OptionRequirement : public RefactoringOptionsRequirement { 97 public: OptionRequirement()98 OptionRequirement() : Opt(createRefactoringOption<OptionType>()) {} 99 100 ArrayRef<std::shared_ptr<RefactoringOption>> getRefactoringOptions()101 getRefactoringOptions() const final { 102 return Opt; 103 } 104 105 Expected<typename OptionType::ValueType> evaluate(RefactoringRuleContext &)106 evaluate(RefactoringRuleContext &) const { 107 return static_cast<OptionType *>(Opt.get())->getValue(); 108 } 109 110 private: 111 /// The partially-owned option. 112 /// 113 /// The ownership of the option is shared among the different requirements 114 /// because the same option can be used by multiple rules in one refactoring 115 /// action. 116 std::shared_ptr<RefactoringOption> Opt; 117 }; 118 119 } // end namespace tooling 120 } // end namespace clang 121 122 #endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULEREQUIREMENTS_H 123