2116: Basic signature help for mbe r=matklad a=kjeremy

This is really basic and just adds info and docs. Does something like this even make sense to have? I wasn't sure how to handle arguments so left them empty for now.

Co-authored-by: kjeremy <kjeremy@gmail.com>
This commit is contained in:
bors[bot] 2019-10-29 16:46:46 +00:00 committed by GitHub
commit 0290fa5fa3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 58 additions and 0 deletions

View file

@ -36,6 +36,10 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
let function = analyzer.resolve_method_call(&expr)?;
(CallInfo::with_fn(db, function), function.data(db).has_self_param())
}
FnCallNode::MacroCallExpr(expr) => {
let macro_def = analyzer.resolve_macro_call(db, &expr)?;
(CallInfo::with_macro(db, macro_def)?, false)
}
};
// If we have a calling expression let's find which argument we are on
@ -77,9 +81,11 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
Some(call_info)
}
#[derive(Debug)]
enum FnCallNode {
CallExpr(ast::CallExpr),
MethodCallExpr(ast::MethodCallExpr),
MacroCallExpr(ast::MacroCall),
}
impl FnCallNode {
@ -89,6 +95,8 @@ impl FnCallNode {
Some(FnCallNode::CallExpr(expr))
} else if let Some(expr) = ast::MethodCallExpr::cast(node.clone()) {
Some(FnCallNode::MethodCallExpr(expr))
} else if let Some(expr) = ast::MacroCall::cast(node.clone()) {
Some(FnCallNode::MacroCallExpr(expr))
} else {
None
}
@ -105,6 +113,8 @@ impl FnCallNode {
FnCallNode::MethodCallExpr(call_expr) => {
call_expr.syntax().children().filter_map(ast::NameRef::cast).nth(0)
}
FnCallNode::MacroCallExpr(call_expr) => call_expr.path()?.segment()?.name_ref(),
}
}
@ -112,6 +122,7 @@ impl FnCallNode {
match self {
FnCallNode::CallExpr(expr) => expr.arg_list(),
FnCallNode::MethodCallExpr(expr) => expr.arg_list(),
FnCallNode::MacroCallExpr(_) => None,
}
}
}
@ -135,6 +146,12 @@ impl CallInfo {
Some(CallInfo { signature, active_parameter: None })
}
fn with_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
let signature = FunctionSignature::from_macro(db, macro_def)?;
Some(CallInfo { signature, active_parameter: None })
}
fn parameters(&self) -> &[String] {
&self.signature.parameters
}
@ -549,4 +566,23 @@ fn main() {
"#,
);
}
#[test]
fn fn_signature_for_macro() {
let info = call_info(
r#"
/// empty macro
macro_rules! foo {
() => {}
}
fn f() {
foo!(<|>);
}
"#,
);
assert_eq!(info.label(), "foo!()");
assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string()));
}
}

View file

@ -17,6 +17,7 @@ pub enum CallableKind {
Function,
StructConstructor,
VariantConstructor,
Macro,
}
/// Contains information about a function signature
@ -123,6 +124,26 @@ impl FunctionSignature {
.with_doc_opt(variant.docs(db)),
)
}
pub(crate) fn from_macro(db: &db::RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
let node: ast::MacroCall = macro_def.source(db).ast;
let params = vec![];
Some(
FunctionSignature {
kind: CallableKind::Macro,
visibility: None,
name: node.name().map(|n| n.text().to_string()),
ret_type: None,
parameters: params,
generic_parameters: vec![],
where_predicates: vec![],
doc: None,
}
.with_doc_opt(macro_def.docs(db)),
)
}
}
impl From<&'_ ast::FnDef> for FunctionSignature {
@ -167,6 +188,7 @@ impl Display for FunctionSignature {
CallableKind::Function => write!(f, "fn {}", name)?,
CallableKind::StructConstructor => write!(f, "struct {}", name)?,
CallableKind::VariantConstructor => write!(f, "{}", name)?,
CallableKind::Macro => write!(f, "{}!", name)?,
}
}