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 20namespace clang { 21namespace 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). 36class 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). 42class SourceSelectionRequirement : public RefactoringActionRuleRequirement {}; 43 44/// A selection requirement that is satisfied when any portion of the source 45/// text is selected. 46class SourceRangeSelectionRequirement : public SourceSelectionRequirement { 47public: 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. 60class ASTSelectionRequirement : public SourceRangeSelectionRequirement { 61public: 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 74class CodeRangeASTSelectionRequirement : public ASTSelectionRequirement { 75public: 76 Expected<CodeRangeASTSelection> 77 evaluate(RefactoringRuleContext &Context) const; 78}; 79 80/// A base class for any requirement that requires some refactoring options. 81class RefactoringOptionsRequirement : public RefactoringActionRuleRequirement { 82public: 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. 95template <typename OptionType> 96class OptionRequirement : public RefactoringOptionsRequirement { 97public: 98 OptionRequirement() : Opt(createRefactoringOption<OptionType>()) {} 99 100 ArrayRef<std::shared_ptr<RefactoringOption>> 101 getRefactoringOptions() const final { 102 return Opt; 103 } 104 105 Expected<typename OptionType::ValueType> 106 evaluate(RefactoringRuleContext &) const { 107 return static_cast<OptionType *>(Opt.get())->getValue(); 108 } 109 110private: 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