mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-19 02:13:57 +00:00
Merge #944
944: Add support for goto definition and hover on Self r=matklad a=vipentti This fixes #943 Co-authored-by: Ville Penttinen <villem.penttinen@gmail.com>
This commit is contained in:
commit
711b82a701
@ -205,19 +205,8 @@ pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> R
|
||||
// TODO const/static/array length
|
||||
None
|
||||
}
|
||||
} else if let Some(module) = ast::Module::cast(node) {
|
||||
Some(module_from_declaration(db, file_id, module)?.resolver(db))
|
||||
} else if let Some(_) = ast::SourceFile::cast(node) {
|
||||
Some(module_from_source(db, file_id.into(), None)?.resolver(db))
|
||||
} else if let Some(s) = ast::StructDef::cast(node) {
|
||||
let module = module_from_child_node(db, file_id, s.syntax())?;
|
||||
Some(struct_from_module(db, module, s).resolver(db))
|
||||
} else if let Some(e) = ast::EnumDef::cast(node) {
|
||||
let module = module_from_child_node(db, file_id, e.syntax())?;
|
||||
Some(enum_from_module(db, module, e).resolver(db))
|
||||
} else {
|
||||
// TODO add missing cases
|
||||
None
|
||||
try_get_resolver_for_node(db, file_id, node)
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -236,20 +225,32 @@ pub fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNo
|
||||
// TODO const/static/array length
|
||||
None
|
||||
}
|
||||
} else if let Some(module) = ast::Module::cast(node) {
|
||||
Some(module_from_declaration(db, file_id, module)?.resolver(db))
|
||||
} else if let Some(_) = ast::SourceFile::cast(node) {
|
||||
Some(module_from_source(db, file_id.into(), None)?.resolver(db))
|
||||
} else if let Some(s) = ast::StructDef::cast(node) {
|
||||
let module = module_from_child_node(db, file_id, s.syntax())?;
|
||||
Some(struct_from_module(db, module, s).resolver(db))
|
||||
} else if let Some(e) = ast::EnumDef::cast(node) {
|
||||
let module = module_from_child_node(db, file_id, e.syntax())?;
|
||||
Some(enum_from_module(db, module, e).resolver(db))
|
||||
} else {
|
||||
// TODO add missing cases
|
||||
None
|
||||
try_get_resolver_for_node(db, file_id, node)
|
||||
}
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn try_get_resolver_for_node(
|
||||
db: &impl HirDatabase,
|
||||
file_id: FileId,
|
||||
node: &SyntaxNode,
|
||||
) -> Option<Resolver> {
|
||||
if let Some(module) = ast::Module::cast(node) {
|
||||
Some(module_from_declaration(db, file_id, module)?.resolver(db))
|
||||
} else if let Some(_) = ast::SourceFile::cast(node) {
|
||||
Some(module_from_source(db, file_id.into(), None)?.resolver(db))
|
||||
} else if let Some(s) = ast::StructDef::cast(node) {
|
||||
let module = module_from_child_node(db, file_id, s.syntax())?;
|
||||
Some(struct_from_module(db, module, s).resolver(db))
|
||||
} else if let Some(e) = ast::EnumDef::cast(node) {
|
||||
let module = module_from_child_node(db, file_id, e.syntax())?;
|
||||
Some(enum_from_module(db, module, e).resolver(db))
|
||||
} else if let Some(f) = ast::FnDef::cast(node) {
|
||||
function_from_source(db, file_id, f).map(|f| f.resolver(db))
|
||||
} else {
|
||||
// TODO add missing cases
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -121,8 +121,12 @@ pub(crate) fn reference_definition(
|
||||
Some(Resolution::GenericParam(..)) => {
|
||||
// TODO: go to the generic param def
|
||||
}
|
||||
Some(Resolution::SelfType(_impl_block)) => {
|
||||
// TODO: go to the implemented type
|
||||
Some(Resolution::SelfType(impl_block)) => {
|
||||
let ty = impl_block.target_ty(db);
|
||||
|
||||
if let hir::Ty::Adt { def_id, .. } = ty {
|
||||
return Exact(NavigationTarget::from_adt_def(db, def_id));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// If we failed to resolve then check associated items
|
||||
@ -337,6 +341,94 @@ mod tests {
|
||||
"spam NAMED_FIELD_DEF FileId(1) [17; 26) [17; 21)",
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn goto_definition_on_self() {
|
||||
check_goto(
|
||||
"
|
||||
//- /lib.rs
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
pub fn new() -> Self {
|
||||
Self<|> {}
|
||||
}
|
||||
}
|
||||
",
|
||||
"Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
|
||||
);
|
||||
|
||||
check_goto(
|
||||
"
|
||||
//- /lib.rs
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
pub fn new() -> Self<|> {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
",
|
||||
"Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
|
||||
);
|
||||
|
||||
check_goto(
|
||||
"
|
||||
//- /lib.rs
|
||||
enum Foo { A }
|
||||
impl Foo {
|
||||
pub fn new() -> Self<|> {
|
||||
Foo::A
|
||||
}
|
||||
}
|
||||
",
|
||||
"Foo ENUM_DEF FileId(1) [0; 14) [5; 8)",
|
||||
);
|
||||
|
||||
check_goto(
|
||||
"
|
||||
//- /lib.rs
|
||||
enum Foo { A }
|
||||
impl Foo {
|
||||
pub fn thing(a: &Self<|>) {
|
||||
}
|
||||
}
|
||||
",
|
||||
"Foo ENUM_DEF FileId(1) [0; 14) [5; 8)",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_definition_on_self_in_trait_impl() {
|
||||
check_goto(
|
||||
"
|
||||
//- /lib.rs
|
||||
struct Foo;
|
||||
trait Make {
|
||||
fn new() -> Self;
|
||||
}
|
||||
impl Make for Foo {
|
||||
fn new() -> Self {
|
||||
Self<|> {}
|
||||
}
|
||||
}
|
||||
",
|
||||
"Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
|
||||
);
|
||||
|
||||
check_goto(
|
||||
"
|
||||
//- /lib.rs
|
||||
struct Foo;
|
||||
trait Make {
|
||||
fn new() -> Self;
|
||||
}
|
||||
impl Make for Foo {
|
||||
fn new() -> Self<|> {
|
||||
Self{}
|
||||
}
|
||||
}
|
||||
",
|
||||
"Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_definition_works_when_used_on_definition_name_itself() {
|
||||
|
@ -557,4 +557,62 @@ mod tests {
|
||||
assert_eq!(trim_markup_opt(hover.info.first()), Some("const C: u32"));
|
||||
assert_eq!(hover.info.is_exact(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hover_self() {
|
||||
let (analysis, position) = single_file_with_position(
|
||||
"
|
||||
struct Thing { x: u32 };
|
||||
impl Thing {
|
||||
fn new() -> Self {
|
||||
Self<|> { x: 0 }
|
||||
}
|
||||
}
|
||||
",
|
||||
);
|
||||
let hover = analysis.hover(position).unwrap().unwrap();
|
||||
assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing"));
|
||||
assert_eq!(hover.info.is_exact(), true);
|
||||
|
||||
let (analysis, position) = single_file_with_position(
|
||||
"
|
||||
struct Thing { x: u32 };
|
||||
impl Thing {
|
||||
fn new() -> Self<|> {
|
||||
Self { x: 0 }
|
||||
}
|
||||
}
|
||||
",
|
||||
);
|
||||
let hover = analysis.hover(position).unwrap().unwrap();
|
||||
assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing"));
|
||||
assert_eq!(hover.info.is_exact(), true);
|
||||
|
||||
let (analysis, position) = single_file_with_position(
|
||||
"
|
||||
enum Thing { A };
|
||||
impl Thing {
|
||||
pub fn new() -> Self<|> {
|
||||
Thing::A
|
||||
}
|
||||
}
|
||||
",
|
||||
);
|
||||
let hover = analysis.hover(position).unwrap().unwrap();
|
||||
assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing"));
|
||||
assert_eq!(hover.info.is_exact(), true);
|
||||
|
||||
let (analysis, position) = single_file_with_position(
|
||||
"
|
||||
enum Thing { A };
|
||||
impl Thing {
|
||||
pub fn thing(a: Self<|>) {
|
||||
}
|
||||
}
|
||||
",
|
||||
);
|
||||
let hover = analysis.hover(position).unwrap().unwrap();
|
||||
assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing"));
|
||||
assert_eq!(hover.info.is_exact(), true);
|
||||
}
|
||||
}
|
||||
|
@ -126,6 +126,19 @@ impl NavigationTarget {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_adt_def(db: &RootDatabase, adt_def: hir::AdtDef) -> NavigationTarget {
|
||||
match adt_def {
|
||||
hir::AdtDef::Struct(s) => {
|
||||
let (file_id, node) = s.source(db);
|
||||
NavigationTarget::from_named(file_id.original_file(db), &*node)
|
||||
}
|
||||
hir::AdtDef::Enum(s) => {
|
||||
let (file_id, node) = s.source(db);
|
||||
NavigationTarget::from_named(file_id.original_file(db), &*node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_def(db: &RootDatabase, module_def: hir::ModuleDef) -> NavigationTarget {
|
||||
match module_def {
|
||||
hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module),
|
||||
|
Loading…
Reference in New Issue
Block a user