Make goto definition/hover resolve constructors

This commit is contained in:
kjeremy 2019-03-01 18:26:49 -05:00 committed by Jeremy Kolb
parent dc8bcc1e42
commit 49da9a3e81
3 changed files with 87 additions and 7 deletions

View file

@ -47,9 +47,10 @@ pub(crate) fn reference_definition(
name_ref: &ast::NameRef,
) -> ReferenceResult {
use self::ReferenceResult::*;
if let Some(function) =
hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())
{
let function = hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax());
if let Some(function) = function {
// Check if it is a method
if let Some(method_call) = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast) {
tested_by!(goto_definition_works_for_methods);
@ -122,9 +123,29 @@ pub(crate) fn reference_definition(
Some(Resolution::SelfType(_impl_block)) => {
// TODO: go to the implemented type
}
None => {}
None => {
// If we failed to resolve then check associated items
if let Some(function) = function {
// Should we do this above and then grab path from the PathExpr?
if let Some(path_expr) =
name_ref.syntax().ancestors().find_map(ast::PathExpr::cast)
{
let infer_result = function.infer(db);
let syntax_mapping = function.body_syntax_mapping(db);
let expr = ast::Expr::cast(path_expr.syntax()).unwrap();
if let Some(func) = syntax_mapping
.node_expr(expr)
.and_then(|it| infer_result.assoc_fn_resolutions(it))
{
return Exact(NavigationTarget::from_function(db, func));
}
}
}
}
}
}
// If that fails try the index based approach.
let navs = crate::symbol_index::index_resolve(db, name_ref)
.into_iter()

View file

@ -512,4 +512,26 @@ mod tests {
let hover = analysis.hover(position).unwrap().unwrap();
assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing"));
}
#[test]
fn test_hover_infer_associated_method_exact() {
let (analysis, position) = single_file_with_position(
"
struct Thing { x: u32 }
impl Thing {
fn new() -> Thing {
Thing { x: 0 }
}
}
fn main() {
let foo_test = Thing::new<|>();
}
",
);
let hover = analysis.hover(position).unwrap().unwrap();
assert_eq!(hover.info.first(), Some("```rust\nfn new() -> Thing\n```"));
assert_eq!(hover.info.is_exact(), true);
}
}