From f8a2b533045757c42c206b2596448baf4737f1f0 Mon Sep 17 00:00:00 2001 From: "Jeremy A. Kolb" Date: Tue, 9 Oct 2018 10:08:17 -0400 Subject: Language Server: textDocument/signatureHelp Implements a pretty barebones function signature help mechanism in the language server. Users can use `Analysis::resolve_callback()` to get basic information about a call site. Fixes #102 --- crates/ra_analysis/src/descriptors.rs | 56 ++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'crates/ra_analysis/src/descriptors.rs') diff --git a/crates/ra_analysis/src/descriptors.rs b/crates/ra_analysis/src/descriptors.rs index 0731b5572..4dcac1aa2 100644 --- a/crates/ra_analysis/src/descriptors.rs +++ b/crates/ra_analysis/src/descriptors.rs @@ -4,7 +4,8 @@ use std::{ use relative_path::RelativePathBuf; use ra_syntax::{ SmolStr, - ast::{self, NameOwner}, + ast::{self, NameOwner, AstNode, TypeParamsOwner}, + text_utils::is_subrange }; use { FileId, @@ -218,3 +219,56 @@ fn resolve_submodule( } (points_to, problem) } + +#[derive(Debug, Clone)] +pub struct FnDescriptor { + pub name: Option, + pub label : String, + pub ret_type: Option, + pub params: Vec, +} + +impl FnDescriptor { + pub fn new(node: ast::FnDef) -> Self { + let name = node.name().map(|name| name.text().to_string()); + + // Strip the body out for the label. + let label : String = if let Some(body) = node.body() { + let body_range = body.syntax().range(); + let label : String = node.syntax().children() + .filter(|child| !is_subrange(body_range, child.range())) + .map(|node| node.text().to_string()) + .collect(); + label + } else { + node.syntax().text().to_string() + }; + + let params = FnDescriptor::param_list(node); + let ret_type = node.ret_type().map(|r| r.syntax().text().to_string()); + + FnDescriptor { + name, + ret_type, + params, + label + } + } + + fn param_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()) + } + + // Maybe use param.pat here? See if we can just extract the name? + //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); + res.extend(param_list.params() + .filter_map(|p| p.pat()) + .map(|pat| pat.syntax().text().to_string()) + ); + } + res + } +} \ No newline at end of file -- cgit v1.2.3 From c9909f42ba4adf55b1e73e7118b48f1b10c80ac6 Mon Sep 17 00:00:00 2001 From: "Jeremy A. Kolb" Date: Fri, 12 Oct 2018 07:54:57 -0400 Subject: A FnDescriptor shouldn't exist without a name --- crates/ra_analysis/src/descriptors.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'crates/ra_analysis/src/descriptors.rs') diff --git a/crates/ra_analysis/src/descriptors.rs b/crates/ra_analysis/src/descriptors.rs index 4dcac1aa2..faf945a41 100644 --- a/crates/ra_analysis/src/descriptors.rs +++ b/crates/ra_analysis/src/descriptors.rs @@ -4,7 +4,7 @@ use std::{ use relative_path::RelativePathBuf; use ra_syntax::{ SmolStr, - ast::{self, NameOwner, AstNode, TypeParamsOwner}, + ast::{self, NameOwner, AstNode}, text_utils::is_subrange }; use { @@ -222,15 +222,15 @@ fn resolve_submodule( #[derive(Debug, Clone)] pub struct FnDescriptor { - pub name: Option, + pub name: String, pub label : String, pub ret_type: Option, pub params: Vec, } impl FnDescriptor { - pub fn new(node: ast::FnDef) -> Self { - let name = node.name().map(|name| name.text().to_string()); + pub fn new(node: ast::FnDef) -> Option { + let name = node.name()?.text().to_string(); // Strip the body out for the label. let label : String = if let Some(body) = node.body() { @@ -247,12 +247,12 @@ impl FnDescriptor { let params = FnDescriptor::param_list(node); let ret_type = node.ret_type().map(|r| r.syntax().text().to_string()); - FnDescriptor { + Some(FnDescriptor { name, ret_type, params, label - } + }) } fn param_list(node: ast::FnDef) -> Vec { -- cgit v1.2.3