From 90357a9090a88b2f7bc5db5d05cb576680ce2960 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 14 Aug 2021 18:08:31 +0300 Subject: [PATCH] internal: merge hir::BinaryOp and ast::BinOp --- crates/hir_def/src/body/lower.rs | 6 +- .../src/handlers/apply_demorgan.rs | 17 +- .../src/handlers/extract_function.rs | 2 +- .../ide_assists/src/handlers/flip_binexpr.rs | 21 +- .../src/handlers/pull_assignment_up.rs | 4 +- crates/ide_assists/src/utils.rs | 17 +- .../src/utils/gen_trait_fn_body.rs | 25 ++- crates/ide_db/src/search.rs | 2 +- crates/syntax/src/ast.rs | 4 +- crates/syntax/src/ast/expr_ext.rs | 186 ++++-------------- crates/syntax/src/ast/make.rs | 3 +- crates/syntax/src/ast/operators.rs | 106 ++++++---- 12 files changed, 160 insertions(+), 233 deletions(-) diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 1c8a33a33a..d8dac66556 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs @@ -27,8 +27,8 @@ use crate::{ builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, db::DefDatabase, expr::{ - dummy_expr_id, Array, BinaryOp, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal, - MatchArm, MatchGuard, Pat, PatId, RecordFieldPat, RecordLitField, Statement, + dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal, MatchArm, + MatchGuard, Pat, PatId, RecordFieldPat, RecordLitField, Statement, }, intern::Interned, item_scope::BuiltinShadowMode, @@ -508,7 +508,7 @@ impl ExprCollector<'_> { ast::Expr::BinExpr(e) => { let lhs = self.collect_expr_opt(e.lhs()); let rhs = self.collect_expr_opt(e.rhs()); - let op = e.op_kind().map(BinaryOp::from); + let op = e.op_kind(); self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr) } ast::Expr::TupleExpr(e) => { diff --git a/crates/ide_assists/src/handlers/apply_demorgan.rs b/crates/ide_assists/src/handlers/apply_demorgan.rs index b8822595d4..9c888e2d4e 100644 --- a/crates/ide_assists/src/handlers/apply_demorgan.rs +++ b/crates/ide_assists/src/handlers/apply_demorgan.rs @@ -26,7 +26,13 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<( let expr = ctx.find_node_at_offset::()?; let op = expr.op_kind()?; let op_range = expr.op_token()?.text_range(); - let opposite_op = opposite_logic_op(op)?; + + let opposite_op = match op { + ast::BinaryOp::LogicOp(ast::LogicOp::And) => "||", + ast::BinaryOp::LogicOp(ast::LogicOp::Or) => "&&", + _ => return None, + }; + let cursor_in_range = op_range.contains_range(ctx.frange.range); if !cursor_in_range { return None; @@ -136,15 +142,6 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<( ) } -// Return the opposite text for a given logical operator, if it makes sense -fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> { - match kind { - ast::BinOp::BooleanOr => Some("&&"), - ast::BinOp::BooleanAnd => Some("||"), - _ => None, - } -} - #[cfg(test)] mod tests { use crate::tests::{check_assist, check_assist_not_applicable}; diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs index 692c3f7f07..5e96cec511 100644 --- a/crates/ide_assists/src/handlers/extract_function.rs +++ b/crates/ide_assists/src/handlers/extract_function.rs @@ -892,7 +892,7 @@ fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Optio let parent = expr.syntax().parent()?; if let Some(bin_expr) = ast::BinExpr::cast(parent.clone()) { - if bin_expr.op_kind()?.is_assignment() { + if matches!(bin_expr.op_kind()?, ast::BinaryOp::Assignment { .. }) { return Some(bin_expr.lhs()?.syntax() == expr.syntax()); } return Some(false); diff --git a/crates/ide_assists/src/handlers/flip_binexpr.rs b/crates/ide_assists/src/handlers/flip_binexpr.rs index 209e5d43c2..0117b8a84b 100644 --- a/crates/ide_assists/src/handlers/flip_binexpr.rs +++ b/crates/ide_assists/src/handlers/flip_binexpr.rs @@ -1,4 +1,4 @@ -use syntax::ast::{AstNode, BinExpr, BinOp}; +use syntax::ast::{self, AstNode, BinExpr}; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -56,14 +56,19 @@ enum FlipAction { DontFlip, } -impl From for FlipAction { - fn from(op_kind: BinOp) -> Self { +impl From for FlipAction { + fn from(op_kind: ast::BinaryOp) -> Self { match op_kind { - kind if kind.is_assignment() => FlipAction::DontFlip, - BinOp::GreaterTest => FlipAction::FlipAndReplaceOp("<"), - BinOp::GreaterEqualTest => FlipAction::FlipAndReplaceOp("<="), - BinOp::LesserTest => FlipAction::FlipAndReplaceOp(">"), - BinOp::LesserEqualTest => FlipAction::FlipAndReplaceOp(">="), + ast::BinaryOp::Assignment { .. } => FlipAction::DontFlip, + ast::BinaryOp::CmpOp(ast::CmpOp::Ord { ordering, strict }) => { + let rev_op = match (ordering, strict) { + (ast::Ordering::Less, true) => ">", + (ast::Ordering::Less, false) => ">=", + (ast::Ordering::Greater, true) => "<", + (ast::Ordering::Greater, false) => "<=", + }; + FlipAction::FlipAndReplaceOp(rev_op) + } _ => FlipAction::Flip, } } diff --git a/crates/ide_assists/src/handlers/pull_assignment_up.rs b/crates/ide_assists/src/handlers/pull_assignment_up.rs index 4d0041e424..8946ecfac7 100644 --- a/crates/ide_assists/src/handlers/pull_assignment_up.rs +++ b/crates/ide_assists/src/handlers/pull_assignment_up.rs @@ -39,7 +39,7 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext) -> Opti let assign_expr = ctx.find_node_at_offset::()?; let op_kind = assign_expr.op_kind()?; - if op_kind != ast::BinOp::Assignment { + if op_kind != (ast::BinaryOp::Assignment { op: None }) { cov_mark::hit!(test_cant_pull_non_assignments); return None; } @@ -143,7 +143,7 @@ impl<'a> AssignmentsCollector<'a> { } fn collect_expr(&mut self, expr: &ast::BinExpr) -> Option<()> { - if expr.op_kind()? == ast::BinOp::Assignment + if expr.op_kind()? == (ast::BinaryOp::Assignment { op: None }) && is_equivalent(self.sema, &expr.lhs()?, &self.common_lhs) { self.assignments.push((expr.clone(), expr.rhs()?)); diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs index 476525d1be..ee81e5048a 100644 --- a/crates/ide_assists/src/utils.rs +++ b/crates/ide_assists/src/utils.rs @@ -210,12 +210,17 @@ pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr { fn invert_special_case(expr: &ast::Expr) -> Option { match expr { ast::Expr::BinExpr(bin) => match bin.op_kind()? { - ast::BinOp::NegatedEqualityTest => bin.replace_op(T![==]).map(|it| it.into()), - ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()), - ast::BinOp::LesserTest => bin.replace_op(T![>=]).map(|it| it.into()), - ast::BinOp::LesserEqualTest => bin.replace_op(T![>]).map(|it| it.into()), - ast::BinOp::GreaterTest => bin.replace_op(T![<=]).map(|it| it.into()), - ast::BinOp::GreaterEqualTest => bin.replace_op(T![<]).map(|it| it.into()), + ast::BinaryOp::CmpOp(op) => { + let rev_op = match op { + ast::CmpOp::Eq { negated: false } => T![!=], + ast::CmpOp::Eq { negated: true } => T![==], + ast::CmpOp::Ord { ordering: ast::Ordering::Less, strict: true } => T![>=], + ast::CmpOp::Ord { ordering: ast::Ordering::Less, strict: false } => T![>], + ast::CmpOp::Ord { ordering: ast::Ordering::Greater, strict: true } => T![<=], + ast::CmpOp::Ord { ordering: ast::Ordering::Greater, strict: false } => T![<], + }; + bin.replace_op(rev_op).map(ast::Expr::from) + } // Parenthesize other expressions before prefixing `!` _ => Some(make::expr_prefix(T![!], make::expr_paren(expr.clone()))), }, diff --git a/crates/ide_assists/src/utils/gen_trait_fn_body.rs b/crates/ide_assists/src/utils/gen_trait_fn_body.rs index 111fa0b23f..5a8914b331 100644 --- a/crates/ide_assists/src/utils/gen_trait_fn_body.rs +++ b/crates/ide_assists/src/utils/gen_trait_fn_body.rs @@ -1,7 +1,7 @@ //! This module contains functions to generate default trait impl function bodies where possible. use syntax::{ - ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner}, + ast::{self, edit::AstNodeEdit, make, AstNode, BinaryOp, CmpOp, LogicOp, NameOwner}, ted, }; @@ -325,7 +325,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { fn gen_eq_chain(expr: Option, cmp: ast::Expr) -> Option { match expr { - Some(expr) => Some(make::expr_op(ast::BinOp::BooleanAnd, expr, cmp)), + Some(expr) => Some(make::expr_bin_op(expr, BinaryOp::LogicOp(LogicOp::And), cmp)), None => Some(cmp), } } @@ -362,7 +362,8 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let lhs = make::expr_call(make_discriminant()?, make::arg_list(Some(lhs_name.clone()))); let rhs_name = make::expr_path(make::ext::ident_path("other")); let rhs = make::expr_call(make_discriminant()?, make::arg_list(Some(rhs_name.clone()))); - let eq_check = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs); + let eq_check = + make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs); let mut case_count = 0; let mut arms = vec![]; @@ -386,7 +387,11 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let lhs = make::expr_path(make::ext::ident_path(l_name)); let rhs = make::expr_path(make::ext::ident_path(r_name)); - let cmp = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs); + let cmp = make::expr_bin_op( + lhs, + BinaryOp::CmpOp(CmpOp::Eq { negated: false }), + rhs, + ); expr = gen_eq_chain(expr, cmp); } @@ -415,7 +420,11 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let lhs = make::expr_path(make::ext::ident_path(&l_name)); let rhs = make::expr_path(make::ext::ident_path(&r_name)); - let cmp = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs); + let cmp = make::expr_bin_op( + lhs, + BinaryOp::CmpOp(CmpOp::Eq { negated: false }), + rhs, + ); expr = gen_eq_chain(expr, cmp); } @@ -455,7 +464,8 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let lhs = make::expr_field(lhs, &field.name()?.to_string()); let rhs = make::expr_path(make::ext::ident_path("other")); let rhs = make::expr_field(rhs, &field.name()?.to_string()); - let cmp = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs); + let cmp = + make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs); expr = gen_eq_chain(expr, cmp); } make::block_expr(None, expr).indent(ast::edit::IndentLevel(1)) @@ -469,7 +479,8 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let lhs = make::expr_field(lhs, &idx); let rhs = make::expr_path(make::ext::ident_path("other")); let rhs = make::expr_field(rhs, &idx); - let cmp = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs); + let cmp = + make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs); expr = gen_eq_chain(expr, cmp); } make::block_expr(None, expr).indent(ast::edit::IndentLevel(1)) diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 980abae93c..627f5e97fa 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs @@ -655,7 +655,7 @@ fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option { - if expr.op_kind()?.is_assignment() { + if matches!(expr.op_kind()?, ast::BinaryOp::Assignment { .. }) { // If the variable or field ends on the LHS's end then it's a Write (covers fields and locals). // FIXME: This is not terribly accurate. if let Some(lhs) = expr.lhs() { diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index 799ba0ced9..e26c5b7ad9 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs @@ -18,13 +18,13 @@ use crate::{ }; pub use self::{ - expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind}, + expr_ext::{ArrayExprKind, Effect, ElseBranch, LiteralKind}, generated::{nodes::*, tokens::*}, node_ext::{ AttrKind, AttrsOwnerNode, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind, }, - operators::{ArithOp, BinaryOp, CmpOp, LogicOp, RangeOp, UnaryOp, Ordering}, + operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp}, token_ext::{ CommentKind, CommentPlacement, CommentShape, FormatSpecifier, HasFormatSpecifier, IsString, QuoteOffsets, Radix, diff --git a/crates/syntax/src/ast/expr_ext.rs b/crates/syntax/src/ast/expr_ext.rs index 3ebb85fc83..4598066bc9 100644 --- a/crates/syntax/src/ast/expr_ext.rs +++ b/crates/syntax/src/ast/expr_ext.rs @@ -5,7 +5,7 @@ use rowan::WalkEvent; use crate::{ ast::{ self, - operators::{RangeOp, UnaryOp}, + operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp}, support, AstChildren, AstNode, }, AstToken, @@ -213,127 +213,51 @@ impl ast::PrefixExpr { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum BinOp { - /// The `||` operator for boolean OR - BooleanOr, - /// The `&&` operator for boolean AND - BooleanAnd, - /// The `==` operator for equality testing - EqualityTest, - /// The `!=` operator for equality testing - NegatedEqualityTest, - /// The `<=` operator for lesser-equal testing - LesserEqualTest, - /// The `>=` operator for greater-equal testing - GreaterEqualTest, - /// The `<` operator for comparison - LesserTest, - /// The `>` operator for comparison - GreaterTest, - /// The `+` operator for addition - Addition, - /// The `*` operator for multiplication - Multiplication, - /// The `-` operator for subtraction - Subtraction, - /// The `/` operator for division - Division, - /// The `%` operator for remainder after division - Remainder, - /// The `<<` operator for left shift - LeftShift, - /// The `>>` operator for right shift - RightShift, - /// The `^` operator for bitwise XOR - BitwiseXor, - /// The `|` operator for bitwise OR - BitwiseOr, - /// The `&` operator for bitwise AND - BitwiseAnd, - /// The `=` operator for assignment - Assignment, - /// The `+=` operator for assignment after addition - AddAssign, - /// The `/=` operator for assignment after division - DivAssign, - /// The `*=` operator for assignment after multiplication - MulAssign, - /// The `%=` operator for assignment after remainders - RemAssign, - /// The `>>=` operator for assignment after shifting right - ShrAssign, - /// The `<<=` operator for assignment after shifting left - ShlAssign, - /// The `-=` operator for assignment after subtraction - SubAssign, - /// The `|=` operator for assignment after bitwise OR - BitOrAssign, - /// The `&=` operator for assignment after bitwise AND - BitAndAssign, - /// The `^=` operator for assignment after bitwise XOR - BitXorAssign, -} - -impl BinOp { - pub fn is_assignment(self) -> bool { - matches!( - self, - BinOp::Assignment - | BinOp::AddAssign - | BinOp::DivAssign - | BinOp::MulAssign - | BinOp::RemAssign - | BinOp::ShrAssign - | BinOp::ShlAssign - | BinOp::SubAssign - | BinOp::BitOrAssign - | BinOp::BitAndAssign - | BinOp::BitXorAssign - ) - } -} - impl ast::BinExpr { - pub fn op_details(&self) -> Option<(SyntaxToken, BinOp)> { + pub fn op_details(&self) -> Option<(SyntaxToken, BinaryOp)> { self.syntax().children_with_tokens().filter_map(|it| it.into_token()).find_map(|c| { + #[rustfmt::skip] let bin_op = match c.kind() { - T![||] => BinOp::BooleanOr, - T![&&] => BinOp::BooleanAnd, - T![==] => BinOp::EqualityTest, - T![!=] => BinOp::NegatedEqualityTest, - T![<=] => BinOp::LesserEqualTest, - T![>=] => BinOp::GreaterEqualTest, - T![<] => BinOp::LesserTest, - T![>] => BinOp::GreaterTest, - T![+] => BinOp::Addition, - T![*] => BinOp::Multiplication, - T![-] => BinOp::Subtraction, - T![/] => BinOp::Division, - T![%] => BinOp::Remainder, - T![<<] => BinOp::LeftShift, - T![>>] => BinOp::RightShift, - T![^] => BinOp::BitwiseXor, - T![|] => BinOp::BitwiseOr, - T![&] => BinOp::BitwiseAnd, - T![=] => BinOp::Assignment, - T![+=] => BinOp::AddAssign, - T![/=] => BinOp::DivAssign, - T![*=] => BinOp::MulAssign, - T![%=] => BinOp::RemAssign, - T![>>=] => BinOp::ShrAssign, - T![<<=] => BinOp::ShlAssign, - T![-=] => BinOp::SubAssign, - T![|=] => BinOp::BitOrAssign, - T![&=] => BinOp::BitAndAssign, - T![^=] => BinOp::BitXorAssign, + T![||] => BinaryOp::LogicOp(LogicOp::Or), + T![&&] => BinaryOp::LogicOp(LogicOp::And), + + T![==] => BinaryOp::CmpOp(CmpOp::Eq { negated: false }), + T![!=] => BinaryOp::CmpOp(CmpOp::Eq { negated: true }), + T![<=] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false }), + T![>=] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false }), + T![<] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true }), + T![>] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true }), + + T![+] => BinaryOp::ArithOp(ArithOp::Add), + T![*] => BinaryOp::ArithOp(ArithOp::Mul), + T![-] => BinaryOp::ArithOp(ArithOp::Sub), + T![/] => BinaryOp::ArithOp(ArithOp::Div), + T![%] => BinaryOp::ArithOp(ArithOp::Rem), + T![<<] => BinaryOp::ArithOp(ArithOp::Shl), + T![>>] => BinaryOp::ArithOp(ArithOp::Shr), + T![^] => BinaryOp::ArithOp(ArithOp::BitXor), + T![|] => BinaryOp::ArithOp(ArithOp::BitOr), + T![&] => BinaryOp::ArithOp(ArithOp::BitAnd), + + T![=] => BinaryOp::Assignment { op: None }, + T![+=] => BinaryOp::Assignment { op: Some(ArithOp::Add) }, + T![*=] => BinaryOp::Assignment { op: Some(ArithOp::Mul) }, + T![-=] => BinaryOp::Assignment { op: Some(ArithOp::Sub) }, + T![/=] => BinaryOp::Assignment { op: Some(ArithOp::Div) }, + T![%=] => BinaryOp::Assignment { op: Some(ArithOp::Rem) }, + T![<<=] => BinaryOp::Assignment { op: Some(ArithOp::Shl) }, + T![>>=] => BinaryOp::Assignment { op: Some(ArithOp::Shr) }, + T![^=] => BinaryOp::Assignment { op: Some(ArithOp::BitXor) }, + T![|=] => BinaryOp::Assignment { op: Some(ArithOp::BitOr) }, + T![&=] => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) }, + _ => return None, }; Some((c, bin_op)) }) } - pub fn op_kind(&self) -> Option { + pub fn op_kind(&self) -> Option { self.op_details().map(|t| t.1) } @@ -357,42 +281,6 @@ impl ast::BinExpr { } } -impl std::fmt::Display for BinOp { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - BinOp::BooleanOr => write!(f, "||"), - BinOp::BooleanAnd => write!(f, "&&"), - BinOp::EqualityTest => write!(f, "=="), - BinOp::NegatedEqualityTest => write!(f, "!="), - BinOp::LesserEqualTest => write!(f, "<="), - BinOp::GreaterEqualTest => write!(f, ">="), - BinOp::LesserTest => write!(f, "<"), - BinOp::GreaterTest => write!(f, ">"), - BinOp::Addition => write!(f, "+"), - BinOp::Multiplication => write!(f, "*"), - BinOp::Subtraction => write!(f, "-"), - BinOp::Division => write!(f, "/"), - BinOp::Remainder => write!(f, "%"), - BinOp::LeftShift => write!(f, "<<"), - BinOp::RightShift => write!(f, ">>"), - BinOp::BitwiseXor => write!(f, "^"), - BinOp::BitwiseOr => write!(f, "|"), - BinOp::BitwiseAnd => write!(f, "&"), - BinOp::Assignment => write!(f, "="), - BinOp::AddAssign => write!(f, "+="), - BinOp::DivAssign => write!(f, "/="), - BinOp::MulAssign => write!(f, "*="), - BinOp::RemAssign => write!(f, "%="), - BinOp::ShrAssign => write!(f, ">>="), - BinOp::ShlAssign => write!(f, "<<="), - BinOp::SubAssign => write!(f, "-"), - BinOp::BitOrAssign => write!(f, "|="), - BinOp::BitAndAssign => write!(f, "&="), - BinOp::BitXorAssign => write!(f, "^="), - } - } -} - impl ast::RangeExpr { fn op_details(&self) -> Option<(usize, SyntaxToken, RangeOp)> { self.syntax().children_with_tokens().enumerate().find_map(|(ix, child)| { diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index e6fab72ac0..5494dd1d3e 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs @@ -276,7 +276,8 @@ pub fn expr_path(path: ast::Path) -> ast::Expr { pub fn expr_continue() -> ast::Expr { expr_from_text("continue") } -pub fn expr_op(op: ast::BinOp, lhs: ast::Expr, rhs: ast::Expr) -> ast::Expr { +// Consider `op: SyntaxKind` instead for nicer syntax at the call-site? +pub fn expr_bin_op(lhs: ast::Expr, op: ast::BinaryOp, rhs: ast::Expr) -> ast::Expr { expr_from_text(&format!("{} {} {}", lhs, op, rhs)) } pub fn expr_break(expr: Option) -> ast::Expr { diff --git a/crates/syntax/src/ast/operators.rs b/crates/syntax/src/ast/operators.rs index 84cb7c0b01..a687ba0b77 100644 --- a/crates/syntax/src/ast/operators.rs +++ b/crates/syntax/src/ast/operators.rs @@ -1,3 +1,9 @@ +//! Defines a bunch of data-less enums for unary and binary operators. +//! +//! Types here don't know about AST, this allows re-using them for both AST and +//! HIR. +use std::fmt; + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum RangeOp { /// `..` @@ -8,11 +14,11 @@ pub enum RangeOp { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum UnaryOp { - /// The `*` operator for dereferencing + /// `*` Deref, - /// The `!` operator for logical inversion + /// `!` Not, - /// The `-` operator for negation + /// `-` Neg, } @@ -56,47 +62,61 @@ pub enum ArithOp { BitAnd, } -use crate::ast; -impl From for BinaryOp { - fn from(ast_op: ast::BinOp) -> Self { - match ast_op { - ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or), - ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And), - ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }), - ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }), - ast::BinOp::LesserEqualTest => { - BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false }) +impl fmt::Display for LogicOp { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let res = match self { + LogicOp::And => "&&", + LogicOp::Or => "||", + }; + f.write_str(res) + } +} + +impl fmt::Display for ArithOp { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let res = match self { + ArithOp::Add => "+", + ArithOp::Mul => "*", + ArithOp::Sub => "-", + ArithOp::Div => "/", + ArithOp::Rem => "%", + ArithOp::Shl => "<<", + ArithOp::Shr => ">>", + ArithOp::BitXor => "^", + ArithOp::BitOr => "|", + ArithOp::BitAnd => "&", + }; + f.write_str(res) + } +} + +impl fmt::Display for CmpOp { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let res = match self { + CmpOp::Eq { negated: false } => "==", + CmpOp::Eq { negated: true } => "!=", + CmpOp::Ord { ordering: Ordering::Less, strict: false } => "<=", + CmpOp::Ord { ordering: Ordering::Less, strict: true } => "<", + CmpOp::Ord { ordering: Ordering::Greater, strict: false } => ">=", + CmpOp::Ord { ordering: Ordering::Greater, strict: true } => ">", + }; + f.write_str(res) + } +} + +impl fmt::Display for BinaryOp { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + BinaryOp::LogicOp(op) => fmt::Display::fmt(op, f), + BinaryOp::ArithOp(op) => fmt::Display::fmt(op, f), + BinaryOp::CmpOp(op) => fmt::Display::fmt(op, f), + BinaryOp::Assignment { op } => { + f.write_str("=")?; + if let Some(op) = op { + fmt::Display::fmt(op, f)?; + } + Ok(()) } - ast::BinOp::GreaterEqualTest => { - BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false }) - } - ast::BinOp::LesserTest => { - BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true }) - } - ast::BinOp::GreaterTest => { - BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true }) - } - ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add), - ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul), - ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub), - ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div), - ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem), - ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl), - ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr), - ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor), - ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr), - ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd), - ast::BinOp::Assignment => BinaryOp::Assignment { op: None }, - ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) }, - ast::BinOp::DivAssign => BinaryOp::Assignment { op: Some(ArithOp::Div) }, - ast::BinOp::MulAssign => BinaryOp::Assignment { op: Some(ArithOp::Mul) }, - ast::BinOp::RemAssign => BinaryOp::Assignment { op: Some(ArithOp::Rem) }, - ast::BinOp::ShlAssign => BinaryOp::Assignment { op: Some(ArithOp::Shl) }, - ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) }, - ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) }, - ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) }, - ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) }, - ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) }, } } }