aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkjeremy <[email protected]>2019-10-28 14:48:40 +0000
committerkjeremy <[email protected]>2019-10-28 14:48:40 +0000
commit01238a6fd7d89f97ea05d90b95d3244f1596dc93 (patch)
treec56902871c42cf5a9875fa56c69932e7c4dca931
parentddf25e9481d79abb6b583a195fd26b8ca1b9f060 (diff)
Filter out non callable versions of Struct/EnumVariant
-rw-r--r--crates/ra_ide_api/src/call_info.rs52
-rw-r--r--crates/ra_ide_api/src/display/function_signature.rs70
2 files changed, 84 insertions, 38 deletions
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index 25363a1d9..d947ac50c 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -28,8 +28,8 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
28 hir::CallableDef::Function(it) => { 28 hir::CallableDef::Function(it) => {
29 (CallInfo::with_fn(db, it), it.data(db).has_self_param()) 29 (CallInfo::with_fn(db, it), it.data(db).has_self_param())
30 } 30 }
31 hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it), false), 31 hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false),
32 hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it), false), 32 hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false),
33 } 33 }
34 } 34 }
35 FnCallNode::MethodCallExpr(expr) => { 35 FnCallNode::MethodCallExpr(expr) => {
@@ -123,16 +123,16 @@ impl CallInfo {
123 CallInfo { signature, active_parameter: None } 123 CallInfo { signature, active_parameter: None }
124 } 124 }
125 125
126 fn with_struct(db: &RootDatabase, st: hir::Struct) -> Self { 126 fn with_struct(db: &RootDatabase, st: hir::Struct) -> Option<Self> {
127 let signature = FunctionSignature::from_struct(db, st); 127 let signature = FunctionSignature::from_struct(db, st)?;
128 128
129 CallInfo { signature, active_parameter: None } 129 Some(CallInfo { signature, active_parameter: None })
130 } 130 }
131 131
132 fn with_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Self { 132 fn with_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option<Self> {
133 let signature = FunctionSignature::from_enum_variant(db, variant); 133 let signature = FunctionSignature::from_enum_variant(db, variant)?;
134 134
135 CallInfo { signature, active_parameter: None } 135 Some(CallInfo { signature, active_parameter: None })
136 } 136 }
137 137
138 fn parameters(&self) -> &[String] { 138 fn parameters(&self) -> &[String] {
@@ -477,6 +477,7 @@ fn main() {
477 assert_eq!(info.label(), "fn bar(&self, _: u32)"); 477 assert_eq!(info.label(), "fn bar(&self, _: u32)");
478 } 478 }
479 479
480 #[test]
480 fn works_for_tuple_structs() { 481 fn works_for_tuple_structs() {
481 let info = call_info( 482 let info = call_info(
482 r#" 483 r#"
@@ -487,12 +488,24 @@ fn main() {
487}"#, 488}"#,
488 ); 489 );
489 490
490 assert_eq!(info.label(), "struct TS(0: u32, 1: i32) -> TS"); 491 assert_eq!(info.label(), "struct TS(u32, i32) -> TS");
491 assert_eq!(info.doc().map(|it| it.into()), Some("A cool tuple struct".to_string())); 492 assert_eq!(info.doc().map(|it| it.into()), Some("A cool tuple struct".to_string()));
492 assert_eq!(info.active_parameter, Some(1)); 493 assert_eq!(info.active_parameter, Some(1));
493 } 494 }
494 495
495 #[test] 496 #[test]
497 #[should_panic]
498 fn cant_call_named_structs() {
499 let _ = call_info(
500 r#"
501struct TS { x: u32, y: i32 }
502fn main() {
503 let s = TS(<|>);
504}"#,
505 );
506 }
507
508 #[test]
496 fn works_for_enum_variants() { 509 fn works_for_enum_variants() {
497 let info = call_info( 510 let info = call_info(
498 r#" 511 r#"
@@ -515,4 +528,25 @@ fn main() {
515 assert_eq!(info.doc().map(|it| it.into()), Some("A Variant".to_string())); 528 assert_eq!(info.doc().map(|it| it.into()), Some("A Variant".to_string()));
516 assert_eq!(info.active_parameter, Some(0)); 529 assert_eq!(info.active_parameter, Some(0));
517 } 530 }
531
532 #[test]
533 #[should_panic]
534 fn cant_call_enum_records() {
535 let _ = call_info(
536 r#"
537enum E {
538 /// A Variant
539 A(i32),
540 /// Another
541 B,
542 /// And C
543 C { a: i32, b: i32 }
544}
545
546fn main() {
547 let a = E::C(<|>);
548}
549 "#,
550 );
551 }
518} 552}
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs
index 6b169b3ae..736b5d3db 100644
--- a/crates/ra_ide_api/src/display/function_signature.rs
+++ b/crates/ra_ide_api/src/display/function_signature.rs
@@ -51,36 +51,46 @@ impl FunctionSignature {
51 FunctionSignature::from(&ast_node).with_doc_opt(doc) 51 FunctionSignature::from(&ast_node).with_doc_opt(doc)
52 } 52 }
53 53
54 pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Self { 54 pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Option<Self> {
55 let doc = st.docs(db);
56
57 let node: ast::StructDef = st.source(db).ast; 55 let node: ast::StructDef = st.source(db).ast;
56 match node.kind() {
57 ast::StructKind::Named(_) => return None,
58 _ => (),
59 };
58 60
59 let params = st 61 let params = st
60 .fields(db) 62 .fields(db)
61 .into_iter() 63 .into_iter()
62 .map(|field: hir::StructField| { 64 .map(|field: hir::StructField| {
63 let name = field.name(db);
64 let ty = field.ty(db); 65 let ty = field.ty(db);
65 format!("{}: {}", name, ty.display(db)) 66 format!("{}", ty.display(db))
66 }) 67 })
67 .collect(); 68 .collect();
68 69
69 FunctionSignature { 70 Some(
70 kind: SigKind::Struct, 71 FunctionSignature {
71 visibility: node.visibility().map(|n| n.syntax().text().to_string()), 72 kind: SigKind::Struct,
72 name: node.name().map(|n| n.text().to_string()), 73 visibility: node.visibility().map(|n| n.syntax().text().to_string()),
73 ret_type: node.name().map(|n| n.text().to_string()), 74 name: node.name().map(|n| n.text().to_string()),
74 parameters: params, 75 ret_type: node.name().map(|n| n.text().to_string()),
75 generic_parameters: generic_parameters(&node), 76 parameters: params,
76 where_predicates: where_predicates(&node), 77 generic_parameters: generic_parameters(&node),
77 doc: None, 78 where_predicates: where_predicates(&node),
78 } 79 doc: None,
79 .with_doc_opt(doc) 80 }
81 .with_doc_opt(st.docs(db)),
82 )
80 } 83 }
81 84
82 pub(crate) fn from_enum_variant(db: &db::RootDatabase, variant: hir::EnumVariant) -> Self { 85 pub(crate) fn from_enum_variant(
83 let doc = variant.docs(db); 86 db: &db::RootDatabase,
87 variant: hir::EnumVariant,
88 ) -> Option<Self> {
89 let node: ast::EnumVariant = variant.source(db).ast;
90 match node.kind() {
91 ast::StructKind::Named(_) | ast::StructKind::Unit => return None,
92 _ => (),
93 };
84 94
85 let parent_name = match variant.parent_enum(db).name(db) { 95 let parent_name = match variant.parent_enum(db).name(db) {
86 Some(name) => name.to_string(), 96 Some(name) => name.to_string(),
@@ -99,17 +109,19 @@ impl FunctionSignature {
99 }) 109 })
100 .collect(); 110 .collect();
101 111
102 FunctionSignature { 112 Some(
103 kind: SigKind::EnumVariant, 113 FunctionSignature {
104 visibility: None, 114 kind: SigKind::EnumVariant,
105 name: Some(name), 115 visibility: None,
106 ret_type: None, 116 name: Some(name),
107 parameters: params, 117 ret_type: None,
108 generic_parameters: vec![], 118 parameters: params,
109 where_predicates: vec![], 119 generic_parameters: vec![],
110 doc: None, 120 where_predicates: vec![],
111 } 121 doc: None,
112 .with_doc_opt(doc) 122 }
123 .with_doc_opt(variant.docs(db)),
124 )
113 } 125 }
114} 126}
115 127