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 | 114 |
1 files changed, 63 insertions, 51 deletions
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index d42af9c38f..effa694aae 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -5,13 +5,14 @@ // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). +use arrayvec::ArrayVec; use hir::{ Field, GenericParam, HasVisibility, Impl, Label, Local, MacroDef, Module, ModuleDef, Name, PathResolution, Semantics, Visibility, }; use syntax::{ ast::{self, AstNode}, - match_ast, SyntaxKind, SyntaxToken, + match_ast, SyntaxKind, SyntaxNode, SyntaxToken, }; use crate::{helpers::try_resolve_derive_input_at, RootDatabase}; @@ -29,60 +30,71 @@ 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![]; + pub fn from_token( + sema: &Semantics<RootDatabase>, + token: &SyntaxToken, + ) -> ArrayVec<Definition, 2> { + let parent = match token.parent() { + Some(parent) => parent, + None => return Default::default(), }; - 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]; - } - } + let attr = parent + .ancestors() + .find_map(ast::TokenTree::cast) + .and_then(|tt| tt.parent_meta()) + .and_then(|meta| meta.parent_attr()); + if let Some(attr) = attr { + try_resolve_derive_input_at(&sema, &attr, &token) + .map(Definition::Macro) + .into_iter() + .collect() + } else { + Self::from_node(sema, &parent) } - 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)] + } + + pub fn from_node(sema: &Semantics<RootDatabase>, node: &SyntaxNode) -> ArrayVec<Definition, 2> { + let mut res = ArrayVec::new(); + (|| { + match_ast! { + match node { + ast::Name(name) => { + match NameClass::classify(&sema, &name)? { + NameClass::Definition(it) | NameClass::ConstReference(it) => res.push(it), + NameClass::PatFieldShorthand { local_def, field_ref } => { + res.push(Definition::Local(local_def)); + res.push(Definition::Field(field_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![], + }, + ast::NameRef(name_ref) => { + match NameRefClass::classify(sema, &name_ref)? { + NameRefClass::Definition(it) => res.push(it), + NameRefClass::FieldShorthand { local_ref, field_ref } => { + res.push(Definition::Local(local_ref)); + res.push(Definition::Field(field_ref)); + } + } + }, + ast::Lifetime(lifetime) => { + let def = 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, + }) + }; + if let Some(def) = def { + res.push(def); + } + }, + _ => (), + } } - } + Some(()) + })(); + res } pub fn module(&self, db: &RootDatabase) -> Option<Module> { |