Target only the actual operator.

Renamed `BinExpr::op()` and `PrefixExpr::op()` to `op_kind`.
Now `op()` returns the `SyntaxNode`.
This commit is contained in:
Marco Groppo 2019-03-24 22:21:22 +01:00
parent acac7415a6
commit 67055c47da
3 changed files with 58 additions and 47 deletions

View file

@ -1,24 +1,23 @@
use hir::db::HirDatabase; use hir::db::HirDatabase;
use ra_syntax::{ use ra_syntax::ast::{AstNode, BinExpr, BinOp};
ast::{AstNode, BinExpr, BinOp}
};
use crate::{AssistCtx, Assist, AssistId}; use crate::{AssistCtx, Assist, AssistId};
pub(crate) fn flip_eq_operands(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { pub(crate) fn flip_eq_operands(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
let expr = ctx.node_at_offset::<BinExpr>()?; let expr = ctx.node_at_offset::<BinExpr>()?;
let lhs = expr.lhs()?.syntax();
let rhs = expr.rhs()?.syntax();
let op_range = expr.op()?.range();
let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
let allowed_ops = [BinOp::EqualityTest, BinOp::NegatedEqualityTest]; let allowed_ops = [BinOp::EqualityTest, BinOp::NegatedEqualityTest];
let expr_op = expr.op()?; let expr_op = expr.op_kind()?;
if !allowed_ops.iter().any(|o| *o == expr_op) { if !cursor_in_range || !allowed_ops.iter().any(|o| *o == expr_op) {
return None; return None;
} }
let node = expr.syntax();
let prev = node.first_child()?;
let next = node.last_child()?;
ctx.add_action(AssistId("flip_eq_operands"), "flip equality operands", |edit| { ctx.add_action(AssistId("flip_eq_operands"), "flip equality operands", |edit| {
edit.target(node.range()); edit.target(op_range);
edit.replace(prev.range(), next.text()); edit.replace(lhs.range(), rhs.text());
edit.replace(next.range(), prev.text()); edit.replace(rhs.range(), lhs.text());
}); });
ctx.build() ctx.build()
@ -82,6 +81,6 @@ mod tests {
#[test] #[test]
fn flip_eq_operands_target() { fn flip_eq_operands_target() {
check_assist_target(flip_eq_operands, "fn f() { let res = 1 ==<|> 2; }", "1 == 2") check_assist_target(flip_eq_operands, "fn f() { let res = 1 ==<|> 2; }", "==")
} }
} }

View file

@ -680,7 +680,7 @@ impl ExprCollector {
} }
ast::ExprKind::PrefixExpr(e) => { ast::ExprKind::PrefixExpr(e) => {
let expr = self.collect_expr_opt(e.expr()); let expr = self.collect_expr_opt(e.expr());
if let Some(op) = e.op() { if let Some(op) = e.op_kind() {
self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr) self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
} else { } else {
self.alloc_expr(Expr::Missing, syntax_ptr) self.alloc_expr(Expr::Missing, syntax_ptr)
@ -703,7 +703,7 @@ impl ExprCollector {
ast::ExprKind::BinExpr(e) => { ast::ExprKind::BinExpr(e) => {
let lhs = self.collect_expr_opt(e.lhs()); let lhs = self.collect_expr_opt(e.lhs());
let rhs = self.collect_expr_opt(e.rhs()); let rhs = self.collect_expr_opt(e.rhs());
let op = e.op(); let op = e.op_kind();
self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr) self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
} }
ast::ExprKind::TupleExpr(e) => { ast::ExprKind::TupleExpr(e) => {

View file

@ -521,7 +521,7 @@ pub enum PrefixOp {
} }
impl PrefixExpr { impl PrefixExpr {
pub fn op(&self) -> Option<PrefixOp> { pub fn op_kind(&self) -> Option<PrefixOp> {
match self.syntax().first_child()?.kind() { match self.syntax().first_child()?.kind() {
STAR => Some(PrefixOp::Deref), STAR => Some(PrefixOp::Deref),
EXCL => Some(PrefixOp::Not), EXCL => Some(PrefixOp::Not),
@ -529,6 +529,10 @@ impl PrefixExpr {
_ => None, _ => None,
} }
} }
pub fn op(&self) -> Option<&SyntaxNode> {
self.syntax().first_child()
}
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@ -598,46 +602,54 @@ pub enum BinOp {
} }
impl BinExpr { impl BinExpr {
pub fn op(&self) -> Option<BinOp> { fn op_details(&self) -> Option<(&SyntaxNode, BinOp)> {
self.syntax() self.syntax()
.children() .children()
.filter_map(|c| match c.kind() { .filter_map(|c| match c.kind() {
PIPEPIPE => Some(BinOp::BooleanOr), PIPEPIPE => Some((c, BinOp::BooleanOr)),
AMPAMP => Some(BinOp::BooleanAnd), AMPAMP => Some((c, BinOp::BooleanAnd)),
EQEQ => Some(BinOp::EqualityTest), EQEQ => Some((c, BinOp::EqualityTest)),
NEQ => Some(BinOp::NegatedEqualityTest), NEQ => Some((c, BinOp::NegatedEqualityTest)),
LTEQ => Some(BinOp::LesserEqualTest), LTEQ => Some((c, BinOp::LesserEqualTest)),
GTEQ => Some(BinOp::GreaterEqualTest), GTEQ => Some((c, BinOp::GreaterEqualTest)),
L_ANGLE => Some(BinOp::LesserTest), L_ANGLE => Some((c, BinOp::LesserTest)),
R_ANGLE => Some(BinOp::GreaterTest), R_ANGLE => Some((c, BinOp::GreaterTest)),
PLUS => Some(BinOp::Addition), PLUS => Some((c, BinOp::Addition)),
STAR => Some(BinOp::Multiplication), STAR => Some((c, BinOp::Multiplication)),
MINUS => Some(BinOp::Subtraction), MINUS => Some((c, BinOp::Subtraction)),
SLASH => Some(BinOp::Division), SLASH => Some((c, BinOp::Division)),
PERCENT => Some(BinOp::Remainder), PERCENT => Some((c, BinOp::Remainder)),
SHL => Some(BinOp::LeftShift), SHL => Some((c, BinOp::LeftShift)),
SHR => Some(BinOp::RightShift), SHR => Some((c, BinOp::RightShift)),
CARET => Some(BinOp::BitwiseXor), CARET => Some((c, BinOp::BitwiseXor)),
PIPE => Some(BinOp::BitwiseOr), PIPE => Some((c, BinOp::BitwiseOr)),
AMP => Some(BinOp::BitwiseAnd), AMP => Some((c, BinOp::BitwiseAnd)),
DOTDOT => Some(BinOp::RangeRightOpen), DOTDOT => Some((c, BinOp::RangeRightOpen)),
DOTDOTEQ => Some(BinOp::RangeRightClosed), DOTDOTEQ => Some((c, BinOp::RangeRightClosed)),
EQ => Some(BinOp::Assignment), EQ => Some((c, BinOp::Assignment)),
PLUSEQ => Some(BinOp::AddAssign), PLUSEQ => Some((c, BinOp::AddAssign)),
SLASHEQ => Some(BinOp::DivAssign), SLASHEQ => Some((c, BinOp::DivAssign)),
STAREQ => Some(BinOp::MulAssign), STAREQ => Some((c, BinOp::MulAssign)),
PERCENTEQ => Some(BinOp::RemAssign), PERCENTEQ => Some((c, BinOp::RemAssign)),
SHREQ => Some(BinOp::ShrAssign), SHREQ => Some((c, BinOp::ShrAssign)),
SHLEQ => Some(BinOp::ShlAssign), SHLEQ => Some((c, BinOp::ShlAssign)),
MINUSEQ => Some(BinOp::SubAssign), MINUSEQ => Some((c, BinOp::SubAssign)),
PIPEEQ => Some(BinOp::BitOrAssign), PIPEEQ => Some((c, BinOp::BitOrAssign)),
AMPEQ => Some(BinOp::BitAndAssign), AMPEQ => Some((c, BinOp::BitAndAssign)),
CARETEQ => Some(BinOp::BitXorAssign), CARETEQ => Some((c, BinOp::BitXorAssign)),
_ => None, _ => None,
}) })
.next() .next()
} }
pub fn op_kind(&self) -> Option<BinOp> {
self.op_details().map(|t| t.1)
}
pub fn op(&self) -> Option<&SyntaxNode> {
self.op_details().map(|t| t.0)
}
pub fn lhs(&self) -> Option<&Expr> { pub fn lhs(&self) -> Option<&Expr> {
children(self).nth(0) children(self).nth(0)
} }