diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs index ee81e5048a3..e59fc6ba4fe 100644 --- a/crates/ide_assists/src/utils.rs +++ b/crates/ide_assists/src/utils.rs @@ -209,21 +209,22 @@ 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::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()))), - }, + ast::Expr::BinExpr(bin) => { + let bin = bin.clone_for_update(); + let op_token = bin.op_token()?; + let rev_token = match op_token.kind() { + T![==] => T![!=], + T![!=] => T![==], + T![<] => T![>=], + T![<=] => T![>], + T![>] => T![<=], + T![>=] => T![<], + // Parenthesize other expressions before prefixing `!` + _ => return Some(make::expr_prefix(T![!], make::expr_paren(expr.clone()))), + }; + ted::replace(op_token, make::token(rev_token)); + Some(bin.into()) + } ast::Expr::MethodCallExpr(mce) => { let receiver = mce.receiver()?; let method = mce.name_ref()?; diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs index ff31bf5cc73..af440426a66 100644 --- a/crates/syntax/src/ast/edit.rs +++ b/crates/syntax/src/ast/edit.rs @@ -1,28 +1,16 @@ //! This module contains functions for editing syntax trees. As the trees are //! immutable, all function here return a fresh copy of the tree, instead of //! doing an in-place modification. -use std::{ - fmt, iter, - ops::{self, RangeInclusive}, -}; +use std::{fmt, iter, ops}; use crate::{ algo, ast::{self, make, AstNode}, - ted, AstToken, NodeOrToken, SyntaxElement, SyntaxKind, + ted, AstToken, NodeOrToken, SyntaxElement, SyntaxKind::{ATTR, COMMENT, WHITESPACE}, SyntaxNode, SyntaxToken, }; -impl ast::BinExpr { - #[must_use] - pub fn replace_op(&self, op: SyntaxKind) -> Option { - let op_node: SyntaxElement = self.op_details()?.0.into(); - let to_insert: Option = Some(make::token(op).into()); - Some(self.replace_children(single_node(op_node), to_insert)) - } -} - impl ast::UseTree { /// Splits off the given prefix, making it the path component of the use tree, appending the rest of the path to all UseTreeList items. #[must_use] @@ -191,15 +179,6 @@ fn prev_tokens(token: SyntaxToken) -> impl Iterator { } pub trait AstNodeEdit: AstNode + Clone + Sized { - #[must_use] - fn replace_children( - &self, - to_replace: RangeInclusive, - to_insert: impl IntoIterator, - ) -> Self { - let new_syntax = algo::replace_children(self.syntax(), to_replace, to_insert); - Self::cast(new_syntax).unwrap() - } fn indent_level(&self) -> IndentLevel { IndentLevel::from_node(self.syntax()) } @@ -220,11 +199,6 @@ fn reset_indent(&self) -> Self { impl AstNodeEdit for N {} -fn single_node(element: impl Into) -> RangeInclusive { - let element = element.into(); - element.clone()..=element -} - #[test] fn test_increase_indent() { let arm_list = {