Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/utils.rs')
-rw-r--r--crates/ide-assists/src/utils.rs44
1 files changed, 40 insertions, 4 deletions
diff --git a/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs
index 0830017bd0..3c26b04359 100644
--- a/crates/ide-assists/src/utils.rs
+++ b/crates/ide-assists/src/utils.rs
@@ -3,11 +3,13 @@
pub(crate) use gen_trait_fn_body::gen_trait_fn_body;
use hir::{
db::{ExpandDatabase, HirDatabase},
- HasAttrs as HirHasAttrs, HirDisplay, InFile, Semantics,
+ HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution, Semantics,
};
use ide_db::{
- famous_defs::FamousDefs, path_transform::PathTransform,
- syntax_helpers::prettify_macro_expansion, RootDatabase,
+ famous_defs::FamousDefs,
+ path_transform::PathTransform,
+ syntax_helpers::{node_ext::preorder_expr, prettify_macro_expansion},
+ RootDatabase,
};
use stdx::format_to;
use syntax::{
@@ -19,7 +21,7 @@ use syntax::{
},
ted, AstNode, AstToken, Direction, Edition, NodeOrToken, SourceFile,
SyntaxKind::*,
- SyntaxNode, SyntaxToken, TextRange, TextSize, T,
+ SyntaxNode, SyntaxToken, TextRange, TextSize, WalkEvent, T,
};
use crate::assist_context::{AssistContext, SourceChangeBuilder};
@@ -966,3 +968,37 @@ pub(crate) fn tt_from_syntax(node: SyntaxNode) -> Vec<NodeOrToken<ast::TokenTree
tt_stack.pop().expect("parent token tree was closed before it was completed").1
}
+
+pub fn is_body_const(sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr) -> bool {
+ let mut is_const = true;
+ preorder_expr(expr, &mut |ev| {
+ let expr = match ev {
+ WalkEvent::Enter(_) if !is_const => return true,
+ WalkEvent::Enter(expr) => expr,
+ WalkEvent::Leave(_) => return false,
+ };
+ match expr {
+ ast::Expr::CallExpr(call) => {
+ if let Some(ast::Expr::PathExpr(path_expr)) = call.expr() {
+ if let Some(PathResolution::Def(ModuleDef::Function(func))) =
+ path_expr.path().and_then(|path| sema.resolve_path(&path))
+ {
+ is_const &= func.is_const(sema.db);
+ }
+ }
+ }
+ ast::Expr::MethodCallExpr(call) => {
+ is_const &=
+ sema.resolve_method_call(&call).map(|it| it.is_const(sema.db)).unwrap_or(true)
+ }
+ ast::Expr::ForExpr(_)
+ | ast::Expr::ReturnExpr(_)
+ | ast::Expr::TryExpr(_)
+ | ast::Expr::YieldExpr(_)
+ | ast::Expr::AwaitExpr(_) => is_const = false,
+ _ => (),
+ }
+ !is_const
+ });
+ is_const
+}