]> git.lizzy.rs Git - rust.git/blob - crates/ra_ide_api/src/navigation_target.rs
reshuffle nones
[rust.git] / crates / ra_ide_api / src / navigation_target.rs
1 use ra_db::{FileId, LocalSyntaxPtr, Cancelable};
2 use ra_syntax::{
3     SyntaxNode, AstNode, SmolStr,
4     ast
5 };
6 use hir::{Def, ModuleSource};
7
8 use crate::{
9     NavigationTarget,
10     FileSymbol,
11     db::RootDatabase,
12 };
13
14 impl NavigationTarget {
15     pub(crate) fn from_symbol(symbol: FileSymbol) -> NavigationTarget {
16         NavigationTarget {
17             file_id: symbol.file_id,
18             name: symbol.name.clone(),
19             kind: symbol.ptr.kind(),
20             range: symbol.ptr.range(),
21             ptr: Some(symbol.ptr.clone()),
22         }
23     }
24
25     // TODO once Def::Item is gone, this should be able to always return a NavigationTarget
26     pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Cancelable<Option<NavigationTarget>> {
27         let res = match def {
28             Def::Struct(s) => {
29                 let (file_id, node) = s.source(db)?;
30                 NavigationTarget::from_named(file_id.original_file(db), &*node)
31             }
32             Def::Enum(e) => {
33                 let (file_id, node) = e.source(db)?;
34                 NavigationTarget::from_named(file_id.original_file(db), &*node)
35             }
36             Def::EnumVariant(ev) => {
37                 let (file_id, node) = ev.source(db)?;
38                 NavigationTarget::from_named(file_id.original_file(db), &*node)
39             }
40             Def::Function(f) => {
41                 let (file_id, node) = f.source(db)?;
42                 NavigationTarget::from_named(file_id.original_file(db), &*node)
43             }
44             Def::Module(m) => {
45                 let (file_id, source) = m.definition_source(db)?;
46                 let name = m
47                     .name(db)?
48                     .map(|it| it.to_string().into())
49                     .unwrap_or_else(|| SmolStr::new(""));
50                 match source {
51                     ModuleSource::SourceFile(node) => {
52                         NavigationTarget::from_syntax(file_id, name, node.syntax())
53                     }
54                     ModuleSource::Module(node) => {
55                         NavigationTarget::from_syntax(file_id, name, node.syntax())
56                     }
57                 }
58             }
59             Def::Item => return Ok(None),
60         };
61         Ok(Some(res))
62     }
63
64     fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget {
65         let name = node
66             .name()
67             .map(|it| it.text().clone())
68             .unwrap_or_else(|| SmolStr::new(""));
69         NavigationTarget::from_syntax(file_id, name, node.syntax())
70     }
71
72     fn from_syntax(file_id: FileId, name: SmolStr, node: &SyntaxNode) -> NavigationTarget {
73         NavigationTarget {
74             file_id,
75             name,
76             kind: node.kind(),
77             range: node.range(),
78             ptr: Some(LocalSyntaxPtr::new(node)),
79         }
80     }
81 }