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.rs60
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),