Filter out non callable versions of Struct/EnumVariant

This commit is contained in:
kjeremy 2019-10-28 10:48:40 -04:00
parent ddf25e9481
commit 01238a6fd7
2 changed files with 84 additions and 38 deletions

View File

@ -28,8 +28,8 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
hir::CallableDef::Function(it) => { hir::CallableDef::Function(it) => {
(CallInfo::with_fn(db, it), it.data(db).has_self_param()) (CallInfo::with_fn(db, it), it.data(db).has_self_param())
} }
hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it), false), hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false),
hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it), false), hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false),
} }
} }
FnCallNode::MethodCallExpr(expr) => { FnCallNode::MethodCallExpr(expr) => {
@ -123,16 +123,16 @@ impl CallInfo {
CallInfo { signature, active_parameter: None } CallInfo { signature, active_parameter: None }
} }
fn with_struct(db: &RootDatabase, st: hir::Struct) -> Self { fn with_struct(db: &RootDatabase, st: hir::Struct) -> Option<Self> {
let signature = FunctionSignature::from_struct(db, st); 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 { fn with_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option<Self> {
let signature = FunctionSignature::from_enum_variant(db, variant); let signature = FunctionSignature::from_enum_variant(db, variant)?;
CallInfo { signature, active_parameter: None } Some(CallInfo { signature, active_parameter: None })
} }
fn parameters(&self) -> &[String] { fn parameters(&self) -> &[String] {
@ -477,6 +477,7 @@ fn main() {
assert_eq!(info.label(), "fn bar(&self, _: u32)"); assert_eq!(info.label(), "fn bar(&self, _: u32)");
} }
#[test]
fn works_for_tuple_structs() { fn works_for_tuple_structs() {
let info = call_info( let info = call_info(
r#" 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.doc().map(|it| it.into()), Some("A cool tuple struct".to_string()));
assert_eq!(info.active_parameter, Some(1)); 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] #[test]
fn works_for_enum_variants() { fn works_for_enum_variants() {
let info = call_info( 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.doc().map(|it| it.into()), Some("A Variant".to_string()));
assert_eq!(info.active_parameter, Some(0)); 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(<|>);
}
"#,
);
}
} }

View File

@ -51,36 +51,46 @@ impl FunctionSignature {
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 { pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Option<Self> {
let doc = st.docs(db);
let node: ast::StructDef = st.source(db).ast; let node: ast::StructDef = st.source(db).ast;
match node.kind() {
ast::StructKind::Named(_) => return None,
_ => (),
};
let params = st let params = st
.fields(db) .fields(db)
.into_iter() .into_iter()
.map(|field: hir::StructField| { .map(|field: hir::StructField| {
let name = field.name(db);
let ty = field.ty(db); let ty = field.ty(db);
format!("{}: {}", name, ty.display(db)) format!("{}", ty.display(db))
}) })
.collect(); .collect();
FunctionSignature { Some(
kind: SigKind::Struct, FunctionSignature {
visibility: node.visibility().map(|n| n.syntax().text().to_string()), kind: SigKind::Struct,
name: node.name().map(|n| n.text().to_string()), visibility: node.visibility().map(|n| n.syntax().text().to_string()),
ret_type: node.name().map(|n| n.text().to_string()), name: node.name().map(|n| n.text().to_string()),
parameters: params, ret_type: node.name().map(|n| n.text().to_string()),
generic_parameters: generic_parameters(&node), parameters: params,
where_predicates: where_predicates(&node), generic_parameters: generic_parameters(&node),
doc: None, where_predicates: where_predicates(&node),
} doc: None,
.with_doc_opt(doc) }
.with_doc_opt(st.docs(db)),
)
} }
pub(crate) fn from_enum_variant(db: &db::RootDatabase, variant: hir::EnumVariant) -> Self { pub(crate) fn from_enum_variant(
let doc = variant.docs(db); db: &db::RootDatabase,
variant: hir::EnumVariant,
) -> Option<Self> {
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) { let parent_name = match variant.parent_enum(db).name(db) {
Some(name) => name.to_string(), Some(name) => name.to_string(),
@ -99,17 +109,19 @@ impl FunctionSignature {
}) })
.collect(); .collect();
FunctionSignature { Some(
kind: SigKind::EnumVariant, FunctionSignature {
visibility: None, kind: SigKind::EnumVariant,
name: Some(name), visibility: None,
ret_type: None, name: Some(name),
parameters: params, ret_type: None,
generic_parameters: vec![], parameters: params,
where_predicates: vec![], generic_parameters: vec![],
doc: None, where_predicates: vec![],
} doc: None,
.with_doc_opt(doc) }
.with_doc_opt(variant.docs(db)),
)
} }
} }