From 01238a6fd7d89f97ea05d90b95d3244f1596dc93 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Mon, 28 Oct 2019 10:48:40 -0400 Subject: Filter out non callable versions of Struct/EnumVariant --- crates/ra_ide_api/src/call_info.rs | 52 +++++++++++++--- .../ra_ide_api/src/display/function_signature.rs | 70 +++++++++++++--------- 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 { (CallInfo::with_fn(db, it), it.data(db).has_self_param()) } - hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it), false), - hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it), false), + hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false), + hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false), } } FnCallNode::MethodCallExpr(expr) => { @@ -123,16 +123,16 @@ impl CallInfo { CallInfo { signature, active_parameter: None } } - fn with_struct(db: &RootDatabase, st: hir::Struct) -> Self { - let signature = FunctionSignature::from_struct(db, st); + fn with_struct(db: &RootDatabase, st: hir::Struct) -> Option { + let signature = FunctionSignature::from_struct(db, st)?; - CallInfo { signature, active_parameter: None } + Some(CallInfo { signature, active_parameter: None }) } - fn with_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Self { - let signature = FunctionSignature::from_enum_variant(db, variant); + fn with_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option { + let signature = FunctionSignature::from_enum_variant(db, variant)?; - CallInfo { signature, active_parameter: None } + Some(CallInfo { signature, active_parameter: None }) } fn parameters(&self) -> &[String] { @@ -477,6 +477,7 @@ fn main() { assert_eq!(info.label(), "fn bar(&self, _: u32)"); } + #[test] fn works_for_tuple_structs() { let info = call_info( r#" @@ -487,11 +488,23 @@ fn main() { }"#, ); - assert_eq!(info.label(), "struct TS(0: u32, 1: i32) -> TS"); + assert_eq!(info.label(), "struct TS(u32, i32) -> TS"); assert_eq!(info.doc().map(|it| it.into()), Some("A cool tuple struct".to_string())); assert_eq!(info.active_parameter, Some(1)); } + #[test] + #[should_panic] + fn cant_call_named_structs() { + let _ = call_info( + r#" +struct TS { x: u32, y: i32 } +fn main() { + let s = TS(<|>); +}"#, + ); + } + #[test] fn works_for_enum_variants() { let info = call_info( @@ -515,4 +528,25 @@ fn main() { assert_eq!(info.doc().map(|it| it.into()), Some("A Variant".to_string())); assert_eq!(info.active_parameter, Some(0)); } + + #[test] + #[should_panic] + fn cant_call_enum_records() { + let _ = call_info( + r#" +enum E { + /// A Variant + A(i32), + /// Another + B, + /// And C + C { a: i32, b: i32 } +} + +fn main() { + let a = E::C(<|>); +} + "#, + ); + } } 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 { 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); - + pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Option { let node: ast::StructDef = st.source(db).ast; + match node.kind() { + ast::StructKind::Named(_) => return None, + _ => (), + }; 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)) + format!("{}", ty.display(db)) }) .collect(); - FunctionSignature { - kind: SigKind::Struct, - 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: params, - generic_parameters: generic_parameters(&node), - where_predicates: where_predicates(&node), - doc: None, - } - .with_doc_opt(doc) + Some( + FunctionSignature { + kind: SigKind::Struct, + 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: params, + generic_parameters: generic_parameters(&node), + where_predicates: where_predicates(&node), + doc: None, + } + .with_doc_opt(st.docs(db)), + ) } - pub(crate) fn from_enum_variant(db: &db::RootDatabase, variant: hir::EnumVariant) -> Self { - let doc = variant.docs(db); + pub(crate) fn from_enum_variant( + db: &db::RootDatabase, + variant: hir::EnumVariant, + ) -> Option { + let node: ast::EnumVariant = variant.source(db).ast; + match node.kind() { + ast::StructKind::Named(_) | ast::StructKind::Unit => return None, + _ => (), + }; let parent_name = match variant.parent_enum(db).name(db) { Some(name) => name.to_string(), @@ -99,17 +109,19 @@ impl FunctionSignature { }) .collect(); - FunctionSignature { - kind: SigKind::EnumVariant, - visibility: None, - name: Some(name), - ret_type: None, - parameters: params, - generic_parameters: vec![], - where_predicates: vec![], - doc: None, - } - .with_doc_opt(doc) + Some( + FunctionSignature { + kind: SigKind::EnumVariant, + visibility: None, + name: Some(name), + ret_type: None, + parameters: params, + generic_parameters: vec![], + where_predicates: vec![], + doc: None, + } + .with_doc_opt(variant.docs(db)), + ) } } -- cgit v1.2.3