Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide_db/src/defs.rs')
| -rw-r--r-- | crates/ide_db/src/defs.rs | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index 719f424fd2..d42af9c38f 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -11,10 +11,10 @@ use hir::{ }; use syntax::{ ast::{self, AstNode}, - match_ast, SyntaxKind, + match_ast, SyntaxKind, SyntaxToken, }; -use crate::RootDatabase; +use crate::{helpers::try_resolve_derive_input_at, RootDatabase}; // FIXME: a more precise name would probably be `Symbol`? #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] @@ -29,6 +29,62 @@ pub enum Definition { } impl Definition { + pub fn from_node(sema: &Semantics<RootDatabase>, token: &SyntaxToken) -> Vec<Definition> { + let node = if let Some(x) = token.parent() { + x + } else { + return vec![]; + }; + if token.kind() != SyntaxKind::COMMENT { + if let Some(attr) = token.ancestors().find_map(ast::Attr::cast) { + // derives + let def = try_resolve_derive_input_at(&sema, &attr, &token).map(Definition::Macro); + if let Some(def) = def { + return vec![def]; + } + } + } + match_ast! { + match node { + ast::Name(name) => { + let class = if let Some(x) = NameClass::classify(&sema, &name) { + x + } else { + return vec![]; + }; + match class { + NameClass::Definition(it) | NameClass::ConstReference(it) => vec![it], + NameClass::PatFieldShorthand { local_def, field_ref } => vec![Definition::Local(local_def), Definition::Field(field_ref)], + } + }, + ast::NameRef(name_ref) => { + let class = if let Some(x) = NameRefClass::classify(sema, &name_ref) { + x + } else { + return vec![]; + }; + match class { + NameRefClass::Definition(def) => vec![def], + NameRefClass::FieldShorthand { local_ref, field_ref } => { + vec![Definition::Field(field_ref), Definition::Local(local_ref)] + } + } + }, + ast::Lifetime(lifetime) => { + (if let Some(x) = NameClass::classify_lifetime(&sema, &lifetime) { + NameClass::defined(x) + } else { + NameRefClass::classify_lifetime(&sema, &lifetime).and_then(|class| match class { + NameRefClass::Definition(it) => Some(it), + _ => None, + }) + }).into_iter().collect() + }, + _ => vec![], + } + } + } + pub fn module(&self, db: &RootDatabase) -> Option<Module> { match self { Definition::Macro(it) => it.module(db), |