mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Refactor CallInfo function signatures to new FunctionSignature type
This is used by CallInfo to create a pretty printed function signature that can be used with completions and other places as well.
This commit is contained in:
parent
5f700179fc
commit
0e49abb7fb
8 changed files with 212 additions and 71 deletions
|
@ -22,6 +22,12 @@ impl Into<String> for Documentation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Into<String> for &'a Documentation {
|
||||||
|
fn into(self) -> String {
|
||||||
|
self.contents().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Docs {
|
pub trait Docs {
|
||||||
fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
|
fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
|
||||||
let mut call_info = CallInfo::new(db, function, fn_def)?;
|
let mut call_info = CallInfo::new(db, function, fn_def)?;
|
||||||
|
|
||||||
// If we have a calling expression let's find which argument we are on
|
// If we have a calling expression let's find which argument we are on
|
||||||
let num_params = call_info.parameters.len();
|
let num_params = call_info.parameters().len();
|
||||||
let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some();
|
let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some();
|
||||||
|
|
||||||
if num_params == 1 {
|
if num_params == 1 {
|
||||||
|
@ -108,27 +108,26 @@ impl<'a> FnCallNode<'a> {
|
||||||
|
|
||||||
impl CallInfo {
|
impl CallInfo {
|
||||||
fn new(db: &RootDatabase, function: hir::Function, node: &ast::FnDef) -> Option<Self> {
|
fn new(db: &RootDatabase, function: hir::Function, node: &ast::FnDef) -> Option<Self> {
|
||||||
let label = crate::completion::function_label(node)?;
|
let sig = crate::completion::function_signature(node)?;
|
||||||
let doc = function.docs(db);
|
let doc = function.docs(db);
|
||||||
|
let sig = sig.with_doc_opt(doc);
|
||||||
|
|
||||||
Some(CallInfo { parameters: param_list(node), label, doc, active_parameter: None })
|
Some(CallInfo { signature: sig, active_parameter: None })
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_list(node: &ast::FnDef) -> Vec<String> {
|
|
||||||
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?
|
fn parameters(&self) -> &[String] {
|
||||||
//res.extend(param_list.params().map(|p| p.syntax().text().to_string()));
|
&self.signature.parameters
|
||||||
res.extend(
|
}
|
||||||
param_list.params().filter_map(|p| p.pat()).map(|pat| pat.syntax().text().to_string()),
|
|
||||||
);
|
#[cfg(test)]
|
||||||
|
fn doc(&self) -> Option<&hir::Documentation> {
|
||||||
|
self.signature.doc.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn label(&self) -> String {
|
||||||
|
self.signature.to_string()
|
||||||
}
|
}
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -151,7 +150,7 @@ mod tests {
|
||||||
fn bar() { foo(<|>3, ); }"#,
|
fn bar() { foo(<|>3, ); }"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string()));
|
assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
|
||||||
assert_eq!(info.active_parameter, Some(0));
|
assert_eq!(info.active_parameter, Some(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +161,7 @@ fn bar() { foo(<|>3, ); }"#,
|
||||||
fn bar() { foo(3, <|>); }"#,
|
fn bar() { foo(3, <|>); }"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string()));
|
assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
|
||||||
assert_eq!(info.active_parameter, Some(1));
|
assert_eq!(info.active_parameter, Some(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +172,27 @@ fn bar() { foo(3, <|>); }"#,
|
||||||
fn bar() { foo(<|>); }"#,
|
fn bar() { foo(<|>); }"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(info.parameters, vec!("x".to_string(), "y".to_string()));
|
assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
|
||||||
|
assert_eq!(info.active_parameter, Some(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fn_signature_two_args_first_generics() {
|
||||||
|
let info = call_info(
|
||||||
|
r#"fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 where T: Copy + Display, U: Debug {x + y}
|
||||||
|
fn bar() { foo(<|>3, ); }"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(info.parameters(), ["x: T", "y: U"]);
|
||||||
|
assert_eq!(
|
||||||
|
info.label(),
|
||||||
|
r#"
|
||||||
|
fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
|
||||||
|
where T: Copy + Display,
|
||||||
|
U: Debug
|
||||||
|
"#
|
||||||
|
.trim()
|
||||||
|
);
|
||||||
assert_eq!(info.active_parameter, Some(0));
|
assert_eq!(info.active_parameter, Some(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +203,7 @@ fn bar() { foo(<|>); }"#,
|
||||||
fn bar() {let _ : F = F::new(<|>);}"#,
|
fn bar() {let _ : F = F::new(<|>);}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(info.parameters, Vec::<String>::new());
|
assert!(info.parameters().is_empty());
|
||||||
assert_eq!(info.active_parameter, None);
|
assert_eq!(info.active_parameter, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +225,7 @@ fn bar() {
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(info.parameters, vec!["&self".to_string()]);
|
assert_eq!(info.parameters(), ["&self"]);
|
||||||
assert_eq!(info.active_parameter, None);
|
assert_eq!(info.active_parameter, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,7 +247,7 @@ fn bar() {
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(info.parameters, vec!["&self".to_string(), "x".to_string()]);
|
assert_eq!(info.parameters(), ["&self", "x: i32"]);
|
||||||
assert_eq!(info.active_parameter, Some(1));
|
assert_eq!(info.active_parameter, Some(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,10 +267,10 @@ fn bar() {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(info.parameters, vec!["j".to_string()]);
|
assert_eq!(info.parameters(), ["j: u32"]);
|
||||||
assert_eq!(info.active_parameter, Some(0));
|
assert_eq!(info.active_parameter, Some(0));
|
||||||
assert_eq!(info.label, "fn foo(j: u32) -> u32".to_string());
|
assert_eq!(info.label(), "fn foo(j: u32) -> u32");
|
||||||
assert_eq!(info.doc.map(|it| it.into()), Some("test".to_string()));
|
assert_eq!(info.doc().map(|it| it.into()), Some("test".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -276,11 +295,11 @@ pub fn do() {
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(info.parameters, vec!["x".to_string()]);
|
assert_eq!(info.parameters(), ["x: i32"]);
|
||||||
assert_eq!(info.active_parameter, Some(0));
|
assert_eq!(info.active_parameter, Some(0));
|
||||||
assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string());
|
assert_eq!(info.label(), "pub fn add_one(x: i32) -> i32");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
info.doc.map(|it| it.into()),
|
info.doc().map(|it| it.into()),
|
||||||
Some(
|
Some(
|
||||||
r#"Adds one to the number given.
|
r#"Adds one to the number given.
|
||||||
|
|
||||||
|
@ -322,11 +341,11 @@ pub fn do_it() {
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(info.parameters, vec!["x".to_string()]);
|
assert_eq!(info.parameters(), ["x: i32"]);
|
||||||
assert_eq!(info.active_parameter, Some(0));
|
assert_eq!(info.active_parameter, Some(0));
|
||||||
assert_eq!(info.label, "pub fn add_one(x: i32) -> i32".to_string());
|
assert_eq!(info.label(), "pub fn add_one(x: i32) -> i32");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
info.doc.map(|it| it.into()),
|
info.doc().map(|it| it.into()),
|
||||||
Some(
|
Some(
|
||||||
r#"Adds one to the number given.
|
r#"Adds one to the number given.
|
||||||
|
|
||||||
|
@ -375,10 +394,10 @@ pub fn foo() {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(info.parameters, vec!["&mut self".to_string(), "ctx".to_string()]);
|
assert_eq!(info.parameters(), ["&mut self", "ctx: &mut Self::Context"]);
|
||||||
assert_eq!(info.active_parameter, Some(1));
|
assert_eq!(info.active_parameter, Some(1));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
info.doc.map(|it| it.into()),
|
info.doc().map(|it| it.into()),
|
||||||
Some(
|
Some(
|
||||||
r#"Method is called when writer finishes.
|
r#"Method is called when writer finishes.
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,12 @@ mod complete_scope;
|
||||||
mod complete_postfix;
|
mod complete_postfix;
|
||||||
|
|
||||||
use ra_db::SourceDatabase;
|
use ra_db::SourceDatabase;
|
||||||
use ra_syntax::{ast::{self, AstNode}, SyntaxKind::{ATTR, COMMENT}};
|
use ra_syntax::{ast::{self, AstNode, NameOwner, VisibilityOwner, TypeParamsOwner}, SyntaxKind::{ATTR, COMMENT}};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db,
|
db,
|
||||||
FilePosition,
|
FilePosition,
|
||||||
|
FunctionSignature,
|
||||||
completion::{
|
completion::{
|
||||||
completion_item::{Completions, CompletionKind},
|
completion_item::{Completions, CompletionKind},
|
||||||
completion_context::CompletionContext,
|
completion_context::CompletionContext,
|
||||||
|
@ -71,22 +72,52 @@ pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Opti
|
||||||
Some(acc)
|
Some(acc)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function_label(node: &ast::FnDef) -> Option<String> {
|
pub fn generic_parameters<N: TypeParamsOwner>(node: &N) -> Vec<String> {
|
||||||
let label: String = if let Some(body) = node.body() {
|
let mut res = vec![];
|
||||||
let body_range = body.syntax().range();
|
if let Some(type_params) = node.type_param_list() {
|
||||||
let label: String = node
|
res.extend(type_params.lifetime_params().map(|p| p.syntax().text().to_string()));
|
||||||
.syntax()
|
res.extend(type_params.type_params().map(|p| p.syntax().text().to_string()));
|
||||||
.children_with_tokens()
|
}
|
||||||
.filter(|child| !child.range().is_subrange(&body_range)) // Filter out body
|
res
|
||||||
.filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR)) // Filter out comments and attrs
|
}
|
||||||
.map(|node| node.to_string())
|
|
||||||
.collect();
|
pub fn where_predicates<N: TypeParamsOwner>(node: &N) -> Vec<String> {
|
||||||
label
|
let mut res = vec![];
|
||||||
} else {
|
if let Some(clause) = node.where_clause() {
|
||||||
node.syntax().text().to_string()
|
res.extend(clause.predicates().map(|p| p.syntax().text().to_string()));
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_signature(node: &ast::FnDef) -> Option<FunctionSignature> {
|
||||||
|
fn param_list(node: &ast::FnDef) -> Vec<String> {
|
||||||
|
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| param.syntax().text().to_string()));
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
let sig = FunctionSignature {
|
||||||
|
visibility: node.visibility().map(|n| n.syntax().text().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: param_list(node),
|
||||||
|
generic_parameters: generic_parameters(node),
|
||||||
|
where_predicates: where_predicates(node),
|
||||||
|
// docs are processed separately
|
||||||
|
doc: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(label.trim().to_owned())
|
Some(sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_label(node: &ast::FnDef) -> Option<String> {
|
||||||
|
function_signature(node).map(|n| n.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_label(node: &ast::ConstDef) -> String {
|
pub fn const_label(node: &ast::ConstDef) -> String {
|
||||||
|
|
|
@ -145,7 +145,7 @@ mod tests {
|
||||||
check_reference_completion(
|
check_reference_completion(
|
||||||
"dont_show_both_completions_for_shadowing",
|
"dont_show_both_completions_for_shadowing",
|
||||||
r"
|
r"
|
||||||
fn foo() -> {
|
fn foo() {
|
||||||
let bar = 92;
|
let bar = 92;
|
||||||
{
|
{
|
||||||
let bar = 62;
|
let bar = 62;
|
||||||
|
|
51
crates/ra_ide_api/src/display.rs
Normal file
51
crates/ra_ide_api/src/display.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
use super::*;
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
|
impl Display for FunctionSignature {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
if let Some(t) = &self.visibility {
|
||||||
|
write!(f, "{} ", t)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(name) = &self.name {
|
||||||
|
write!(f, "fn {}", name)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.generic_parameters.is_empty() {
|
||||||
|
write!(f, "<")?;
|
||||||
|
write_joined(f, &self.generic_parameters, ", ")?;
|
||||||
|
write!(f, ">")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "(")?;
|
||||||
|
write_joined(f, &self.parameters, ", ")?;
|
||||||
|
write!(f, ")")?;
|
||||||
|
|
||||||
|
if let Some(t) = &self.ret_type {
|
||||||
|
write!(f, " -> {}", t)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.where_predicates.is_empty() {
|
||||||
|
write!(f, "\nwhere ")?;
|
||||||
|
write_joined(f, &self.where_predicates, ",\n ")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_joined<T: Display>(
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
items: impl IntoIterator<Item = T>,
|
||||||
|
sep: &str,
|
||||||
|
) -> fmt::Result {
|
||||||
|
let mut first = true;
|
||||||
|
for e in items {
|
||||||
|
if !first {
|
||||||
|
write!(f, "{}", sep)?;
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
write!(f, "{}", e)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ mod join_lines;
|
||||||
mod structure;
|
mod structure;
|
||||||
mod typing;
|
mod typing;
|
||||||
mod matching_brace;
|
mod matching_brace;
|
||||||
|
mod display;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod marks;
|
mod marks;
|
||||||
|
@ -243,12 +244,36 @@ impl<T> RangeInfo<T> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CallInfo {
|
pub struct CallInfo {
|
||||||
pub label: String,
|
pub signature: FunctionSignature,
|
||||||
pub doc: Option<Documentation>,
|
|
||||||
pub parameters: Vec<String>,
|
|
||||||
pub active_parameter: Option<usize>,
|
pub active_parameter: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Contains information about a function signature
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FunctionSignature {
|
||||||
|
/// Optional visibility
|
||||||
|
pub visibility: Option<String>,
|
||||||
|
/// Name of the function
|
||||||
|
pub name: Option<String>,
|
||||||
|
/// Documentation for the function
|
||||||
|
pub doc: Option<Documentation>,
|
||||||
|
/// Generic parameters
|
||||||
|
pub generic_parameters: Vec<String>,
|
||||||
|
/// Parameters of the function
|
||||||
|
pub parameters: Vec<String>,
|
||||||
|
/// Optional return type
|
||||||
|
pub ret_type: Option<String>,
|
||||||
|
/// Where predicates
|
||||||
|
pub where_predicates: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FunctionSignature {
|
||||||
|
pub(crate) fn with_doc_opt(mut self, doc: Option<Documentation>) -> Self {
|
||||||
|
self.doc = doc;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// `AnalysisHost` stores the current state of the world.
|
/// `AnalysisHost` stores the current state of the world.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct AnalysisHost {
|
pub struct AnalysisHost {
|
||||||
|
|
|
@ -174,6 +174,28 @@ impl Conv for ra_ide_api::Documentation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Conv for ra_ide_api::FunctionSignature {
|
||||||
|
type Output = lsp_types::SignatureInformation;
|
||||||
|
fn conv(self) -> Self::Output {
|
||||||
|
use lsp_types::{ParameterInformation, ParameterLabel, SignatureInformation};
|
||||||
|
|
||||||
|
let label = self.to_string();
|
||||||
|
|
||||||
|
let documentation = self.doc.map(|it| it.conv());
|
||||||
|
|
||||||
|
let parameters: Vec<ParameterInformation> = self
|
||||||
|
.parameters
|
||||||
|
.into_iter()
|
||||||
|
.map(|param| ParameterInformation {
|
||||||
|
label: ParameterLabel::Simple(param),
|
||||||
|
documentation: None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
SignatureInformation { label, documentation, parameters: Some(parameters) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ConvWith for TextEdit {
|
impl ConvWith for TextEdit {
|
||||||
type Ctx = LineIndex;
|
type Ctx = LineIndex;
|
||||||
type Output = Vec<lsp_types::TextEdit>;
|
type Output = Vec<lsp_types::TextEdit>;
|
||||||
|
|
|
@ -3,8 +3,8 @@ use lsp_types::{
|
||||||
CodeActionResponse, CodeLens, Command, Diagnostic, DiagnosticSeverity, CodeAction,
|
CodeActionResponse, CodeLens, Command, Diagnostic, DiagnosticSeverity, CodeAction,
|
||||||
DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange,
|
DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange,
|
||||||
FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent,
|
FoldingRangeKind, FoldingRangeParams, Hover, HoverContents, Location, MarkupContent,
|
||||||
MarkupKind, ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range,
|
MarkupKind, Position, PrepareRenameResponse, Range,
|
||||||
RenameParams, SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit,
|
RenameParams,SymbolInformation, TextDocumentIdentifier, TextEdit,
|
||||||
WorkspaceEdit,
|
WorkspaceEdit,
|
||||||
};
|
};
|
||||||
use ra_ide_api::{
|
use ra_ide_api::{
|
||||||
|
@ -403,26 +403,13 @@ pub fn handle_signature_help(
|
||||||
) -> Result<Option<req::SignatureHelp>> {
|
) -> Result<Option<req::SignatureHelp>> {
|
||||||
let position = params.try_conv_with(&world)?;
|
let position = params.try_conv_with(&world)?;
|
||||||
if let Some(call_info) = world.analysis().call_info(position)? {
|
if let Some(call_info) = world.analysis().call_info(position)? {
|
||||||
let parameters: Vec<ParameterInformation> = call_info
|
let active_parameter = call_info.active_parameter.map(|it| it as i64);
|
||||||
.parameters
|
let sig_info = call_info.signature.conv();
|
||||||
.into_iter()
|
|
||||||
.map(|param| ParameterInformation {
|
|
||||||
label: ParameterLabel::Simple(param.clone()),
|
|
||||||
documentation: None,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let documentation = call_info.doc.map(|it| it.conv());
|
|
||||||
|
|
||||||
let sig_info = SignatureInformation {
|
|
||||||
label: call_info.label,
|
|
||||||
documentation,
|
|
||||||
parameters: Some(parameters),
|
|
||||||
};
|
|
||||||
Ok(Some(req::SignatureHelp {
|
Ok(Some(req::SignatureHelp {
|
||||||
signatures: vec![sig_info],
|
signatures: vec![sig_info],
|
||||||
active_signature: Some(0),
|
active_signature: Some(0),
|
||||||
active_parameter: call_info.active_parameter.map(|it| it as i64),
|
active_parameter,
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue