aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/utils.rs')
-rw-r--r--crates/ra_assists/src/utils.rs75
1 files changed, 73 insertions, 2 deletions
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 0d5722295..6ff44c95c 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -1,10 +1,81 @@
1//! Assorted functions shared by several assists. 1//! Assorted functions shared by several assists.
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast::{self, make}, 4 ast::{self, make, NameOwner},
5 T, 5 AstNode, T,
6}; 6};
7 7
8use hir::db::HirDatabase;
9use rustc_hash::FxHashSet;
10
11pub fn get_missing_impl_items(
12 db: &impl HirDatabase,
13 analyzer: &hir::SourceAnalyzer,
14 impl_block: &ast::ImplBlock,
15) -> Vec<hir::AssocItem> {
16 // Names must be unique between constants and functions. However, type aliases
17 // may share the same name as a function or constant.
18 let mut impl_fns_consts = FxHashSet::default();
19 let mut impl_type = FxHashSet::default();
20
21 if let Some(item_list) = impl_block.item_list() {
22 for item in item_list.impl_items() {
23 match item {
24 ast::ImplItem::FnDef(f) => {
25 if let Some(n) = f.name() {
26 impl_fns_consts.insert(n.syntax().to_string());
27 }
28 }
29
30 ast::ImplItem::TypeAliasDef(t) => {
31 if let Some(n) = t.name() {
32 impl_type.insert(n.syntax().to_string());
33 }
34 }
35
36 ast::ImplItem::ConstDef(c) => {
37 if let Some(n) = c.name() {
38 impl_fns_consts.insert(n.syntax().to_string());
39 }
40 }
41 }
42 }
43 }
44
45 resolve_target_trait(db, analyzer, impl_block).map_or(vec![], |target_trait| {
46 target_trait
47 .items(db)
48 .iter()
49 .filter(|i| match i {
50 hir::AssocItem::Function(f) => !impl_fns_consts.contains(&f.name(db).to_string()),
51 hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(db).to_string()),
52 hir::AssocItem::Const(c) => c
53 .name(db)
54 .map(|n| !impl_fns_consts.contains(&n.to_string()))
55 .unwrap_or_default(),
56 })
57 .cloned()
58 .collect()
59 })
60}
61
62pub(crate) fn resolve_target_trait(
63 db: &impl HirDatabase,
64 analyzer: &hir::SourceAnalyzer,
65 impl_block: &ast::ImplBlock,
66) -> Option<hir::Trait> {
67 let ast_path = impl_block
68 .target_trait()
69 .map(|it| it.syntax().clone())
70 .and_then(ast::PathType::cast)?
71 .path()?;
72
73 match analyzer.resolve_path(db, &ast_path) {
74 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def),
75 _ => None,
76 }
77}
78
8pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr { 79pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr {
9 if let Some(expr) = invert_special_case(&expr) { 80 if let Some(expr) = invert_special_case(&expr) {
10 return expr; 81 return expr;