aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Kolb <[email protected]>2019-10-27 23:12:21 +0000
committerJeremy Kolb <[email protected]>2019-10-28 12:32:22 +0000
commit5a59bc9fcbbacb3d214e5bb9490f66ccb0abf5cb (patch)
treeed2cae97531aaff1ddbd509858358aca33e46635
parent02828520a75f686d044cb9767572ea49e93c4828 (diff)
WIP: Expand signature help
This is hacky but works for tuple structs. Proof of concept.
-rw-r--r--crates/ra_ide_api/src/call_info.rs39
-rw-r--r--crates/ra_ide_api/src/display/function_signature.rs29
2 files changed, 60 insertions, 8 deletions
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index c95133343..dfd6e69c5 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -20,24 +20,27 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
20 let name_ref = calling_node.name_ref()?; 20 let name_ref = calling_node.name_ref()?;
21 21
22 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None); 22 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None);
23 let function = match &calling_node { 23 let (mut call_info, has_self) = match &calling_node {
24 FnCallNode::CallExpr(expr) => { 24 FnCallNode::CallExpr(expr) => {
25 //FIXME: apply subst 25 //FIXME: apply subst
26 let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; 26 let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
27 match callable_def { 27 match callable_def {
28 hir::CallableDef::Function(it) => it, 28 hir::CallableDef::Function(it) => {
29 (CallInfo::with_fn(db, it), it.data(db).has_self_param())
30 }
31 hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it), false),
29 //FIXME: handle other callables 32 //FIXME: handle other callables
30 _ => return None, 33 _ => return None,
31 } 34 }
32 } 35 }
33 FnCallNode::MethodCallExpr(expr) => analyzer.resolve_method_call(&expr)?, 36 FnCallNode::MethodCallExpr(expr) => {
37 let function = analyzer.resolve_method_call(&expr)?;
38 (CallInfo::with_fn(db, function), function.data(db).has_self_param())
39 }
34 }; 40 };
35 41
36 let mut call_info = CallInfo::new(db, function);
37
38 // If we have a calling expression let's find which argument we are on 42 // If we have a calling expression let's find which argument we are on
39 let num_params = call_info.parameters().len(); 43 let num_params = call_info.parameters().len();
40 let has_self = function.data(db).has_self_param();
41 44
42 if num_params == 1 { 45 if num_params == 1 {
43 if !has_self { 46 if !has_self {
@@ -115,12 +118,18 @@ impl FnCallNode {
115} 118}
116 119
117impl CallInfo { 120impl CallInfo {
118 fn new(db: &RootDatabase, function: hir::Function) -> Self { 121 fn with_fn(db: &RootDatabase, function: hir::Function) -> Self {
119 let signature = FunctionSignature::from_hir(db, function); 122 let signature = FunctionSignature::from_hir(db, function);
120 123
121 CallInfo { signature, active_parameter: None } 124 CallInfo { signature, active_parameter: None }
122 } 125 }
123 126
127 fn with_struct(db: &RootDatabase, st: hir::Struct) -> Self {
128 let signature = FunctionSignature::from_struct(db, st);
129
130 CallInfo { signature, active_parameter: None }
131 }
132
124 fn parameters(&self) -> &[String] { 133 fn parameters(&self) -> &[String] {
125 &self.signature.parameters 134 &self.signature.parameters
126 } 135 }
@@ -462,4 +471,20 @@ fn main() {
462 assert_eq!(info.active_parameter, Some(1)); 471 assert_eq!(info.active_parameter, Some(1));
463 assert_eq!(info.label(), "fn bar(&self, _: u32)"); 472 assert_eq!(info.label(), "fn bar(&self, _: u32)");
464 } 473 }
474
475 fn works_for_tuple_structs() {
476 let info = call_info(
477 r#"
478/// A cool tuple struct
479struct TS(String, i32);
480fn main() {
481 let s = TS("".into(), <|>);
482}"#,
483 );
484
485 //assert_eq!(info.label(), "struct TS(String, i32)");
486 assert_eq!(info.label(), "fn TS(0: {unknown}, 1: i32) -> TS");
487 assert_eq!(info.doc().map(|it| it.into()), Some("A cool tuple struct".to_string()));
488 assert_eq!(info.active_parameter, Some(1));
489 }
465} 490}
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs
index 43f022ccd..0697a0727 100644
--- a/crates/ra_ide_api/src/display/function_signature.rs
+++ b/crates/ra_ide_api/src/display/function_signature.rs
@@ -2,7 +2,7 @@
2 2
3use std::fmt::{self, Display}; 3use std::fmt::{self, Display};
4 4
5use hir::{Docs, Documentation, HasSource}; 5use hir::{Docs, Documentation, HasSource, HirDisplay};
6use join_to_string::join; 6use join_to_string::join;
7use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; 7use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
8use std::convert::From; 8use std::convert::From;
@@ -42,6 +42,33 @@ impl FunctionSignature {
42 let ast_node = function.source(db).ast; 42 let ast_node = function.source(db).ast;
43 FunctionSignature::from(&ast_node).with_doc_opt(doc) 43 FunctionSignature::from(&ast_node).with_doc_opt(doc)
44 } 44 }
45
46 pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Self {
47 let doc = st.docs(db);
48
49 let node: ast::StructDef = st.source(db).ast;
50
51 let params = st
52 .fields(db)
53 .into_iter()
54 .map(|field: hir::StructField| {
55 let name = field.name(db);
56 let ty = field.ty(db);
57 format!("{}: {}", name, ty.display(db))
58 })
59 .collect();
60
61 FunctionSignature {
62 visibility: node.visibility().map(|n| n.syntax().text().to_string()),
63 name: node.name().map(|n| n.text().to_string()),
64 ret_type: node.name().map(|n| n.text().to_string()),
65 parameters: /*param_list(node)*/ params,
66 generic_parameters: generic_parameters(&node),
67 where_predicates: where_predicates(&node),
68 doc: None,
69 }
70 .with_doc_opt(doc)
71 }
45} 72}
46 73
47impl From<&'_ ast::FnDef> for FunctionSignature { 74impl From<&'_ ast::FnDef> for FunctionSignature {