"#,
expect![[r#"
fn public_method() fn()
- ct PUBLIC_CONST pub const PUBLIC_CONST: u32 = 1;
- ta PublicType pub type PublicType = u32;
+ ct PUBLIC_CONST pub const PUBLIC_CONST: u32;
+ ta PublicType pub type PublicType;
"#]],
);
}
expect![[r#"
ta SubTy (as Sub) type SubTy;
ta Ty (as Super) type Ty;
- ct CONST (as Super) const CONST: u8 = 0;
+ 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)
"#]],
}
"#,
expect![[r#"
- ct MAX pub const MAX: Self = 255;
+ ct MAX pub const MAX: Self;
me func(…) fn(self)
"#]],
);
for import in imports.into_iter() {
builder.add_import(import);
}
- builder.detail(snip.description.as_deref().unwrap_or_default());
+ builder.set_detail(snip.description.clone());
builder.add_to(acc);
},
);
kind: SymbolKind(
Variant,
),
- detail: "{ x: i32, y: i32 }",
+ detail: "{x: i32, y: i32}",
},
]
"#]],
//! Renderer for `enum` variants.
-use std::iter;
+use std::{iter, mem};
use hir::{HasAttrs, HirDisplay};
use ide_db::SymbolKind;
-use itertools::Itertools;
+use stdx::format_to;
use crate::{
item::{CompletionItem, ImportEdit},
.into_iter()
.map(|field| (field.name(self.ctx.db()), field.ty(self.ctx.db())));
+ let mut b = String::new();
+ let mut first_run = true;
match self.variant_kind {
- hir::StructKind::Tuple | hir::StructKind::Unit => format!(
- "({})",
- detail_types.map(|(_, t)| t.display(self.ctx.db()).to_string()).format(", ")
- ),
- hir::StructKind::Record => format!(
- "{{ {} }}",
- detail_types
- .map(|(n, t)| format!("{}: {}", n, t.display(self.ctx.db()).to_string()))
- .format(", ")
- ),
+ hir::StructKind::Tuple | hir::StructKind::Unit => {
+ format_to!(b, "(");
+ for (_, t) in detail_types {
+ if !mem::take(&mut first_run) {
+ format_to!(b, ", ");
+ }
+ format_to!(b, "{}", t.display(self.ctx.db()));
+ }
+ format_to!(b, ")");
+ }
+ hir::StructKind::Record => {
+ format_to!(b, "{{");
+ for (n, t) in detail_types {
+ if !mem::take(&mut first_run) {
+ format_to!(b, ", ");
+ }
+ format_to!(b, "{}: {}", n, t.display(self.ctx.db()));
+ }
+ format_to!(b, "}}");
+ }
}
+ b
}
}
use hir::{AsAssocItem, HasSource, HirDisplay};
use ide_db::SymbolKind;
use itertools::Itertools;
+use stdx::format_to;
use syntax::ast;
use crate::{
fn detail(&self) -> String {
let ret_ty = self.func.ret_type(self.ctx.db());
- let ret = if ret_ty.is_unit() {
- // Omit the return type if it is the unit type
- String::new()
- } else {
- format!(" {}", self.ty_display())
- };
-
- format!("fn({}){}", self.params_display(), ret)
+ let mut detail = format!("fn({})", self.params_display());
+ if !ret_ty.is_unit() {
+ format_to!(detail, " -> {}", ret_ty.display(self.ctx.db()));
+ }
+ detail
}
fn params_display(&self) -> String {
}
}
- fn ty_display(&self) -> String {
- let ret_ty = self.func.ret_type(self.ctx.db());
-
- format!("-> {}", ret_ty.display(self.ctx.db()))
- }
-
fn params(&self) -> Params {
let ast_params = match self.ast_node.param_list() {
Some(it) => it,
imports.push(green);
}
let snippet = snippet.iter().join("\n");
- let description = if description.is_empty() { None } else { Some(description.into()) };
+ let description = (!description.is_empty())
+ .then(|| description.split_once('\n').map_or(description, |(it, _)| it))
+ .map(ToOwned::to_owned)
+ .map(Into::into);
Some((imports.into_boxed_slice(), snippet, description))
}
"#,
expect![[r#"
ev TupleV(…) (u32)
- ev RecordV { field: 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;
"#]],
);
}
"#,
expect![[r#"
ev TupleV(…) (u32)
- ev RecordV { field: 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;
"#]],
);
}
fn func(_: Enum::$0) {}
"#,
expect![[r#"
- ta AssocType type AssocType = ();
+ ta AssocType type AssocType;
"#]],
);
}
-//! This module contains utilities for turning SyntaxNodes and HIR types
-//! into types that may be used to render in a UI.
+//! This module contains utilities for rendering syntax nodes into a string representing their signature.
-use crate::{
- ast::{self, AstNode, HasAttrs, HasGenericParams, HasName},
- SyntaxKind::{ATTR, COMMENT},
-};
+use crate::ast::{self, HasAttrs, HasGenericParams, HasName};
use ast::HasVisibility;
use stdx::format_to;
}
pub fn const_label(node: &ast::Const) -> String {
- let label: String = node
- .syntax()
- .children_with_tokens()
- .filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR))
- .map(|node| node.to_string())
- .collect();
-
- label.trim().to_owned()
+ 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 label: String = node
- .syntax()
- .children_with_tokens()
- .filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR))
- .map(|node| node.to_string())
- .collect();
-
- label.trim().to_owned()
+ 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 {