From 83f780eabfdaf37cb50c10c79af87506f2cc2afe Mon Sep 17 00:00:00 2001 From: Ekaterina Babshukova Date: Thu, 3 Oct 2019 06:08:44 +0300 Subject: return Declaration from classify_name --- crates/ra_ide_api/src/name_kind.rs | 93 +++++++++++++++++++++++-------------- crates/ra_ide_api/src/references.rs | 2 +- 2 files changed, 59 insertions(+), 36 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/name_kind.rs b/crates/ra_ide_api/src/name_kind.rs index 0effeb8a1..5dc6b1a13 100644 --- a/crates/ra_ide_api/src/name_kind.rs +++ b/crates/ra_ide_api/src/name_kind.rs @@ -1,13 +1,19 @@ //! FIXME: write short doc here -use hir::{Either, FromSource}; +use hir::{Either, FromSource, HasSource}; use ra_db::FileId; -use ra_syntax::{ast, AstNode, AstPtr}; +use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr}; use test_utils::tested_by; use crate::db::RootDatabase; -pub enum NameKind { +pub(crate) struct Declaration { + visibility: Option, + container: hir::ModuleSource, + pub item: NameKind, +} + +pub(crate) enum NameKind { Macro(hir::MacroDef), FieldAccess(hir::StructField), AssocItem(hir::AssocItem), @@ -96,7 +102,7 @@ pub(crate) fn classify_name( db: &RootDatabase, file_id: FileId, name: &ast::Name, -) -> Option { +) -> Option { use NameKind::*; let parent = name.syntax().parent()?; @@ -105,89 +111,106 @@ pub(crate) fn classify_name( macro_rules! match_ast { (match $node:ident { $( ast::$ast:ident($it:ident) => $res:block, )* - _ => $catch_all:expr, + _ => $catch_all:block, }) => {{ $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )* - { $catch_all } + $catch_all }}; } + let container = parent.ancestors().find_map(|n| { + match_ast! { + match n { + ast::Module(it) => { Some(hir::ModuleSource::Module(it)) }, + ast::SourceFile(it) => { Some(hir::ModuleSource::SourceFile(it)) }, + _ => { None }, + } + } + })?; + // FIXME: add ast::MacroCall(it) - match_ast! { + let (item, visibility) = match_ast! { match parent { ast::BindPat(it) => { let pat = AstPtr::new(&it); - Some(Pat(pat)) + (Pat(pat), None) }, ast::RecordFieldDef(it) => { let src = hir::Source { file_id, ast: hir::FieldSource::Named(it) }; let field = hir::StructField::from_source(db, src)?; - Some(FieldAccess(field)) + let visibility = match field.parent_def(db) { + hir::VariantDef::Struct(s) => s.source(db).ast.visibility(), + hir::VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), + }; + (FieldAccess(field), visibility) }, ast::FnDef(it) => { if parent.parent().and_then(ast::ItemList::cast).is_some() { - let src = hir::Source { file_id, ast: ast::ImplItem::from(it) }; + let src = hir::Source { file_id, ast: ast::ImplItem::from(it.clone()) }; let item = hir::AssocItem::from_source(db, src)?; - Some(AssocItem(item)) + (AssocItem(item), it.visibility()) } else { - let src = hir::Source { file_id, ast: it }; + let src = hir::Source { file_id, ast: it.clone() }; let def = hir::Function::from_source(db, src)?; - Some(Def(def.into())) + (Def(def.into()), it.visibility()) } }, ast::ConstDef(it) => { if parent.parent().and_then(ast::ItemList::cast).is_some() { - let src = hir::Source { file_id, ast: ast::ImplItem::from(it) }; + let src = hir::Source { file_id, ast: ast::ImplItem::from(it.clone()) }; let item = hir::AssocItem::from_source(db, src)?; - Some(AssocItem(item)) + (AssocItem(item), it.visibility()) } else { - let src = hir::Source { file_id, ast: it }; + let src = hir::Source { file_id, ast: it.clone() }; let def = hir::Const::from_source(db, src)?; - Some(Def(def.into())) + (Def(def.into()), it.visibility()) } }, ast::TypeAliasDef(it) => { if parent.parent().and_then(ast::ItemList::cast).is_some() { - let src = hir::Source { file_id, ast: ast::ImplItem::from(it) }; + let src = hir::Source { file_id, ast: ast::ImplItem::from(it.clone()) }; let item = hir::AssocItem::from_source(db, src)?; - Some(AssocItem(item)) + (AssocItem(item), it.visibility()) } else { - let src = hir::Source { file_id, ast: it }; + let src = hir::Source { file_id, ast: it.clone() }; let def = hir::TypeAlias::from_source(db, src)?; - Some(Def(def.into())) + (Def(def.into()), it.visibility()) } }, ast::Module(it) => { - let src = hir::Source { file_id, ast: hir::ModuleSource::Module(it) }; + let src = hir::Source { file_id, ast: hir::ModuleSource::Module(it.clone()) }; let def = hir::Module::from_definition(db, src)?; - Some(Def(def.into())) + (Def(def.into()), it.visibility()) }, ast::StructDef(it) => { - let src = hir::Source { file_id, ast: it }; + let src = hir::Source { file_id, ast: it.clone() }; let def = hir::Struct::from_source(db, src)?; - Some(Def(def.into())) + (Def(def.into()), it.visibility()) }, ast::EnumDef(it) => { - let src = hir::Source { file_id, ast: it }; + let src = hir::Source { file_id, ast: it.clone() }; let def = hir::Enum::from_source(db, src)?; - Some(Def(def.into())) + (Def(def.into()), it.visibility()) }, ast::TraitDef(it) => { - let src = hir::Source { file_id, ast: it }; + let src = hir::Source { file_id, ast: it.clone() }; let def = hir::Trait::from_source(db, src)?; - Some(Def(def.into())) + (Def(def.into()), it.visibility()) }, ast::StaticDef(it) => { - let src = hir::Source { file_id, ast: it }; + let src = hir::Source { file_id, ast: it.clone() }; let def = hir::Static::from_source(db, src)?; - Some(Def(def.into())) + (Def(def.into()), it.visibility()) }, ast::EnumVariant(it) => { - let src = hir::Source { file_id, ast: it }; + let src = hir::Source { file_id, ast: it.clone() }; let def = hir::EnumVariant::from_source(db, src)?; - Some(Def(def.into())) + (Def(def.into()), it.parent_enum().visibility()) + }, + _ => { + return None; }, - _ => None, } - } + }; + Some(Declaration { item, container, visibility }) } diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 6a8407c51..6777aa5f3 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs @@ -92,7 +92,7 @@ pub(crate) fn find_all_refs( ) -> Option> { if let Some(name) = find_node_at_offset::(&syntax, position.offset) { let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name.syntax(), None); - let name_kind = classify_name(db, position.file_id, &name)?; + let name_kind = classify_name(db, position.file_id, &name)?.item; let range = name.syntax().text_range(); return Some(RangeInfo::new(range, (analyzer, name_kind))); } -- cgit v1.2.3