aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists')
-rw-r--r--crates/ra_assists/src/lib.rs2
-rw-r--r--crates/ra_assists/src/utils.rs77
2 files changed, 76 insertions, 3 deletions
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 828a8e9e8..cb124eaf0 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -9,7 +9,7 @@ mod assist_ctx;
9mod marks; 9mod marks;
10#[cfg(test)] 10#[cfg(test)]
11mod doc_tests; 11mod doc_tests;
12mod utils; 12pub mod utils;
13pub mod ast_transform; 13pub mod ast_transform;
14 14
15use ra_db::FileRange; 15use ra_db::FileRange;
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 0d5722295..7bc21c6e4 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -1,10 +1,83 @@
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;
9
10use rustc_hash::FxHashSet;
11
12pub fn get_missing_impl_items(
13 db: &impl HirDatabase,
14 analyzer: &hir::SourceAnalyzer,
15 impl_block: &ast::ImplBlock,
16) -> Vec<hir::AssocItem> {
17 // since the names are unique only to each associated type (fn/type/const),
18 // create buckets of each already implemented type that we'll use in the
19 // lookup later.
20 let mut impl_fns = FxHashSet::default();
21 let mut impl_type = FxHashSet::default();
22 let mut impl_const = FxHashSet::default();
23
24 if let Some(item_list) = impl_block.item_list() {
25 for item in item_list.impl_items() {
26 match item {
27 ast::ImplItem::FnDef(f) => {
28 if let Some(n) = f.name() {
29 impl_fns.insert(n.syntax().to_string());
30 }
31 }
32
33 ast::ImplItem::TypeAliasDef(t) => {
34 if let Some(n) = t.name() {
35 impl_type.insert(n.syntax().to_string());
36 }
37 }
38
39 ast::ImplItem::ConstDef(c) => {
40 if let Some(n) = c.name() {
41 impl_const.insert(n.syntax().to_string());
42 }
43 }
44 }
45 }
46 }
47
48 resolve_target_trait(db, analyzer, impl_block).map_or(vec![], |target_trait| {
49 target_trait
50 .items(db)
51 .iter()
52 .filter(|i| match i {
53 hir::AssocItem::Function(f) => !impl_fns.contains(&f.name(db).to_string()),
54 hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(db).to_string()),
55 hir::AssocItem::Const(c) => {
56 c.name(db).map(|n| !impl_const.contains(&n.to_string())).unwrap_or_default()
57 }
58 })
59 .map(|i| i.clone())
60 .collect()
61 })
62}
63
64fn resolve_target_trait(
65 db: &impl HirDatabase,
66 analyzer: &hir::SourceAnalyzer,
67 impl_block: &ast::ImplBlock,
68) -> Option<hir::Trait> {
69 let ast_path = impl_block
70 .target_trait()
71 .map(|it| it.syntax().clone())
72 .and_then(ast::PathType::cast)?
73 .path()?;
74
75 match analyzer.resolve_path(db, &ast_path) {
76 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def),
77 _ => None,
78 }
79}
80
8pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr { 81pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr {
9 if let Some(expr) = invert_special_case(&expr) { 82 if let Some(expr) = invert_special_case(&expr) {
10 return expr; 83 return expr;