Repository: rust-analyzer/rust-analyzer
Pull request #11089 (2021-12-21 17:29:11)

internal: Render more completions from hir instead of ast
bors r+


Patch:
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index b0edec56ff..2b53d4a27b 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -420,7 +420,7 @@ where
     E: Fn(&D) -> Option<V>,
     V: Display,
 {
-    let label = if let Some(value) = (value_extractor)(&def) {
+    let label = if let Some(value) = value_extractor(&def) {
         format!("{} = {}", def.display(db), value)
     } else {
         def.display(db).to_string()
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index 656d46b10b..88fb395920 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -287,8 +287,8 @@ fn foo() { let _ = lib::S::$0 }
 "#,
             expect![[r#"
                 fn public_method() fn()
-                ct PUBLIC_CONST    pub const PUBLIC_CONST: u32;
-                ta PublicType      pub type PublicType;
+                ct PUBLIC_CONST    pub const PUBLIC_CONST: u32
+                ta PublicType      pub type PublicType = u32
             "#]],
         );
     }
@@ -377,12 +377,12 @@ trait Sub: Super {
 fn foo<T: Sub>() { T::$0 }
 "#,
             expect![[r#"
-                ta SubTy (as Sub)        type SubTy;
-                ta Ty (as Super)         type Ty;
-                ct C2 (as Sub)           const C2: ();
+                ta SubTy (as Sub)        type SubTy
+                ta Ty (as Super)         type Ty
+                ct C2 (as Sub)           const C2: ()
                 fn subfunc() (as Sub)    fn()
                 me submethod(…) (as Sub) fn(&self)
-                ct CONST (as Super)      const CONST: u8;
+                ct CONST (as Super)      const CONST: u8
                 fn func() (as Super)     fn()
                 me method(…) (as Super)  fn(&self)
             "#]],
@@ -417,12 +417,12 @@ impl<T> Sub for Wrap<T> {
 }
 "#,
             expect![[r#"
-                ta SubTy (as Sub)        type SubTy;
-                ta Ty (as Super)         type Ty;
-                ct CONST (as Super)      const CONST: u8;
+                ta SubTy (as Sub)        type SubTy
+                ta Ty (as Super)         type Ty
+                ct CONST (as Super)      const CONST: u8
                 fn func() (as Super)     fn()
                 me method(…) (as Super)  fn(&self)
-                ct C2 (as Sub)           const C2: ();
+                ct C2 (as Sub)           const C2: ()
                 fn subfunc() (as Sub)    fn()
                 me submethod(…) (as Sub) fn(&self)
             "#]],
@@ -653,7 +653,7 @@ impl u8 {
 }
 "#,
             expect![[r#"
-                ct MAX     pub const MAX: Self;
+                ct MAX     pub const MAX: Self
                 me func(…) fn(self)
             "#]],
         );
diff --git a/crates/ide_completion/src/render/builder_ext.rs b/crates/ide_completion/src/render/builder_ext.rs
index 8f8bd1dfcd..653515fec2 100644
--- a/crates/ide_completion/src/render/builder_ext.rs
+++ b/crates/ide_completion/src/render/builder_ext.rs
@@ -1,6 +1,7 @@
 //! Extensions for `Builder` structure required for item rendering.
 
 use itertools::Itertools;
+use syntax::SmolStr;
 
 use crate::{context::PathKind, item::Builder, patterns::ImmediateLocation, CompletionContext};
 
@@ -56,7 +57,7 @@ impl Builder {
     pub(super) fn add_call_parens(
         &mut self,
         ctx: &CompletionContext,
-        name: String,
+        name: SmolStr,
         params: Params,
     ) -> &mut Builder {
         if !self.should_add_parens(ctx) {
diff --git a/crates/ide_completion/src/render/const_.rs b/crates/ide_completion/src/render/const_.rs
index 65c9d1d63e..4c8258f12c 100644
--- a/crates/ide_completion/src/render/const_.rs
+++ b/crates/ide_completion/src/render/const_.rs
@@ -1,8 +1,7 @@
 //! Renderer for `const` fields.
 
-use hir::{AsAssocItem, HasSource};
+use hir::{AsAssocItem, HirDisplay};
 use ide_db::SymbolKind;
-use syntax::display::const_label;
 
 use crate::{item::CompletionItem, render::RenderContext};
 
@@ -14,8 +13,7 @@ pub(crate) fn render_const(ctx: RenderContext<'_>, const_: hir::Const) -> Option
 fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem> {
     let db = ctx.db();
     let name = const_.name(db)?.to_smol_str();
-    // FIXME: This is parsing files!
-    let detail = const_label(&const_.source(db)?.value);
+    let detail = const_.display(db).to_string();
 
     let mut item = CompletionItem::new(SymbolKind::Const, ctx.source_range(), name.clone());
     item.set_documentation(ctx.docs(const_))
diff --git a/crates/ide_completion/src/render/enum_variant.rs b/crates/ide_completion/src/render/enum_variant.rs
index f613f0dfde..4c276a9afe 100644
--- a/crates/ide_completion/src/render/enum_variant.rs
+++ b/crates/ide_completion/src/render/enum_variant.rs
@@ -5,6 +5,7 @@ use std::iter;
 use hir::{db::HirDatabase, HasAttrs, HirDisplay, StructKind};
 use ide_db::SymbolKind;
 use itertools::Itertools;
+use syntax::SmolStr;
 
 use crate::{
     item::{CompletionItem, ImportEdit},
@@ -48,10 +49,10 @@ fn render(
             false,
         ),
     };
+    let qualified_name = qualified_name.to_string();
+    let short_qualified_name: SmolStr = short_qualified_name.to_string().into();
 
-    // FIXME: ModPath::to_smol_str()?
-    let mut item =
-        CompletionItem::new(SymbolKind::Variant, ctx.source_range(), qualified_name.to_string());
+    let mut item = CompletionItem::new(SymbolKind::Variant, ctx.source_range(), qualified_name);
     item.set_documentation(variant.docs(db))
         .set_deprecated(ctx.is_deprecated(variant))
         .detail(detail(db, variant, variant_kind));
@@ -60,8 +61,6 @@ fn render(
         item.add_import(import_to_add);
     }
 
-    // FIXME: ModPath::to_smol_str()?
-    let short_qualified_name = short_qualified_name.to_string();
     if variant_kind == hir::StructKind::Tuple {
         cov_mark::hit!(inserts_parens_for_tuple_enums);
         let params = Params::Anonymous(variant.fields(db).len());
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs
index f166b87ab6..bd46e1fefb 100644
--- a/crates/ide_completion/src/render/function.rs
+++ b/crates/ide_completion/src/render/function.rs
@@ -52,10 +52,9 @@ fn render(
     let name = local_name.unwrap_or_else(|| func.name(db));
     let params = params(completion, func, &func_type);
 
-    // FIXME: SmolStr?
     let call = match &func_type {
-        FuncType::Method(Some(receiver)) => format!("{}.{}", receiver, &name),
-        _ => name.to_string(),
+        FuncType::Method(Some(receiver)) => format!("{}.{}", receiver, &name).into(),
+        _ => name.to_smol_str(),
     };
     let mut item = CompletionItem::new(
         if func.self_param(db).is_some() {
@@ -66,23 +65,6 @@ fn render(
         ctx.source_range(),
         call.clone(),
     );
-    item.set_documentation(ctx.docs(func))
-        .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
-        .detail(detail(db, func))
-        .add_call_parens(completion, call.clone(), params);
-
-    if import_to_add.is_none() {
-        if let Some(actm) = func.as_assoc_item(db) {
-            if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
-                item.trait_name(trt.name(db).to_smol_str());
-            }
-        }
-    }
-
-    if let Some(import_to_add) = import_to_add {
-        item.add_import(import_to_add);
-    }
-    item.lookup_by(name.to_smol_str());
 
     let ret_type = func.ret_type(db);
     item.set_relevance(CompletionRelevance {
@@ -100,6 +82,24 @@ fn render(
         }
     }
 
+    item.set_documentation(ctx.docs(func))
+        .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
+        .detail(detail(db, func))
+        .add_call_parens(completion, call, params);
+
+    if import_to_add.is_none() {
+        if let Some(actm) = func.as_assoc_item(db) {
+            if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
+                item.trait_name(trt.name(db).to_smol_str());
+            }
+        }
+    }
+
+    if let Some(import_to_add) = import_to_add {
+        item.add_import(import_to_add);
+    }
+    item.lookup_by(name.to_smol_str());
+
     item.build()
 }
 
diff --git a/crates/ide_completion/src/render/type_alias.rs b/crates/ide_completion/src/render/type_alias.rs
index 5df21fb36c..5bfb4349ed 100644
--- a/crates/ide_completion/src/render/type_alias.rs
+++ b/crates/ide_completion/src/render/type_alias.rs
@@ -1,8 +1,8 @@
 //! Renderer for type aliases.
 
-use hir::{AsAssocItem, HasSource};
+use hir::{AsAssocItem, HirDisplay};
 use ide_db::SymbolKind;
-use syntax::{ast::HasName, display::type_label};
+use syntax::SmolStr;
 
 use crate::{item::CompletionItem, render::RenderContext};
 
@@ -29,16 +29,12 @@ fn render(
 ) -> Option<CompletionItem> {
     let db = ctx.db();
 
-    // FIXME: This parses the file!
-    let ast_node = type_alias.source(db)?.value;
-    let name = ast_node.name().map(|name| {
-        if with_eq {
-            format!("{} = ", name.text())
-        } else {
-            name.text().to_string()
-        }
-    })?;
-    let detail = type_label(&ast_node);
+    let name = if with_eq {
+        SmolStr::from_iter([&*type_alias.name(db).to_smol_str(), " = "])
+    } else {
+        type_alias.name(db).to_smol_str()
+    };
+    let detail = type_alias.display(db).to_string();
 
     let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), name.clone());
     item.set_documentation(ctx.docs(type_alias))
diff --git a/crates/syntax/src/display.rs b/crates/syntax/src/display.rs
index e2115cbd2b..d03e94d058 100644
--- a/crates/syntax/src/display.rs
+++ b/crates/syntax/src/display.rs
@@ -50,42 +50,6 @@ pub fn function_declaration(node: &ast::Fn) -> String {
     buf
 }
 
-pub fn const_label(node: &ast::Const) -> String {
-    let mut s = String::new();
-    if let Some(vis) = node.visibility() {
-        format_to!(s, "{} ", vis);
-    }
-    format_to!(s, "const ");
-    if let Some(name) = node.name() {
-        format_to!(s, "{}", name);
-    } else {
-        format_to!(s, "?");
-    }
-    format_to!(s, ": ");
-    if let Some(ty) = node.ty() {
-        format_to!(s, "{}", ty);
-    } else {
-        format_to!(s, "?");
-    }
-    format_to!(s, ";");
-    s
-}
-
-pub fn type_label(node: &ast::TypeAlias) -> String {
-    let mut s = String::new();
-    if let Some(vis) = node.visibility() {
-        format_to!(s, "{} ", vis);
-    }
-    format_to!(s, "type ");
-    if let Some(name) = node.name() {
-        format_to!(s, "{}", name);
-    } else {
-        format_to!(s, "?");
-    }
-    format_to!(s, ";");
-    s
-}
-
 pub fn macro_label(node: &ast::Macro) -> String {
     let name = node.name();
     let mut s = String::new();


Test patch:
diff --git a/crates/ide_completion/src/tests/expression.rs b/crates/ide_completion/src/tests/expression.rs
index eba2a5e1ef..56a2cd6e9d 100644
--- a/crates/ide_completion/src/tests/expression.rs
+++ b/crates/ide_completion/src/tests/expression.rs
@@ -546,9 +546,9 @@ fn func() {
             ev TupleV(…)   (u32)
             ev RecordV     {field: u32}
             ev UnitV       ()
-            ct ASSOC_CONST const ASSOC_CONST: ();
+            ct ASSOC_CONST const ASSOC_CONST: ()
             fn assoc_fn()  fn()
-            ta AssocType   type AssocType;
+            ta AssocType   type AssocType = ()
         "#]],
     );
 }
diff --git a/crates/ide_completion/src/tests/pattern.rs b/crates/ide_completion/src/tests/pattern.rs
index 99e20b6ed0..c9a31eea84 100644
--- a/crates/ide_completion/src/tests/pattern.rs
+++ b/crates/ide_completion/src/tests/pattern.rs
@@ -294,9 +294,9 @@ fn func() {
             ev TupleV(…)   (u32)
             ev RecordV     {field: u32}
             ev UnitV       ()
-            ct ASSOC_CONST const ASSOC_CONST: ();
+            ct ASSOC_CONST const ASSOC_CONST: ()
             fn assoc_fn()  fn()
-            ta AssocType   type AssocType;
+            ta AssocType   type AssocType = ()
         "#]],
     );
 }
diff --git a/crates/ide_completion/src/tests/type_pos.rs b/crates/ide_completion/src/tests/type_pos.rs
index a76f97f3da..d6c1a787ff 100644
--- a/crates/ide_completion/src/tests/type_pos.rs
+++ b/crates/ide_completion/src/tests/type_pos.rs
@@ -148,7 +148,7 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
             kw self
             kw super
             kw crate
-            ta Foo =  (as Trait2) type Foo;
+            ta Foo =  (as Trait2) type Foo
             tp T
             cp CONST_PARAM
             tt Trait
@@ -199,7 +199,7 @@ impl Enum {
 fn func(_: Enum::$0) {}
 "#,
         expect![[r#"
-            ta AssocType type AssocType;
+            ta AssocType type AssocType = ()
         "#]],
     );
 }