aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock18
-rw-r--r--crates/ra_assists/src/assists/add_import.rs12
-rw-r--r--crates/ra_ide_api/src/call_info.rs142
-rw-r--r--crates/ra_ide_api/src/display/function_signature.rs112
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs19
5 files changed, 277 insertions, 26 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 18d2fb9d5..c7ec98226 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -455,7 +455,7 @@ name = "heck"
455version = "0.3.1" 455version = "0.3.1"
456source = "registry+https://github.com/rust-lang/crates.io-index" 456source = "registry+https://github.com/rust-lang/crates.io-index"
457dependencies = [ 457dependencies = [
458 "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 458 "unicode-segmentation 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
459] 459]
460 460
461[[package]] 461[[package]]
@@ -802,7 +802,7 @@ dependencies = [
802 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 802 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
803 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 803 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
804 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 804 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
805 "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 805 "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
806 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 806 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
807] 807]
808 808
@@ -1091,7 +1091,7 @@ dependencies = [
1091 "ra_syntax 0.1.0", 1091 "ra_syntax 0.1.0",
1092 "ra_tt 0.1.0", 1092 "ra_tt 0.1.0",
1093 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1093 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1094 "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 1094 "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
1095 "test_utils 0.1.0", 1095 "test_utils 0.1.0",
1096] 1096]
1097 1097
@@ -1456,7 +1456,7 @@ dependencies = [
1456 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1456 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1457 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1457 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1458 "salsa-macros 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", 1458 "salsa-macros 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
1459 "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 1459 "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
1460] 1460]
1461 1461
1462[[package]] 1462[[package]]
@@ -1553,7 +1553,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1553 1553
1554[[package]] 1554[[package]]
1555name = "smallvec" 1555name = "smallvec"
1556version = "0.6.10" 1556version = "0.6.11"
1557source = "registry+https://github.com/rust-lang/crates.io-index" 1557source = "registry+https://github.com/rust-lang/crates.io-index"
1558 1558
1559[[package]] 1559[[package]]
@@ -1673,12 +1673,12 @@ name = "unicode-normalization"
1673version = "0.1.8" 1673version = "0.1.8"
1674source = "registry+https://github.com/rust-lang/crates.io-index" 1674source = "registry+https://github.com/rust-lang/crates.io-index"
1675dependencies = [ 1675dependencies = [
1676 "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 1676 "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
1677] 1677]
1678 1678
1679[[package]] 1679[[package]]
1680name = "unicode-segmentation" 1680name = "unicode-segmentation"
1681version = "1.3.0" 1681version = "1.4.0"
1682source = "registry+https://github.com/rust-lang/crates.io-index" 1682source = "registry+https://github.com/rust-lang/crates.io-index"
1683 1683
1684[[package]] 1684[[package]]
@@ -1955,7 +1955,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1955"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" 1955"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573"
1956"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" 1956"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35"
1957"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 1957"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
1958"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" 1958"checksum smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cefaa50e76a6f10b86f36e640eb1739eafbd4084865067778463913e43a77ff3"
1959"checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" 1959"checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b"
1960"checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a" 1960"checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a"
1961"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" 1961"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
@@ -1969,7 +1969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1969"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" 1969"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150"
1970"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 1970"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
1971"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" 1971"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
1972"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" 1972"checksum unicode-segmentation 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc5415c074426c7c65db13bd647c23d78c0fb2e10dca0b8fb0f40058a59bccdf"
1973"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" 1973"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
1974"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 1974"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
1975"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" 1975"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61"
diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs
index c8b9809f4..363ade016 100644
--- a/crates/ra_assists/src/assists/add_import.rs
+++ b/crates/ra_assists/src/assists/add_import.rs
@@ -545,7 +545,7 @@ fn make_assist_add_nested_import(
545 if add_colon_colon { 545 if add_colon_colon {
546 buf.push_str("::"); 546 buf.push_str("::");
547 } 547 }
548 buf.push_str("{ "); 548 buf.push_str("{");
549 if add_self { 549 if add_self {
550 buf.push_str("self, "); 550 buf.push_str("self, ");
551 } 551 }
@@ -734,7 +734,7 @@ impl std::io<|> for Foo {
734} 734}
735 ", 735 ",
736 " 736 "
737use std::{ io, fmt}; 737use std::{io, fmt};
738 738
739impl io<|> for Foo { 739impl io<|> for Foo {
740} 740}
@@ -753,7 +753,7 @@ impl std::fmt::Debug<|> for Foo {
753} 753}
754 ", 754 ",
755 " 755 "
756use std::fmt::{ self, Debug, }; 756use std::fmt::{self, Debug, };
757 757
758impl Debug<|> for Foo { 758impl Debug<|> for Foo {
759} 759}
@@ -772,7 +772,7 @@ impl std::fmt<|> for Foo {
772} 772}
773 ", 773 ",
774 " 774 "
775use std::fmt::{ self, Debug}; 775use std::fmt::{self, Debug};
776 776
777impl fmt<|> for Foo { 777impl fmt<|> for Foo {
778} 778}
@@ -848,7 +848,7 @@ impl std::fmt::nested::Display<|> for Foo {
848} 848}
849", 849",
850 " 850 "
851use std::fmt::{ nested::Display, Debug}; 851use std::fmt::{nested::Display, Debug};
852 852
853impl Display<|> for Foo { 853impl Display<|> for Foo {
854} 854}
@@ -867,7 +867,7 @@ impl std::fmt::Display<|> for Foo {
867} 867}
868", 868",
869 " 869 "
870use std::fmt::{ Display, nested::Debug}; 870use std::fmt::{Display, nested::Debug};
871 871
872impl Display<|> for Foo { 872impl Display<|> for Foo {
873} 873}
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index c95133343..175af3fd9 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -20,24 +20,30 @@ 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 //FIXME: handle other callables 29 (CallInfo::with_fn(db, it), it.data(db).has_self_param())
30 _ => return None, 30 }
31 hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false),
32 hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false),
31 } 33 }
32 } 34 }
33 FnCallNode::MethodCallExpr(expr) => analyzer.resolve_method_call(&expr)?, 35 FnCallNode::MethodCallExpr(expr) => {
36 let function = analyzer.resolve_method_call(&expr)?;
37 (CallInfo::with_fn(db, function), function.data(db).has_self_param())
38 }
39 FnCallNode::MacroCallExpr(expr) => {
40 let macro_def = analyzer.resolve_macro_call(db, &expr)?;
41 (CallInfo::with_macro(db, macro_def)?, false)
42 }
34 }; 43 };
35 44
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 45 // If we have a calling expression let's find which argument we are on
39 let num_params = call_info.parameters().len(); 46 let num_params = call_info.parameters().len();
40 let has_self = function.data(db).has_self_param();
41 47
42 if num_params == 1 { 48 if num_params == 1 {
43 if !has_self { 49 if !has_self {
@@ -75,9 +81,11 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
75 Some(call_info) 81 Some(call_info)
76} 82}
77 83
84#[derive(Debug)]
78enum FnCallNode { 85enum FnCallNode {
79 CallExpr(ast::CallExpr), 86 CallExpr(ast::CallExpr),
80 MethodCallExpr(ast::MethodCallExpr), 87 MethodCallExpr(ast::MethodCallExpr),
88 MacroCallExpr(ast::MacroCall),
81} 89}
82 90
83impl FnCallNode { 91impl FnCallNode {
@@ -87,6 +95,8 @@ impl FnCallNode {
87 Some(FnCallNode::CallExpr(expr)) 95 Some(FnCallNode::CallExpr(expr))
88 } else if let Some(expr) = ast::MethodCallExpr::cast(node.clone()) { 96 } else if let Some(expr) = ast::MethodCallExpr::cast(node.clone()) {
89 Some(FnCallNode::MethodCallExpr(expr)) 97 Some(FnCallNode::MethodCallExpr(expr))
98 } else if let Some(expr) = ast::MacroCall::cast(node.clone()) {
99 Some(FnCallNode::MacroCallExpr(expr))
90 } else { 100 } else {
91 None 101 None
92 } 102 }
@@ -103,6 +113,8 @@ impl FnCallNode {
103 FnCallNode::MethodCallExpr(call_expr) => { 113 FnCallNode::MethodCallExpr(call_expr) => {
104 call_expr.syntax().children().filter_map(ast::NameRef::cast).nth(0) 114 call_expr.syntax().children().filter_map(ast::NameRef::cast).nth(0)
105 } 115 }
116
117 FnCallNode::MacroCallExpr(call_expr) => call_expr.path()?.segment()?.name_ref(),
106 } 118 }
107 } 119 }
108 120
@@ -110,17 +122,36 @@ impl FnCallNode {
110 match self { 122 match self {
111 FnCallNode::CallExpr(expr) => expr.arg_list(), 123 FnCallNode::CallExpr(expr) => expr.arg_list(),
112 FnCallNode::MethodCallExpr(expr) => expr.arg_list(), 124 FnCallNode::MethodCallExpr(expr) => expr.arg_list(),
125 FnCallNode::MacroCallExpr(_) => None,
113 } 126 }
114 } 127 }
115} 128}
116 129
117impl CallInfo { 130impl CallInfo {
118 fn new(db: &RootDatabase, function: hir::Function) -> Self { 131 fn with_fn(db: &RootDatabase, function: hir::Function) -> Self {
119 let signature = FunctionSignature::from_hir(db, function); 132 let signature = FunctionSignature::from_hir(db, function);
120 133
121 CallInfo { signature, active_parameter: None } 134 CallInfo { signature, active_parameter: None }
122 } 135 }
123 136
137 fn with_struct(db: &RootDatabase, st: hir::Struct) -> Option<Self> {
138 let signature = FunctionSignature::from_struct(db, st)?;
139
140 Some(CallInfo { signature, active_parameter: None })
141 }
142
143 fn with_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option<Self> {
144 let signature = FunctionSignature::from_enum_variant(db, variant)?;
145
146 Some(CallInfo { signature, active_parameter: None })
147 }
148
149 fn with_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
150 let signature = FunctionSignature::from_macro(db, macro_def)?;
151
152 Some(CallInfo { signature, active_parameter: None })
153 }
154
124 fn parameters(&self) -> &[String] { 155 fn parameters(&self) -> &[String] {
125 &self.signature.parameters 156 &self.signature.parameters
126 } 157 }
@@ -417,6 +448,7 @@ pub fn foo(mut r: WriteHandler<()>) {
417"#, 448"#,
418 ); 449 );
419 450
451 assert_eq!(info.label(), "fn finished(&mut self, ctx: &mut Self::Context)".to_string());
420 assert_eq!(info.parameters(), ["&mut self", "ctx: &mut Self::Context"]); 452 assert_eq!(info.parameters(), ["&mut self", "ctx: &mut Self::Context"]);
421 assert_eq!(info.active_parameter, Some(1)); 453 assert_eq!(info.active_parameter, Some(1));
422 assert_eq!( 454 assert_eq!(
@@ -462,4 +494,96 @@ fn main() {
462 assert_eq!(info.active_parameter, Some(1)); 494 assert_eq!(info.active_parameter, Some(1));
463 assert_eq!(info.label(), "fn bar(&self, _: u32)"); 495 assert_eq!(info.label(), "fn bar(&self, _: u32)");
464 } 496 }
497
498 #[test]
499 fn works_for_tuple_structs() {
500 let info = call_info(
501 r#"
502/// A cool tuple struct
503struct TS(u32, i32);
504fn main() {
505 let s = TS(0, <|>);
506}"#,
507 );
508
509 assert_eq!(info.label(), "struct TS(u32, i32) -> TS");
510 assert_eq!(info.doc().map(|it| it.into()), Some("A cool tuple struct".to_string()));
511 assert_eq!(info.active_parameter, Some(1));
512 }
513
514 #[test]
515 #[should_panic]
516 fn cant_call_named_structs() {
517 let _ = call_info(
518 r#"
519struct TS { x: u32, y: i32 }
520fn main() {
521 let s = TS(<|>);
522}"#,
523 );
524 }
525
526 #[test]
527 fn works_for_enum_variants() {
528 let info = call_info(
529 r#"
530enum E {
531 /// A Variant
532 A(i32),
533 /// Another
534 B,
535 /// And C
536 C { a: i32, b: i32 }
537}
538
539fn main() {
540 let a = E::A(<|>);
541}
542 "#,
543 );
544
545 assert_eq!(info.label(), "E::A(0: i32)");
546 assert_eq!(info.doc().map(|it| it.into()), Some("A Variant".to_string()));
547 assert_eq!(info.active_parameter, Some(0));
548 }
549
550 #[test]
551 #[should_panic]
552 fn cant_call_enum_records() {
553 let _ = call_info(
554 r#"
555enum E {
556 /// A Variant
557 A(i32),
558 /// Another
559 B,
560 /// And C
561 C { a: i32, b: i32 }
562}
563
564fn main() {
565 let a = E::C(<|>);
566}
567 "#,
568 );
569 }
570
571 #[test]
572 fn fn_signature_for_macro() {
573 let info = call_info(
574 r#"
575/// empty macro
576macro_rules! foo {
577 () => {}
578}
579
580fn f() {
581 foo!(<|>);
582}
583 "#,
584 );
585
586 assert_eq!(info.label(), "foo!()");
587 assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string()));
588 }
465} 589}
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs
index 43f022ccd..9075ca443 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;
@@ -12,9 +12,18 @@ use crate::{
12 display::{generic_parameters, where_predicates}, 12 display::{generic_parameters, where_predicates},
13}; 13};
14 14
15#[derive(Debug)]
16pub enum CallableKind {
17 Function,
18 StructConstructor,
19 VariantConstructor,
20 Macro,
21}
22
15/// Contains information about a function signature 23/// Contains information about a function signature
16#[derive(Debug)] 24#[derive(Debug)]
17pub struct FunctionSignature { 25pub struct FunctionSignature {
26 pub kind: CallableKind,
18 /// Optional visibility 27 /// Optional visibility
19 pub visibility: Option<String>, 28 pub visibility: Option<String>,
20 /// Name of the function 29 /// Name of the function
@@ -42,6 +51,99 @@ impl FunctionSignature {
42 let ast_node = function.source(db).ast; 51 let ast_node = function.source(db).ast;
43 FunctionSignature::from(&ast_node).with_doc_opt(doc) 52 FunctionSignature::from(&ast_node).with_doc_opt(doc)
44 } 53 }
54
55 pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Option<Self> {
56 let node: ast::StructDef = st.source(db).ast;
57 match node.kind() {
58 ast::StructKind::Named(_) => return None,
59 _ => (),
60 };
61
62 let params = st
63 .fields(db)
64 .into_iter()
65 .map(|field: hir::StructField| {
66 let ty = field.ty(db);
67 format!("{}", ty.display(db))
68 })
69 .collect();
70
71 Some(
72 FunctionSignature {
73 kind: CallableKind::StructConstructor,
74 visibility: node.visibility().map(|n| n.syntax().text().to_string()),
75 name: node.name().map(|n| n.text().to_string()),
76 ret_type: node.name().map(|n| n.text().to_string()),
77 parameters: params,
78 generic_parameters: generic_parameters(&node),
79 where_predicates: where_predicates(&node),
80 doc: None,
81 }
82 .with_doc_opt(st.docs(db)),
83 )
84 }
85
86 pub(crate) fn from_enum_variant(
87 db: &db::RootDatabase,
88 variant: hir::EnumVariant,
89 ) -> Option<Self> {
90 let node: ast::EnumVariant = variant.source(db).ast;
91 match node.kind() {
92 ast::StructKind::Named(_) | ast::StructKind::Unit => return None,
93 _ => (),
94 };
95
96 let parent_name = match variant.parent_enum(db).name(db) {
97 Some(name) => name.to_string(),
98 None => "missing".into(),
99 };
100
101 let name = format!("{}::{}", parent_name, variant.name(db).unwrap());
102
103 let params = variant
104 .fields(db)
105 .into_iter()
106 .map(|field: hir::StructField| {
107 let name = field.name(db);
108 let ty = field.ty(db);
109 format!("{}: {}", name, ty.display(db))
110 })
111 .collect();
112
113 Some(
114 FunctionSignature {
115 kind: CallableKind::VariantConstructor,
116 visibility: None,
117 name: Some(name),
118 ret_type: None,
119 parameters: params,
120 generic_parameters: vec![],
121 where_predicates: vec![],
122 doc: None,
123 }
124 .with_doc_opt(variant.docs(db)),
125 )
126 }
127
128 pub(crate) fn from_macro(db: &db::RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
129 let node: ast::MacroCall = macro_def.source(db).ast;
130
131 let params = vec![];
132
133 Some(
134 FunctionSignature {
135 kind: CallableKind::Macro,
136 visibility: None,
137 name: node.name().map(|n| n.text().to_string()),
138 ret_type: None,
139 parameters: params,
140 generic_parameters: vec![],
141 where_predicates: vec![],
142 doc: None,
143 }
144 .with_doc_opt(macro_def.docs(db)),
145 )
146 }
45} 147}
46 148
47impl From<&'_ ast::FnDef> for FunctionSignature { 149impl From<&'_ ast::FnDef> for FunctionSignature {
@@ -59,6 +161,7 @@ impl From<&'_ ast::FnDef> for FunctionSignature {
59 } 161 }
60 162
61 FunctionSignature { 163 FunctionSignature {
164 kind: CallableKind::Function,
62 visibility: node.visibility().map(|n| n.syntax().text().to_string()), 165 visibility: node.visibility().map(|n| n.syntax().text().to_string()),
63 name: node.name().map(|n| n.text().to_string()), 166 name: node.name().map(|n| n.text().to_string()),
64 ret_type: node 167 ret_type: node
@@ -81,7 +184,12 @@ impl Display for FunctionSignature {
81 } 184 }
82 185
83 if let Some(name) = &self.name { 186 if let Some(name) = &self.name {
84 write!(f, "fn {}", name)?; 187 match self.kind {
188 CallableKind::Function => write!(f, "fn {}", name)?,
189 CallableKind::StructConstructor => write!(f, "struct {}", name)?,
190 CallableKind::VariantConstructor => write!(f, "{}", name)?,
191 CallableKind::Macro => write!(f, "{}!", name)?,
192 }
85 } 193 }
86 194
87 if !self.generic_parameters.is_empty() { 195 if !self.generic_parameters.is_empty() {
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 16fb07266..20f9aee13 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -27,6 +27,7 @@ use crate::{
27}; 27};
28 28
29pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> { 29pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> {
30 let _p = profile("handle_analyzer_status");
30 let mut buf = world.status(); 31 let mut buf = world.status();
31 writeln!(buf, "\n\nrequests:").unwrap(); 32 writeln!(buf, "\n\nrequests:").unwrap();
32 let requests = world.latest_requests.read(); 33 let requests = world.latest_requests.read();
@@ -38,6 +39,7 @@ pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> {
38} 39}
39 40
40pub fn handle_syntax_tree(world: WorldSnapshot, params: req::SyntaxTreeParams) -> Result<String> { 41pub fn handle_syntax_tree(world: WorldSnapshot, params: req::SyntaxTreeParams) -> Result<String> {
42 let _p = profile("handle_syntax_tree");
41 let id = params.text_document.try_conv_with(&world)?; 43 let id = params.text_document.try_conv_with(&world)?;
42 let line_index = world.analysis().file_line_index(id)?; 44 let line_index = world.analysis().file_line_index(id)?;
43 let text_range = params.range.map(|p| p.conv_with(&line_index)); 45 let text_range = params.range.map(|p| p.conv_with(&line_index));
@@ -172,6 +174,7 @@ pub fn handle_document_symbol(
172 world: WorldSnapshot, 174 world: WorldSnapshot,
173 params: req::DocumentSymbolParams, 175 params: req::DocumentSymbolParams,
174) -> Result<Option<req::DocumentSymbolResponse>> { 176) -> Result<Option<req::DocumentSymbolResponse>> {
177 let _p = profile("handle_document_symbol");
175 let file_id = params.text_document.try_conv_with(&world)?; 178 let file_id = params.text_document.try_conv_with(&world)?;
176 let line_index = world.analysis().file_line_index(file_id)?; 179 let line_index = world.analysis().file_line_index(file_id)?;
177 180
@@ -210,6 +213,7 @@ pub fn handle_workspace_symbol(
210 world: WorldSnapshot, 213 world: WorldSnapshot,
211 params: req::WorkspaceSymbolParams, 214 params: req::WorkspaceSymbolParams,
212) -> Result<Option<Vec<SymbolInformation>>> { 215) -> Result<Option<Vec<SymbolInformation>>> {
216 let _p = profile("handle_workspace_symbol");
213 let all_symbols = params.query.contains('#'); 217 let all_symbols = params.query.contains('#');
214 let libs = params.query.contains('*'); 218 let libs = params.query.contains('*');
215 let query = { 219 let query = {
@@ -253,6 +257,7 @@ pub fn handle_goto_definition(
253 world: WorldSnapshot, 257 world: WorldSnapshot,
254 params: req::TextDocumentPositionParams, 258 params: req::TextDocumentPositionParams,
255) -> Result<Option<req::GotoDefinitionResponse>> { 259) -> Result<Option<req::GotoDefinitionResponse>> {
260 let _p = profile("handle_goto_definition");
256 let position = params.try_conv_with(&world)?; 261 let position = params.try_conv_with(&world)?;
257 let nav_info = match world.analysis().goto_definition(position)? { 262 let nav_info = match world.analysis().goto_definition(position)? {
258 None => return Ok(None), 263 None => return Ok(None),
@@ -266,6 +271,7 @@ pub fn handle_goto_implementation(
266 world: WorldSnapshot, 271 world: WorldSnapshot,
267 params: req::TextDocumentPositionParams, 272 params: req::TextDocumentPositionParams,
268) -> Result<Option<req::GotoImplementationResponse>> { 273) -> Result<Option<req::GotoImplementationResponse>> {
274 let _p = profile("handle_goto_implementation");
269 let position = params.try_conv_with(&world)?; 275 let position = params.try_conv_with(&world)?;
270 let nav_info = match world.analysis().goto_implementation(position)? { 276 let nav_info = match world.analysis().goto_implementation(position)? {
271 None => return Ok(None), 277 None => return Ok(None),
@@ -279,6 +285,7 @@ pub fn handle_goto_type_definition(
279 world: WorldSnapshot, 285 world: WorldSnapshot,
280 params: req::TextDocumentPositionParams, 286 params: req::TextDocumentPositionParams,
281) -> Result<Option<req::GotoTypeDefinitionResponse>> { 287) -> Result<Option<req::GotoTypeDefinitionResponse>> {
288 let _p = profile("handle_goto_type_definition");
282 let position = params.try_conv_with(&world)?; 289 let position = params.try_conv_with(&world)?;
283 let nav_info = match world.analysis().goto_type_definition(position)? { 290 let nav_info = match world.analysis().goto_type_definition(position)? {
284 None => return Ok(None), 291 None => return Ok(None),
@@ -292,6 +299,7 @@ pub fn handle_parent_module(
292 world: WorldSnapshot, 299 world: WorldSnapshot,
293 params: req::TextDocumentPositionParams, 300 params: req::TextDocumentPositionParams,
294) -> Result<Vec<Location>> { 301) -> Result<Vec<Location>> {
302 let _p = profile("handle_parent_module");
295 let position = params.try_conv_with(&world)?; 303 let position = params.try_conv_with(&world)?;
296 world.analysis().parent_module(position)?.iter().try_conv_with_to_vec(&world) 304 world.analysis().parent_module(position)?.iter().try_conv_with_to_vec(&world)
297} 305}
@@ -300,6 +308,7 @@ pub fn handle_runnables(
300 world: WorldSnapshot, 308 world: WorldSnapshot,
301 params: req::RunnablesParams, 309 params: req::RunnablesParams,
302) -> Result<Vec<req::Runnable>> { 310) -> Result<Vec<req::Runnable>> {
311 let _p = profile("handle_runnables");
303 let file_id = params.text_document.try_conv_with(&world)?; 312 let file_id = params.text_document.try_conv_with(&world)?;
304 let line_index = world.analysis().file_line_index(file_id)?; 313 let line_index = world.analysis().file_line_index(file_id)?;
305 let offset = params.position.map(|it| it.conv_with(&line_index)); 314 let offset = params.position.map(|it| it.conv_with(&line_index));
@@ -341,6 +350,7 @@ pub fn handle_decorations(
341 world: WorldSnapshot, 350 world: WorldSnapshot,
342 params: TextDocumentIdentifier, 351 params: TextDocumentIdentifier,
343) -> Result<Vec<Decoration>> { 352) -> Result<Vec<Decoration>> {
353 let _p = profile("handle_decorations");
344 let file_id = params.try_conv_with(&world)?; 354 let file_id = params.try_conv_with(&world)?;
345 highlight(&world, file_id) 355 highlight(&world, file_id)
346} 356}
@@ -389,6 +399,7 @@ pub fn handle_folding_range(
389 world: WorldSnapshot, 399 world: WorldSnapshot,
390 params: FoldingRangeParams, 400 params: FoldingRangeParams,
391) -> Result<Option<Vec<FoldingRange>>> { 401) -> Result<Option<Vec<FoldingRange>>> {
402 let _p = profile("handle_folding_range");
392 let file_id = params.text_document.try_conv_with(&world)?; 403 let file_id = params.text_document.try_conv_with(&world)?;
393 let folds = world.analysis().folding_ranges(file_id)?; 404 let folds = world.analysis().folding_ranges(file_id)?;
394 let text = world.analysis().file_text(file_id)?; 405 let text = world.analysis().file_text(file_id)?;
@@ -406,6 +417,7 @@ pub fn handle_signature_help(
406 world: WorldSnapshot, 417 world: WorldSnapshot,
407 params: req::TextDocumentPositionParams, 418 params: req::TextDocumentPositionParams,
408) -> Result<Option<req::SignatureHelp>> { 419) -> Result<Option<req::SignatureHelp>> {
420 let _p = profile("handle_signature_help");
409 let position = params.try_conv_with(&world)?; 421 let position = params.try_conv_with(&world)?;
410 if let Some(call_info) = world.analysis().call_info(position)? { 422 if let Some(call_info) = world.analysis().call_info(position)? {
411 let active_parameter = call_info.active_parameter.map(|it| it as i64); 423 let active_parameter = call_info.active_parameter.map(|it| it as i64);
@@ -425,6 +437,7 @@ pub fn handle_hover(
425 world: WorldSnapshot, 437 world: WorldSnapshot,
426 params: req::TextDocumentPositionParams, 438 params: req::TextDocumentPositionParams,
427) -> Result<Option<Hover>> { 439) -> Result<Option<Hover>> {
440 let _p = profile("handle_hover");
428 let position = params.try_conv_with(&world)?; 441 let position = params.try_conv_with(&world)?;
429 let info = match world.analysis().hover(position)? { 442 let info = match world.analysis().hover(position)? {
430 None => return Ok(None), 443 None => return Ok(None),
@@ -523,6 +536,7 @@ pub fn handle_formatting(
523 world: WorldSnapshot, 536 world: WorldSnapshot,
524 params: DocumentFormattingParams, 537 params: DocumentFormattingParams,
525) -> Result<Option<Vec<TextEdit>>> { 538) -> Result<Option<Vec<TextEdit>>> {
539 let _p = profile("handle_formatting");
526 let file_id = params.text_document.try_conv_with(&world)?; 540 let file_id = params.text_document.try_conv_with(&world)?;
527 let file = world.analysis().file_text(file_id)?; 541 let file = world.analysis().file_text(file_id)?;
528 542
@@ -645,6 +659,7 @@ pub fn handle_code_lens(
645 world: WorldSnapshot, 659 world: WorldSnapshot,
646 params: req::CodeLensParams, 660 params: req::CodeLensParams,
647) -> Result<Option<Vec<CodeLens>>> { 661) -> Result<Option<Vec<CodeLens>>> {
662 let _p = profile("handle_code_lens");
648 let file_id = params.text_document.try_conv_with(&world)?; 663 let file_id = params.text_document.try_conv_with(&world)?;
649 let line_index = world.analysis().file_line_index(file_id)?; 664 let line_index = world.analysis().file_line_index(file_id)?;
650 665
@@ -705,6 +720,7 @@ enum CodeLensResolveData {
705} 720}
706 721
707pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Result<CodeLens> { 722pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Result<CodeLens> {
723 let _p = profile("handle_code_lens_resolve");
708 let data = code_lens.data.unwrap(); 724 let data = code_lens.data.unwrap();
709 let resolve = serde_json::from_value(data)?; 725 let resolve = serde_json::from_value(data)?;
710 match resolve { 726 match resolve {
@@ -776,6 +792,7 @@ pub fn publish_diagnostics(
776 world: &WorldSnapshot, 792 world: &WorldSnapshot,
777 file_id: FileId, 793 file_id: FileId,
778) -> Result<req::PublishDiagnosticsParams> { 794) -> Result<req::PublishDiagnosticsParams> {
795 let _p = profile("publish_diagnostics");
779 let uri = world.file_id_to_uri(file_id)?; 796 let uri = world.file_id_to_uri(file_id)?;
780 let line_index = world.analysis().file_line_index(file_id)?; 797 let line_index = world.analysis().file_line_index(file_id)?;
781 let diagnostics = world 798 let diagnostics = world
@@ -798,6 +815,7 @@ pub fn publish_decorations(
798 world: &WorldSnapshot, 815 world: &WorldSnapshot,
799 file_id: FileId, 816 file_id: FileId,
800) -> Result<req::PublishDecorationsParams> { 817) -> Result<req::PublishDecorationsParams> {
818 let _p = profile("publish_decorations");
801 let uri = world.file_id_to_uri(file_id)?; 819 let uri = world.file_id_to_uri(file_id)?;
802 Ok(req::PublishDecorationsParams { uri, decorations: highlight(&world, file_id)? }) 820 Ok(req::PublishDecorationsParams { uri, decorations: highlight(&world, file_id)? })
803} 821}
@@ -847,6 +865,7 @@ pub fn handle_inlay_hints(
847 world: WorldSnapshot, 865 world: WorldSnapshot,
848 params: InlayHintsParams, 866 params: InlayHintsParams,
849) -> Result<Vec<InlayHint>> { 867) -> Result<Vec<InlayHint>> {
868 let _p = profile("handle_inlay_hints");
850 let file_id = params.text_document.try_conv_with(&world)?; 869 let file_id = params.text_document.try_conv_with(&world)?;
851 let analysis = world.analysis(); 870 let analysis = world.analysis();
852 let line_index = analysis.file_line_index(file_id)?; 871 let line_index = analysis.file_line_index(file_id)?;