14#include "clang/AST/ASTContext.h"
15#include "clang/AST/Expr.h"
16#include "clang/AST/OperationKinds.h"
17#include "clang/AST/Stmt.h"
18#include "clang/Basic/LLVM.h"
19#include "clang/Basic/SourceLocation.h"
20#include "clang/Tooling/Core/Replacement.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/Support/Casting.h"
23#include "llvm/Support/FormatVariadic.h"
35bool isOpSwappable(
const BinaryOperatorKind Opcode) {
37 case BinaryOperatorKind::BO_Mul:
38 case BinaryOperatorKind::BO_Add:
39 case BinaryOperatorKind::BO_LT:
40 case BinaryOperatorKind::BO_GT:
41 case BinaryOperatorKind::BO_LE:
42 case BinaryOperatorKind::BO_GE:
43 case BinaryOperatorKind::BO_EQ:
44 case BinaryOperatorKind::BO_NE:
45 case BinaryOperatorKind::BO_And:
46 case BinaryOperatorKind::BO_Xor:
47 case BinaryOperatorKind::BO_Or:
48 case BinaryOperatorKind::BO_LAnd:
49 case BinaryOperatorKind::BO_LOr:
50 case BinaryOperatorKind::BO_Comma:
53 case BinaryOperatorKind::BO_Div:
54 case BinaryOperatorKind::BO_Sub:
55 case BinaryOperatorKind::BO_Shl:
56 case BinaryOperatorKind::BO_Shr:
57 case BinaryOperatorKind::BO_Rem:
59 case BinaryOperatorKind::BO_Cmp:
61 case BinaryOperatorKind::BO_PtrMemD:
62 case BinaryOperatorKind::BO_PtrMemI:
64 case BinaryOperatorKind::BO_Assign:
65 case BinaryOperatorKind::BO_MulAssign:
66 case BinaryOperatorKind::BO_DivAssign:
67 case BinaryOperatorKind::BO_RemAssign:
68 case BinaryOperatorKind::BO_AddAssign:
69 case BinaryOperatorKind::BO_SubAssign:
70 case BinaryOperatorKind::BO_ShlAssign:
71 case BinaryOperatorKind::BO_ShrAssign:
72 case BinaryOperatorKind::BO_AndAssign:
73 case BinaryOperatorKind::BO_XorAssign:
74 case BinaryOperatorKind::BO_OrAssign:
84BinaryOperatorKind swapOperator(
const BinaryOperatorKind Opcode) {
86 case BinaryOperatorKind::BO_LT:
87 return BinaryOperatorKind::BO_GT;
89 case BinaryOperatorKind::BO_GT:
90 return BinaryOperatorKind::BO_LT;
92 case BinaryOperatorKind::BO_LE:
93 return BinaryOperatorKind::BO_GE;
95 case BinaryOperatorKind::BO_GE:
96 return BinaryOperatorKind::BO_LE;
98 case BinaryOperatorKind::BO_Mul:
99 case BinaryOperatorKind::BO_Add:
100 case BinaryOperatorKind::BO_Cmp:
101 case BinaryOperatorKind::BO_EQ:
102 case BinaryOperatorKind::BO_NE:
103 case BinaryOperatorKind::BO_And:
104 case BinaryOperatorKind::BO_Xor:
105 case BinaryOperatorKind::BO_Or:
106 case BinaryOperatorKind::BO_LAnd:
107 case BinaryOperatorKind::BO_LOr:
108 case BinaryOperatorKind::BO_Comma:
109 case BinaryOperatorKind::BO_Div:
110 case BinaryOperatorKind::BO_Sub:
111 case BinaryOperatorKind::BO_Shl:
112 case BinaryOperatorKind::BO_Shr:
113 case BinaryOperatorKind::BO_Rem:
114 case BinaryOperatorKind::BO_PtrMemD:
115 case BinaryOperatorKind::BO_PtrMemI:
116 case BinaryOperatorKind::BO_Assign:
117 case BinaryOperatorKind::BO_MulAssign:
118 case BinaryOperatorKind::BO_DivAssign:
119 case BinaryOperatorKind::BO_RemAssign:
120 case BinaryOperatorKind::BO_AddAssign:
121 case BinaryOperatorKind::BO_SubAssign:
122 case BinaryOperatorKind::BO_ShlAssign:
123 case BinaryOperatorKind::BO_ShrAssign:
124 case BinaryOperatorKind::BO_AndAssign:
125 case BinaryOperatorKind::BO_XorAssign:
126 case BinaryOperatorKind::BO_OrAssign:
129 llvm_unreachable(
"Unknown BinaryOperatorKind enum");
138class SwapBinaryOperands :
public Tweak {
140 const char *id() const final;
142 bool prepare(const Selection &Inputs) override;
143 Expected<Effect> apply(const Selection &Inputs) override;
144 std::
string title()
const override {
145 return llvm::formatv(
"Swap operands to {0}",
146 Op ? Op->getOpcodeStr() :
"binary operator");
148 llvm::StringLiteral kind()
const override {
151 bool hidden()
const override {
return false; }
154 const BinaryOperator *Op;
159bool SwapBinaryOperands::prepare(
const Selection &Inputs) {
160 for (
const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor();
161 N && !Op; N = N->Parent) {
166 if (llvm::isa_and_nonnull<CompoundStmt>(N->ASTNode.get<Stmt>()))
168 Op = dyn_cast_or_null<BinaryOperator>(N->ASTNode.get<Stmt>());
170 if (Op && !isOpSwappable(Op->getOpcode())) {
174 return Op !=
nullptr;
177Expected<Tweak::Effect> SwapBinaryOperands::apply(
const Selection &Inputs) {
178 const auto &Ctx = Inputs.AST->getASTContext();
179 const auto &SrcMgr = Inputs.AST->getSourceManager();
182 Op->getLHS()->getSourceRange());
185 "Could not obtain range of the 'lhs' of the operator. Macros?");
187 Op->getRHS()->getSourceRange());
190 "Could not obtain range of the 'rhs' of the operator. Macros?");
194 return error(
"Could not obtain range of the operator itself. Macros?");
200 tooling::Replacements Result;
201 if (
auto Err = Result.add(tooling::Replacement(
202 Ctx.getSourceManager(), LHSRng->getBegin(), LHSCode.size(), RHSCode)))
203 return std::move(Err);
204 if (
auto Err = Result.add(tooling::Replacement(
205 Ctx.getSourceManager(), RHSRng->getBegin(), RHSCode.size(), LHSCode)))
206 return std::move(Err);
207 const auto SwappedOperator = swapOperator(Op->getOpcode());
208 if (
auto Err = Result.add(tooling::Replacement(
209 Ctx.getSourceManager(), OpRng->getBegin(), OperatorCode.size(),
210 Op->getOpcodeStr(SwappedOperator))))
211 return std::move(Err);
212 return Effect::mainFileEdit(SrcMgr, std::move(Result));
std::vector< const char * > Expected
#define REGISTER_TWEAK(Subclass)
std::optional< SourceRange > toHalfOpenFileRange(const SourceManager &SM, const LangOptions &LangOpts, SourceRange R)
Turns a token range into a half-open range and checks its correctness.
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
llvm::StringRef toSourceCode(const SourceManager &SM, SourceRange R)
Returns the source code covered by the source range.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static const llvm::StringLiteral REFACTOR_KIND