mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 05:15:04 +00:00
WIP: Expand signature help
This is hacky but works for tuple structs. Proof of concept.
This commit is contained in:
parent
02828520a7
commit
5a59bc9fcb
2 changed files with 60 additions and 8 deletions
|
@ -20,24 +20,27 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
|
||||||
let name_ref = calling_node.name_ref()?;
|
let name_ref = calling_node.name_ref()?;
|
||||||
|
|
||||||
let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None);
|
let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None);
|
||||||
let function = match &calling_node {
|
let (mut call_info, has_self) = match &calling_node {
|
||||||
FnCallNode::CallExpr(expr) => {
|
FnCallNode::CallExpr(expr) => {
|
||||||
//FIXME: apply subst
|
//FIXME: apply subst
|
||||||
let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
|
let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
|
||||||
match callable_def {
|
match callable_def {
|
||||||
hir::CallableDef::Function(it) => it,
|
hir::CallableDef::Function(it) => {
|
||||||
|
(CallInfo::with_fn(db, it), it.data(db).has_self_param())
|
||||||
|
}
|
||||||
|
hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it), false),
|
||||||
//FIXME: handle other callables
|
//FIXME: handle other callables
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FnCallNode::MethodCallExpr(expr) => analyzer.resolve_method_call(&expr)?,
|
FnCallNode::MethodCallExpr(expr) => {
|
||||||
|
let function = analyzer.resolve_method_call(&expr)?;
|
||||||
|
(CallInfo::with_fn(db, function), function.data(db).has_self_param())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut call_info = CallInfo::new(db, function);
|
|
||||||
|
|
||||||
// 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 = function.data(db).has_self_param();
|
|
||||||
|
|
||||||
if num_params == 1 {
|
if num_params == 1 {
|
||||||
if !has_self {
|
if !has_self {
|
||||||
|
@ -115,12 +118,18 @@ impl FnCallNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallInfo {
|
impl CallInfo {
|
||||||
fn new(db: &RootDatabase, function: hir::Function) -> Self {
|
fn with_fn(db: &RootDatabase, function: hir::Function) -> Self {
|
||||||
let signature = FunctionSignature::from_hir(db, function);
|
let signature = FunctionSignature::from_hir(db, function);
|
||||||
|
|
||||||
CallInfo { signature, active_parameter: None }
|
CallInfo { signature, active_parameter: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_struct(db: &RootDatabase, st: hir::Struct) -> Self {
|
||||||
|
let signature = FunctionSignature::from_struct(db, st);
|
||||||
|
|
||||||
|
CallInfo { signature, active_parameter: None }
|
||||||
|
}
|
||||||
|
|
||||||
fn parameters(&self) -> &[String] {
|
fn parameters(&self) -> &[String] {
|
||||||
&self.signature.parameters
|
&self.signature.parameters
|
||||||
}
|
}
|
||||||
|
@ -462,4 +471,20 @@ fn main() {
|
||||||
assert_eq!(info.active_parameter, Some(1));
|
assert_eq!(info.active_parameter, Some(1));
|
||||||
assert_eq!(info.label(), "fn bar(&self, _: u32)");
|
assert_eq!(info.label(), "fn bar(&self, _: u32)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn works_for_tuple_structs() {
|
||||||
|
let info = call_info(
|
||||||
|
r#"
|
||||||
|
/// A cool tuple struct
|
||||||
|
struct TS(String, i32);
|
||||||
|
fn main() {
|
||||||
|
let s = TS("".into(), <|>);
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
//assert_eq!(info.label(), "struct TS(String, i32)");
|
||||||
|
assert_eq!(info.label(), "fn TS(0: {unknown}, 1: i32) -> TS");
|
||||||
|
assert_eq!(info.doc().map(|it| it.into()), Some("A cool tuple struct".to_string()));
|
||||||
|
assert_eq!(info.active_parameter, Some(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
use hir::{Docs, Documentation, HasSource};
|
use hir::{Docs, Documentation, HasSource, HirDisplay};
|
||||||
use join_to_string::join;
|
use join_to_string::join;
|
||||||
use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
|
use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
|
@ -42,6 +42,33 @@ impl FunctionSignature {
|
||||||
let ast_node = function.source(db).ast;
|
let ast_node = function.source(db).ast;
|
||||||
FunctionSignature::from(&ast_node).with_doc_opt(doc)
|
FunctionSignature::from(&ast_node).with_doc_opt(doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Self {
|
||||||
|
let doc = st.docs(db);
|
||||||
|
|
||||||
|
let node: ast::StructDef = st.source(db).ast;
|
||||||
|
|
||||||
|
let params = st
|
||||||
|
.fields(db)
|
||||||
|
.into_iter()
|
||||||
|
.map(|field: hir::StructField| {
|
||||||
|
let name = field.name(db);
|
||||||
|
let ty = field.ty(db);
|
||||||
|
format!("{}: {}", name, ty.display(db))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
FunctionSignature {
|
||||||
|
visibility: node.visibility().map(|n| n.syntax().text().to_string()),
|
||||||
|
name: node.name().map(|n| n.text().to_string()),
|
||||||
|
ret_type: node.name().map(|n| n.text().to_string()),
|
||||||
|
parameters: /*param_list(node)*/ params,
|
||||||
|
generic_parameters: generic_parameters(&node),
|
||||||
|
where_predicates: where_predicates(&node),
|
||||||
|
doc: None,
|
||||||
|
}
|
||||||
|
.with_doc_opt(doc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'_ ast::FnDef> for FunctionSignature {
|
impl From<&'_ ast::FnDef> for FunctionSignature {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue