From 0265778e86f7e130a921ab6307cfdcc0ad953fe0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 16 Jul 2020 21:32:20 +0200 Subject: Don't use function signature for Display --- .../ra_ide/src/completion/complete_trait_impl.rs | 9 ++-- crates/ra_ide/src/completion/presentation.rs | 6 ++- crates/ra_ide/src/display.rs | 38 ++++++++++++++- crates/ra_ide/src/display/function_signature.rs | 56 +--------------------- 4 files changed, 47 insertions(+), 62 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index 90f5b1c25..05e605670 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs @@ -43,7 +43,7 @@ use crate::{ completion::{ CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, }, - display::function_signature::FunctionSignature, + display::function_label, }; pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { @@ -125,8 +125,6 @@ fn add_function_impl( ctx: &CompletionContext, func: hir::Function, ) { - let signature = FunctionSignature::from_hir(ctx.db, func); - let fn_name = func.name(ctx.db).to_string(); let label = if !func.params(ctx.db).is_empty() { @@ -146,13 +144,14 @@ fn add_function_impl( }; let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end()); + let function_decl = function_label(&func.source(ctx.db).value); match ctx.config.snippet_cap { Some(cap) => { - let snippet = format!("{} {{\n $0\n}}", signature); + let snippet = format!("{} {{\n $0\n}}", function_decl); builder.snippet_edit(cap, TextEdit::replace(range, snippet)) } None => { - let header = format!("{} {{", signature); + let header = format!("{} {{", function_decl); builder.text_edit(TextEdit::replace(range, header)) } } diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index e29b82017..160f2f319 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs @@ -11,7 +11,9 @@ use crate::{ completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, }, - display::{const_label, function_signature::FunctionSignature, macro_label, type_label}, + display::{ + const_label, function_label, function_signature::FunctionSignature, macro_label, type_label, + }, CompletionScore, RootDatabase, }; @@ -206,7 +208,7 @@ impl Completions { }) .set_documentation(func.docs(ctx.db)) .set_deprecated(is_deprecated(func, ctx.db)) - .detail(function_signature.to_string()); + .detail(function_label(&ast_node)); let params = function_signature .parameter_names diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs index 1ec946369..9d413cf0a 100644 --- a/crates/ra_ide/src/display.rs +++ b/crates/ra_ide/src/display.rs @@ -13,10 +13,46 @@ use ra_syntax::{ pub(crate) use navigation_target::{ToNav, TryToNav}; pub(crate) use short_label::ShortLabel; +use ast::VisibilityOwner; pub use navigation_target::NavigationTarget; +use stdx::format_to; pub(crate) fn function_label(node: &ast::FnDef) -> String { - function_signature::FunctionSignature::from(node).to_string() + let mut buf = String::new(); + if let Some(vis) = node.visibility() { + format_to!(buf, "{} ", vis); + } + if node.async_token().is_some() { + format_to!(buf, "async "); + } + if node.const_token().is_some() { + format_to!(buf, "const "); + } + if node.unsafe_token().is_some() { + format_to!(buf, "unsafe "); + } + if let Some(abi) = node.abi() { + // Keyword `extern` is included in the string. + format_to!(buf, "{} ", abi); + } + if let Some(name) = node.name() { + format_to!(buf, "fn {}", name) + } + if let Some(type_params) = node.type_param_list() { + format_to!(buf, "{}", type_params); + } + if let Some(param_list) = node.param_list() { + format_to!(buf, "{}", param_list); + } + if let Some(ret_type) = node.ret_type() { + if ret_type.type_ref().is_some() { + format_to!(buf, " {}", ret_type); + } + } + if let Some(where_clause) = node.where_clause() { + format_to!(buf, "\n{}", where_clause); + } + buf } pub(crate) fn const_label(node: &ast::ConstDef) -> String { diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index 9b7220d1f..77551117b 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs @@ -2,15 +2,12 @@ // FIXME: this modules relies on strings and AST way too much, and it should be // rewritten (matklad 2020-05-07) -use std::{ - convert::From, - fmt::{self, Display}, -}; +use std::convert::From; use hir::{Docs, Documentation, HasSource, HirDisplay}; use ra_ide_db::RootDatabase; use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; -use stdx::{split_delim, SepBy}; +use stdx::split_delim; use crate::display::{generic_parameters, where_predicates}; @@ -247,52 +244,3 @@ impl From<&'_ ast::FnDef> for FunctionSignature { } } } - -impl Display for FunctionSignature { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(t) = &self.visibility { - write!(f, "{} ", t)?; - } - - if self.qualifier.is_async { - write!(f, "async ")?; - } - - if self.qualifier.is_const { - write!(f, "const ")?; - } - - if self.qualifier.is_unsafe { - write!(f, "unsafe ")?; - } - - if let Some(extern_abi) = &self.qualifier.extern_abi { - // Keyword `extern` is included in the string. - write!(f, "{} ", extern_abi)?; - } - - if let Some(name) = &self.name { - match self.kind { - CallableKind::Function => write!(f, "fn {}", name)?, - CallableKind::StructConstructor => write!(f, "struct {}", name)?, - CallableKind::VariantConstructor => write!(f, "{}", name)?, - } - } - - if !self.generic_parameters.is_empty() { - write!(f, "{}", self.generic_parameters.iter().sep_by(", ").surround_with("<", ">"))?; - } - - write!(f, "{}", self.parameters.iter().sep_by(", ").surround_with("(", ")"))?; - - if let Some(t) = &self.ret_type { - write!(f, " -> {}", t)?; - } - - if !self.where_predicates.is_empty() { - write!(f, "\nwhere {}", self.where_predicates.iter().sep_by(",\n "))?; - } - - Ok(()) - } -} -- cgit v1.2.3 From edc0190f7a2a701ef7c8534b053070212798cd8b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 16 Jul 2020 21:33:11 +0200 Subject: Rename --- crates/ra_ide/src/completion/complete_trait_impl.rs | 4 ++-- crates/ra_ide/src/completion/presentation.rs | 5 +++-- crates/ra_ide/src/display.rs | 10 +++++----- crates/ra_ide/src/display/short_label.rs | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index 05e605670..cf716540f 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs @@ -43,7 +43,7 @@ use crate::{ completion::{ CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, }, - display::function_label, + display::function_declaration, }; pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { @@ -144,7 +144,7 @@ fn add_function_impl( }; let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end()); - let function_decl = function_label(&func.source(ctx.db).value); + let function_decl = function_declaration(&func.source(ctx.db).value); match ctx.config.snippet_cap { Some(cap) => { let snippet = format!("{} {{\n $0\n}}", function_decl); diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 160f2f319..6aab93e17 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs @@ -12,7 +12,8 @@ use crate::{ CompletionKind, Completions, }, display::{ - const_label, function_label, function_signature::FunctionSignature, macro_label, type_label, + const_label, function_declaration, function_signature::FunctionSignature, macro_label, + type_label, }, CompletionScore, RootDatabase, }; @@ -208,7 +209,7 @@ impl Completions { }) .set_documentation(func.docs(ctx.db)) .set_deprecated(is_deprecated(func, ctx.db)) - .detail(function_label(&ast_node)); + .detail(function_declaration(&ast_node)); let params = function_signature .parameter_names diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs index 9d413cf0a..34ce32e81 100644 --- a/crates/ra_ide/src/display.rs +++ b/crates/ra_ide/src/display.rs @@ -10,14 +10,14 @@ use ra_syntax::{ SyntaxKind::{ATTR, COMMENT}, }; -pub(crate) use navigation_target::{ToNav, TryToNav}; -pub(crate) use short_label::ShortLabel; - use ast::VisibilityOwner; -pub use navigation_target::NavigationTarget; use stdx::format_to; -pub(crate) fn function_label(node: &ast::FnDef) -> String { +pub use navigation_target::NavigationTarget; +pub(crate) use navigation_target::{ToNav, TryToNav}; +pub(crate) use short_label::ShortLabel; + +pub(crate) fn function_declaration(node: &ast::FnDef) -> String { let mut buf = String::new(); if let Some(vis) = node.visibility() { format_to!(buf, "{} ", vis); diff --git a/crates/ra_ide/src/display/short_label.rs b/crates/ra_ide/src/display/short_label.rs index d37260e96..5588130a1 100644 --- a/crates/ra_ide/src/display/short_label.rs +++ b/crates/ra_ide/src/display/short_label.rs @@ -9,7 +9,7 @@ pub(crate) trait ShortLabel { impl ShortLabel for ast::FnDef { fn short_label(&self) -> Option { - Some(crate::display::function_label(self)) + Some(crate::display::function_declaration(self)) } } -- cgit v1.2.3 From a5ae8b8b92748e1b876002799d160136a7836212 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 16 Jul 2020 21:51:44 +0200 Subject: Inlay hints use callables --- crates/ra_hir/src/code_model.rs | 3 + crates/ra_ide/src/display/function_signature.rs | 96 +------------------------ crates/ra_ide/src/inlay_hints.rs | 76 ++++++++------------ 3 files changed, 35 insertions(+), 140 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index eb6a14eda..6cbcc3850 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -1552,6 +1552,9 @@ impl Callable { let param_list = src.value.param_list()?; param_list.self_param() } + pub fn n_params(&self) -> usize { + self.sig.params().len() + } pub fn params( &self, db: &dyn HirDatabase, diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index 77551117b..f6e11357f 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs @@ -4,8 +4,7 @@ // rewritten (matklad 2020-05-07) use std::convert::From; -use hir::{Docs, Documentation, HasSource, HirDisplay}; -use ra_ide_db::RootDatabase; +use hir::Documentation; use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; use stdx::split_delim; @@ -14,8 +13,6 @@ use crate::display::{generic_parameters, where_predicates}; #[derive(Debug)] pub(crate) enum CallableKind { Function, - StructConstructor, - VariantConstructor, } /// Contains information about a function signature @@ -56,97 +53,6 @@ pub(crate) struct FunctionQualifier { pub(crate) extern_abi: Option, } -impl FunctionSignature { - pub(crate) fn from_hir(db: &RootDatabase, function: hir::Function) -> Self { - let ast_node = function.source(db).value; - let mut res = FunctionSignature::from(&ast_node); - res.doc = function.docs(db); - res - } - - pub(crate) fn from_struct(db: &RootDatabase, st: hir::Struct) -> Option { - let node: ast::StructDef = st.source(db).value; - if let ast::StructKind::Record(_) = node.kind() { - return None; - }; - - let mut params = vec![]; - let mut parameter_types = vec![]; - for field in st.fields(db).into_iter() { - let ty = field.signature_ty(db); - let raw_param = format!("{}", ty.display(db)); - - if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) { - parameter_types.push(param_type.to_string()); - } else { - // useful when you have tuple struct - parameter_types.push(raw_param.clone()); - } - params.push(raw_param); - } - - Some(FunctionSignature { - kind: CallableKind::StructConstructor, - visibility: node.visibility().map(|n| n.syntax().text().to_string()), - // Do we need `const`? - qualifier: Default::default(), - name: node.name().map(|n| n.text().to_string()), - ret_type: node.name().map(|n| n.text().to_string()), - parameters: params, - parameter_names: vec![], - parameter_types, - generic_parameters: generic_parameters(&node), - where_predicates: where_predicates(&node), - doc: st.docs(db), - has_self_param: false, - }) - } - - pub(crate) fn from_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option { - let node: ast::EnumVariant = variant.source(db).value; - match node.kind() { - ast::StructKind::Record(_) | ast::StructKind::Unit => return None, - _ => (), - }; - - let parent_name = variant.parent_enum(db).name(db).to_string(); - - let name = format!("{}::{}", parent_name, variant.name(db)); - - let mut params = vec![]; - let mut parameter_types = vec![]; - for field in variant.fields(db).into_iter() { - let ty = field.signature_ty(db); - let raw_param = format!("{}", ty.display(db)); - if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) { - parameter_types.push(param_type.to_string()); - } else { - // The unwrap_or_else is useful when you have tuple - parameter_types.push(raw_param); - } - let name = field.name(db); - - params.push(format!("{}: {}", name, ty.display(db))); - } - - Some(FunctionSignature { - kind: CallableKind::VariantConstructor, - visibility: None, - // Do we need `const`? - qualifier: Default::default(), - name: Some(name), - ret_type: None, - parameters: params, - parameter_names: vec![], - parameter_types, - generic_parameters: vec![], - where_predicates: vec![], - doc: variant.docs(db), - has_self_param: false, - }) - } -} - impl From<&'_ ast::FnDef> for FunctionSignature { fn from(node: &ast::FnDef) -> FunctionSignature { fn param_list(node: &ast::FnDef) -> (bool, Vec, Vec) { diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index ae5695f61..cec3b04e8 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -1,4 +1,4 @@ -use hir::{Adt, HirDisplay, Semantics, Type}; +use hir::{Adt, Callable, HirDisplay, Semantics, Type}; use ra_ide_db::RootDatabase; use ra_prof::profile; use ra_syntax::{ @@ -7,7 +7,9 @@ use ra_syntax::{ }; use stdx::to_lower_snake_case; -use crate::{display::function_signature::FunctionSignature, FileId}; +use crate::FileId; +use ast::NameOwner; +use either::Either; #[derive(Clone, Debug, PartialEq, Eq)] pub struct InlayHintsConfig { @@ -150,23 +152,26 @@ fn get_param_name_hints( _ => return None, }; - let fn_signature = get_fn_signature(sema, &expr)?; - let n_params_to_skip = - if fn_signature.has_self_param && matches!(&expr, ast::Expr::MethodCallExpr(_)) { - 1 - } else { - 0 - }; - let hints = fn_signature - .parameter_names - .iter() - .skip(n_params_to_skip) + let callable = get_callable(sema, &expr)?; + let hints = callable + .params(sema.db) + .into_iter() .zip(args) - .filter(|(param, arg)| should_show_param_name_hint(sema, &fn_signature, param, &arg)) + .filter_map(|((param, _ty), arg)| match param? { + Either::Left(self_param) => Some((self_param.to_string(), arg)), + Either::Right(pat) => { + let param_name = match pat { + ast::Pat::BindPat(it) => it.name()?.to_string(), + it => it.to_string(), + }; + Some((param_name, arg)) + } + }) + .filter(|(param_name, arg)| should_show_param_name_hint(sema, &callable, ¶m_name, &arg)) .map(|(param_name, arg)| InlayHint { range: arg.syntax().text_range(), kind: InlayKind::ParameterHint, - label: param_name.into(), + label: param_name.to_string().into(), }); acc.extend(hints); @@ -250,28 +255,26 @@ fn should_not_display_type_hint(db: &RootDatabase, bind_pat: &ast::BindPat, pat_ fn should_show_param_name_hint( sema: &Semantics, - fn_signature: &FunctionSignature, + callable: &Callable, param_name: &str, argument: &ast::Expr, ) -> bool { let param_name = param_name.trim_start_matches('_'); + let fn_name = match callable.kind() { + hir::CallableKind::Function(it) => Some(it.name(sema.db).to_string()), + hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => None, + }; if param_name.is_empty() - || Some(param_name) == fn_signature.name.as_ref().map(|s| s.trim_start_matches('_')) + || Some(param_name) == fn_name.as_ref().map(|s| s.trim_start_matches('_')) || is_argument_similar_to_param_name(sema, argument, param_name) || param_name.starts_with("ra_fixture") { return false; } - let parameters_len = if fn_signature.has_self_param { - fn_signature.parameters.len() - 1 - } else { - fn_signature.parameters.len() - }; - // avoid displaying hints for common functions like map, filter, etc. // or other obvious words used in std - !(parameters_len == 1 && is_obvious_param(param_name)) + !(callable.n_params() == 1 && is_obvious_param(param_name)) } fn is_argument_similar_to_param_name( @@ -318,27 +321,10 @@ fn is_obvious_param(param_name: &str) -> bool { param_name.len() == 1 || is_obvious_param_name } -fn get_fn_signature(sema: &Semantics, expr: &ast::Expr) -> Option { +fn get_callable(sema: &Semantics, expr: &ast::Expr) -> Option { match expr { - ast::Expr::CallExpr(expr) => { - // FIXME: Type::as_callable is broken for closures - let callable = sema.type_of_expr(&expr.expr()?)?.as_callable(sema.db)?; - match callable.kind() { - hir::CallableKind::Function(it) => { - Some(FunctionSignature::from_hir(sema.db, it.into())) - } - hir::CallableKind::TupleStruct(it) => { - FunctionSignature::from_struct(sema.db, it.into()) - } - hir::CallableKind::TupleEnumVariant(it) => { - FunctionSignature::from_enum_variant(sema.db, it.into()) - } - } - } - ast::Expr::MethodCallExpr(expr) => { - let fn_def = sema.resolve_method_call(&expr)?; - Some(FunctionSignature::from_hir(sema.db, fn_def)) - } + ast::Expr::CallExpr(expr) => sema.type_of_expr(&expr.expr()?)?.as_callable(sema.db), + ast::Expr::MethodCallExpr(expr) => sema.resolve_method_call_as_callable(expr), _ => None, } } @@ -360,7 +346,7 @@ mod tests { let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); let actual = inlay_hints.into_iter().map(|it| (it.range, it.label.to_string())).collect::>(); - assert_eq!(expected, actual); + assert_eq!(expected, actual, "\nExpected:\n{:#?}\n\nActual:\n{:#?}", expected, actual); } fn check_expect(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) { -- cgit v1.2.3 From 3823c2dc1995ec261e36435662b8802c714e23d4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 16 Jul 2020 22:05:43 +0200 Subject: Remove FunctionSignature --- crates/ra_hir/src/code_model.rs | 2 +- crates/ra_ide/src/completion/presentation.rs | 17 ++- crates/ra_ide/src/display.rs | 18 --- crates/ra_ide/src/display/function_signature.rs | 152 ------------------------ 4 files changed, 8 insertions(+), 181 deletions(-) delete mode 100644 crates/ra_ide/src/display/function_signature.rs (limited to 'crates') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 6cbcc3850..0f6953158 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -1553,7 +1553,7 @@ impl Callable { param_list.self_param() } pub fn n_params(&self) -> usize { - self.sig.params().len() + self.sig.params().len() - if self.is_bound_method { 1 } else { 0 } } pub fn params( &self, diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 6aab93e17..c7b74e635 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs @@ -11,10 +11,7 @@ use crate::{ completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, }, - display::{ - const_label, function_declaration, function_signature::FunctionSignature, macro_label, - type_label, - }, + display::{const_label, function_declaration, macro_label, type_label}, CompletionScore, RootDatabase, }; @@ -198,7 +195,6 @@ impl Completions { let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); let ast_node = func.source(ctx.db).value; - let function_signature = FunctionSignature::from(&ast_node); let mut builder = CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) @@ -211,11 +207,12 @@ impl Completions { .set_deprecated(is_deprecated(func, ctx.db)) .detail(function_declaration(&ast_node)); - let params = function_signature - .parameter_names - .iter() - .skip(if function_signature.has_self_param { 1 } else { 0 }) - .map(|name| name.trim_start_matches('_').into()) + let params = ast_node + .param_list() + .into_iter() + .flat_map(|it| it.params()) + .flat_map(|it| it.pat()) + .map(|pat| pat.to_string().trim_start_matches('_').into()) .collect(); builder = builder.add_call_parens(ctx, name, Params::Named(params)); diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs index 34ce32e81..6d4151dd8 100644 --- a/crates/ra_ide/src/display.rs +++ b/crates/ra_ide/src/display.rs @@ -1,7 +1,6 @@ //! This module contains utilities for turning SyntaxNodes and HIR types //! into types that may be used to render in a UI. -pub(crate) mod function_signature; mod navigation_target; mod short_label; @@ -77,23 +76,6 @@ pub(crate) fn type_label(node: &ast::TypeAliasDef) -> String { label.trim().to_owned() } -pub(crate) fn generic_parameters(node: &N) -> Vec { - let mut res = vec![]; - if let Some(type_params) = node.type_param_list() { - res.extend(type_params.lifetime_params().map(|p| p.syntax().text().to_string())); - res.extend(type_params.type_params().map(|p| p.syntax().text().to_string())); - } - res -} - -pub(crate) fn where_predicates(node: &N) -> Vec { - let mut res = vec![]; - if let Some(clause) = node.where_clause() { - res.extend(clause.predicates().map(|p| p.syntax().text().to_string())); - } - res -} - pub(crate) fn macro_label(node: &ast::MacroCall) -> String { let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default(); let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" }; diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs deleted file mode 100644 index f6e11357f..000000000 --- a/crates/ra_ide/src/display/function_signature.rs +++ /dev/null @@ -1,152 +0,0 @@ -//! FIXME: write short doc here - -// FIXME: this modules relies on strings and AST way too much, and it should be -// rewritten (matklad 2020-05-07) -use std::convert::From; - -use hir::Documentation; -use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; -use stdx::split_delim; - -use crate::display::{generic_parameters, where_predicates}; - -#[derive(Debug)] -pub(crate) enum CallableKind { - Function, -} - -/// Contains information about a function signature -#[derive(Debug)] -pub(crate) struct FunctionSignature { - pub(crate) kind: CallableKind, - /// Optional visibility - pub(crate) visibility: Option, - /// Qualifiers like `async`, `unsafe`, ... - pub(crate) qualifier: FunctionQualifier, - /// Name of the function - pub(crate) name: Option, - /// Documentation for the function - pub(crate) doc: Option, - /// Generic parameters - pub(crate) generic_parameters: Vec, - /// Parameters of the function - pub(crate) parameters: Vec, - /// Parameter names of the function - pub(crate) parameter_names: Vec, - /// Parameter types of the function - pub(crate) parameter_types: Vec, - /// Optional return type - pub(crate) ret_type: Option, - /// Where predicates - pub(crate) where_predicates: Vec, - /// Self param presence - pub(crate) has_self_param: bool, -} - -#[derive(Debug, Default)] -pub(crate) struct FunctionQualifier { - // `async` and `const` are mutually exclusive. Do we need to enforcing it here? - pub(crate) is_async: bool, - pub(crate) is_const: bool, - pub(crate) is_unsafe: bool, - /// The string `extern ".."` - pub(crate) extern_abi: Option, -} - -impl From<&'_ ast::FnDef> for FunctionSignature { - fn from(node: &ast::FnDef) -> FunctionSignature { - fn param_list(node: &ast::FnDef) -> (bool, Vec, Vec) { - let mut res = vec![]; - let mut res_types = vec![]; - let mut has_self_param = false; - if let Some(param_list) = node.param_list() { - if let Some(self_param) = param_list.self_param() { - has_self_param = true; - let raw_param = self_param.syntax().text().to_string(); - - res_types.push( - raw_param - .split(':') - .nth(1) - .and_then(|it| it.get(1..)) - .unwrap_or_else(|| "Self") - .to_string(), - ); - res.push(raw_param); - } - - // macro-generated functions are missing whitespace - fn fmt_param(param: ast::Param) -> String { - let text = param.syntax().text().to_string(); - match split_delim(&text, ':') { - Some((left, right)) => format!("{}: {}", left.trim(), right.trim()), - _ => text, - } - } - - res.extend(param_list.params().map(fmt_param)); - res_types.extend(param_list.params().map(|param| { - let param_text = param.syntax().text().to_string(); - match param_text.split(':').nth(1).and_then(|it| it.get(1..)) { - Some(it) => it.to_string(), - None => param_text, - } - })); - } - (has_self_param, res, res_types) - } - - fn param_name_list(node: &ast::FnDef) -> Vec { - let mut res = vec![]; - if let Some(param_list) = node.param_list() { - if let Some(self_param) = param_list.self_param() { - res.push(self_param.syntax().text().to_string()) - } - - res.extend( - param_list - .params() - .map(|param| { - Some( - param - .pat()? - .syntax() - .descendants() - .find_map(ast::Name::cast)? - .text() - .to_string(), - ) - }) - .map(|param| param.unwrap_or_default()), - ); - } - res - } - - let (has_self_param, parameters, parameter_types) = param_list(node); - - FunctionSignature { - kind: CallableKind::Function, - visibility: node.visibility().map(|n| n.syntax().text().to_string()), - qualifier: FunctionQualifier { - is_async: node.async_token().is_some(), - is_const: node.const_token().is_some(), - is_unsafe: node.unsafe_token().is_some(), - extern_abi: node.abi().map(|n| n.to_string()), - }, - name: node.name().map(|n| n.text().to_string()), - ret_type: node - .ret_type() - .and_then(|r| r.type_ref()) - .map(|n| n.syntax().text().to_string()), - parameters, - parameter_names: param_name_list(node), - parameter_types, - generic_parameters: generic_parameters(node), - where_predicates: where_predicates(node), - // docs are processed separately - doc: None, - has_self_param, - } - } -} -- cgit v1.2.3