From b5b6fb25a60d2ecc3cedffcf9e58da4f48fd355c Mon Sep 17 00:00:00 2001 From: Ekaterina Babshukova Date: Sat, 12 Oct 2019 20:30:53 +0300 Subject: [PATCH] replace trait by a bunch of functions --- crates/ra_hir/src/from_source.rs | 60 +----- crates/ra_ide_api/src/goto_definition.rs | 2 +- crates/ra_ide_api/src/hover.rs | 2 +- crates/ra_ide_api/src/references.rs | 10 +- crates/ra_ide_api/src/references/classify.rs | 196 ++++++++++-------- .../ra_ide_api/src/references/definition.rs | 177 ---------------- .../src/references/name_definition.rs | 104 ++++++++++ .../ra_ide_api/src/references/search_scope.rs | 4 +- crates/ra_ide_api/src/syntax_highlighting.rs | 2 +- 9 files changed, 227 insertions(+), 330 deletions(-) delete mode 100644 crates/ra_ide_api/src/references/definition.rs create mode 100644 crates/ra_ide_api/src/references/name_definition.rs diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 35ffd8fffbe7..a012f33f7b37 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -11,9 +11,8 @@ use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, ids::{AstItemDef, LocationCtx}, name::AsName, - AssocItem, Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, - Module, ModuleDef, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, - VariantDef, + Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module, + ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, }; pub trait FromSource: Sized { @@ -130,61 +129,6 @@ impl FromSource for StructField { } } -impl FromSource for AssocItem { - type Ast = ast::ImplItem; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - macro_rules! def { - ($kind:ident, $ast:ident) => { - $kind::from_source(db, Source { file_id: src.file_id, ast: $ast }) - .and_then(|it| Some(AssocItem::from(it))) - }; - } - - match src.ast { - ast::ImplItem::FnDef(f) => def!(Function, f), - ast::ImplItem::ConstDef(c) => def!(Const, c), - ast::ImplItem::TypeAliasDef(a) => def!(TypeAlias, a), - } - } -} - -// not fully matched -impl FromSource for ModuleDef { - type Ast = ast::ModuleItem; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { - macro_rules! def { - ($kind:ident, $ast:ident) => { - $kind::from_source(db, Source { file_id: src.file_id, ast: $ast }) - .and_then(|it| Some(ModuleDef::from(it))) - }; - } - - match src.ast { - ast::ModuleItem::FnDef(f) => def!(Function, f), - ast::ModuleItem::ConstDef(c) => def!(Const, c), - ast::ModuleItem::TypeAliasDef(a) => def!(TypeAlias, a), - ast::ModuleItem::TraitDef(t) => def!(Trait, t), - ast::ModuleItem::StaticDef(s) => def!(Static, s), - ast::ModuleItem::StructDef(s) => { - let src = Source { file_id: src.file_id, ast: s }; - let s = Struct::from_source(db, src)?; - Some(ModuleDef::Adt(s.into())) - } - ast::ModuleItem::EnumDef(e) => { - let src = Source { file_id: src.file_id, ast: e }; - let e = Enum::from_source(db, src)?; - Some(ModuleDef::Adt(e.into())) - } - ast::ModuleItem::Module(ref m) if !m.has_semi() => { - let src = Source { file_id: src.file_id, ast: ModuleSource::Module(m.clone()) }; - let module = Module::from_definition(db, src)?; - Some(ModuleDef::Module(module)) - } - _ => None, - } - } -} - // FIXME: simplify it impl ModuleSource { pub fn from_position( diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index c35d8da4104b..1b4ad3a597bf 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -57,7 +57,7 @@ pub(crate) fn reference_definition( let name_kind = classify_name_ref(db, file_id, &name_ref).and_then(|d| Some(d.item)); match name_kind { Some(Macro(mac)) => return Exact(NavigationTarget::from_macro_def(db, mac)), - Some(FieldAccess(field)) => return Exact(NavigationTarget::from_field(db, field)), + Some(Field(field)) => return Exact(NavigationTarget::from_field(db, field)), Some(AssocItem(assoc)) => return Exact(NavigationTarget::from_assoc_item(db, assoc)), Some(Def(def)) => match NavigationTarget::from_def(db, def) { Some(nav) => return Exact(nav), diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 189094ae5f56..318708df3df0 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -107,7 +107,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option { + Some(Field(it)) => { let src = it.source(db); if let hir::FieldSource::Named(it) = src.ast { res.extend(hover_text(it.doc_comment_text(), it.short_label())); diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index bba29bc4733a..532cbe371dca 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here mod classify; -mod definition; +mod name_definition; mod rename; mod search_scope; @@ -12,7 +12,7 @@ use crate::{db::RootDatabase, FileId, FilePosition, FileRange, NavigationTarget, pub(crate) use self::{ classify::{classify_name, classify_name_ref}, - definition::{Definition, NameKind}, + name_definition::{NameDefinition, NameKind}, rename::rename, }; @@ -63,7 +63,7 @@ pub(crate) fn find_all_refs( let declaration = match def.item { NameKind::Macro(mac) => NavigationTarget::from_macro_def(db, mac), - NameKind::FieldAccess(field) => NavigationTarget::from_field(db, field), + NameKind::Field(field) => NavigationTarget::from_field(db, field), NameKind::AssocItem(assoc) => NavigationTarget::from_assoc_item(db, assoc), NameKind::Def(def) => NavigationTarget::from_def(db, def)?, NameKind::SelfType(ref ty) => match ty.as_adt() { @@ -84,7 +84,7 @@ fn find_name<'a>( db: &RootDatabase, syntax: &SyntaxNode, position: FilePosition, -) -> Option> { +) -> Option> { if let Some(name) = find_node_at_offset::(&syntax, position.offset) { let def = classify_name(db, position.file_id, &name)?; let range = name.syntax().text_range(); @@ -96,7 +96,7 @@ fn find_name<'a>( Some(RangeInfo::new(range, (name_ref.text().to_string(), def))) } -fn process_definition(db: &RootDatabase, def: Definition, name: String) -> Vec { +fn process_definition(db: &RootDatabase, def: NameDefinition, name: String) -> Vec { let pat = name.as_str(); let scope = def.scope(db).scope; let mut refs = vec![]; diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 0b604a5cf7c9..2ba1cf71ce62 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -1,47 +1,90 @@ -use hir::{ - AssocItem, Either, EnumVariant, FromSource, Module, ModuleDef, ModuleSource, Path, - PathResolution, Source, SourceAnalyzer, StructField, -}; +use hir::{Either, FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; use ra_db::FileId; use ra_syntax::{ast, match_ast, AstNode, AstPtr}; -use super::{definition::HasDefinition, Definition, NameKind}; +use super::{ + name_definition::{from_assoc_item, from_module_def, from_pat, from_struct_field}, + NameDefinition, NameKind, +}; use crate::db::RootDatabase; -use hir::{db::AstDatabase, HirFileId}; - pub(crate) fn classify_name( db: &RootDatabase, file_id: FileId, name: &ast::Name, -) -> Option { +) -> Option { let parent = name.syntax().parent()?; let file_id = file_id.into(); + // FIXME: add ast::MacroCall(it) match_ast! { match parent { ast::BindPat(it) => { - decl_from_pat(db, file_id, AstPtr::new(&it)) + from_pat(db, file_id, AstPtr::new(&it)) }, ast::RecordFieldDef(it) => { - StructField::from_def(db, file_id, it) + let ast = hir::FieldSource::Named(it); + let src = hir::Source { file_id, ast }; + let field = hir::StructField::from_source(db, src)?; + Some(from_struct_field(db, field)) + }, + ast::Module(it) => { + let ast = hir::ModuleSource::Module(it); + let src = hir::Source { file_id, ast }; + let def = hir::Module::from_definition(db, src)?; + Some(from_module_def(db, def.into())) }, - ast::ImplItem(it) => { - AssocItem::from_def(db, file_id, it.clone()).or_else(|| { - match it { - ast::ImplItem::FnDef(f) => ModuleDef::from_def(db, file_id, f.into()), - ast::ImplItem::ConstDef(c) => ModuleDef::from_def(db, file_id, c.into()), - ast::ImplItem::TypeAliasDef(a) => ModuleDef::from_def(db, file_id, a.into()), - } - }) + ast::StructDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::Struct::from_source(db, src)?; + Some(from_module_def(db, def.into())) + }, + ast::EnumDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::Enum::from_source(db, src)?; + Some(from_module_def(db, def.into())) + }, + ast::TraitDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::Trait::from_source(db, src)?; + Some(from_module_def(db, def.into())) + }, + ast::StaticDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::Static::from_source(db, src)?; + Some(from_module_def(db, def.into())) }, ast::EnumVariant(it) => { - let src = hir::Source { file_id, ast: it.clone() }; - let def: ModuleDef = EnumVariant::from_source(db, src)?.into(); - Some(def.definition(db)) + let src = hir::Source { file_id, ast: it }; + let def = hir::EnumVariant::from_source(db, src)?; + Some(from_module_def(db, def.into())) + }, + ast::FnDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::Function::from_source(db, src)?; + if parent.parent().and_then(ast::ItemList::cast).is_some() { + Some(from_assoc_item(db, def.into())) + } else { + Some(from_module_def(db, def.into())) + } + }, + ast::ConstDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::Const::from_source(db, src)?; + if parent.parent().and_then(ast::ItemList::cast).is_some() { + Some(from_assoc_item(db, def.into())) + } else { + Some(from_module_def(db, def.into())) + } }, - ast::ModuleItem(it) => { - ModuleDef::from_def(db, file_id, it) + ast::TypeAliasDef(it) => { + let src = hir::Source { file_id, ast: it }; + let def = hir::TypeAlias::from_source(db, src)?; + if parent.parent().and_then(ast::ItemList::cast).is_some() { + Some(from_assoc_item(db, def.into())) + } else { + Some(from_module_def(db, def.into())) + } }, _ => None, } @@ -52,92 +95,75 @@ pub(crate) fn classify_name_ref( db: &RootDatabase, file_id: FileId, name_ref: &ast::NameRef, -) -> Option { - let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); +) -> Option { + use PathResolution::*; + let parent = name_ref.syntax().parent()?; - match_ast! { - match parent { - ast::MethodCallExpr(it) => { - return AssocItem::from_ref(db, &analyzer, it); - }, - ast::FieldExpr(it) => { - if let Some(field) = analyzer.resolve_field(&it) { - return Some(field.definition(db)); - } - }, - ast::RecordField(it) => { - if let Some(record_lit) = it.syntax().ancestors().find_map(ast::RecordLit::cast) { - let variant_def = analyzer.resolve_record_literal(&record_lit)?; - let hir_path = Path::from_name_ref(name_ref); - let hir_name = hir_path.as_ident()?; - let field = variant_def.field(db, hir_name)?; - return Some(field.definition(db)); - } - }, - _ => (), + let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); + + if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { + let func = analyzer.resolve_method_call(&method_call)?; + return Some(from_assoc_item(db, func.into())); + } + + if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { + if let Some(field) = analyzer.resolve_field(&field_expr) { + return Some(from_struct_field(db, field)); + } + } + + if let Some(record_field) = ast::RecordField::cast(parent.clone()) { + if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) { + let variant_def = analyzer.resolve_record_literal(&record_lit)?; + let hir_path = Path::from_name_ref(name_ref); + let hir_name = hir_path.as_ident()?; + let field = variant_def.field(db, hir_name)?; + return Some(from_struct_field(db, field)); } } let ast = ModuleSource::from_child_node(db, file_id, &parent); let file_id = file_id.into(); + // FIXME: find correct container and visibility for each case let container = Module::from_definition(db, Source { file_id, ast })?; let visibility = None; if let Some(macro_call) = parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) { - if let Some(mac) = analyzer.resolve_macro_call(db, ¯o_call) { - return Some(Definition { item: NameKind::Macro(mac), container, visibility }); + if let Some(macro_def) = analyzer.resolve_macro_call(db, ¯o_call) { + return Some(NameDefinition { + item: NameKind::Macro(macro_def), + container, + visibility, + }); } } - // General case, a path or a local: let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; let resolved = analyzer.resolve_path(db, &path)?; match resolved { - PathResolution::Def(def) => Some(def.definition(db)), - PathResolution::LocalBinding(Either::A(pat)) => decl_from_pat(db, file_id, pat), - PathResolution::LocalBinding(Either::B(par)) => { - Some(Definition { item: NameKind::SelfParam(par), container, visibility }) + Def(def) => Some(from_module_def(db, def)), + AssocItem(item) => Some(from_assoc_item(db, item)), + LocalBinding(Either::A(pat)) => from_pat(db, file_id, pat), + LocalBinding(Either::B(par)) => { + let item = NameKind::SelfParam(par); + Some(NameDefinition { item, container, visibility }) } - PathResolution::GenericParam(par) => { + GenericParam(par) => { // FIXME: get generic param def - Some(Definition { item: NameKind::GenericParam(par), container, visibility }) + let item = NameKind::GenericParam(par); + Some(NameDefinition { item, container, visibility }) } - PathResolution::Macro(def) => { - Some(Definition { item: NameKind::Macro(def), container, visibility }) + Macro(def) => { + let item = NameKind::Macro(def); + Some(NameDefinition { item, container, visibility }) } - PathResolution::SelfType(impl_block) => { + SelfType(impl_block) => { let ty = impl_block.target_ty(db); + let item = NameKind::SelfType(ty); let container = impl_block.module(); - Some(Definition { item: NameKind::SelfType(ty), container, visibility }) + Some(NameDefinition { item, container, visibility }) } - PathResolution::AssocItem(assoc) => Some(assoc.definition(db)), } } - -fn decl_from_pat( - db: &RootDatabase, - file_id: HirFileId, - pat: AstPtr, -) -> Option { - let root = db.parse_or_expand(file_id)?; - // FIXME: use match_ast! - let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { - if let Some(it) = ast::FnDef::cast(node.clone()) { - let src = hir::Source { file_id, ast: it }; - Some(hir::Function::from_source(db, src)?.into()) - } else if let Some(it) = ast::ConstDef::cast(node.clone()) { - let src = hir::Source { file_id, ast: it }; - Some(hir::Const::from_source(db, src)?.into()) - } else if let Some(it) = ast::StaticDef::cast(node.clone()) { - let src = hir::Source { file_id, ast: it }; - Some(hir::Static::from_source(db, src)?.into()) - } else { - None - } - })?; - let item = NameKind::Pat((def, pat)); - let container = def.module(db); - Some(Definition { item, container, visibility: None }) -} diff --git a/crates/ra_ide_api/src/references/definition.rs b/crates/ra_ide_api/src/references/definition.rs deleted file mode 100644 index 65b1f8dd77d3..000000000000 --- a/crates/ra_ide_api/src/references/definition.rs +++ /dev/null @@ -1,177 +0,0 @@ -use hir::{ - db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef, - Module, ModuleDef, SourceAnalyzer, StructField, Ty, VariantDef, -}; -use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr}; - -use crate::db::RootDatabase; - -#[derive(Debug, PartialEq, Eq)] -pub enum NameKind { - Macro(MacroDef), - FieldAccess(StructField), - AssocItem(AssocItem), - Def(ModuleDef), - SelfType(Ty), - Pat((DefWithBody, AstPtr)), - SelfParam(AstPtr), - GenericParam(u32), -} - -#[derive(PartialEq, Eq)] -pub(crate) struct Definition { - pub visibility: Option, - pub container: Module, - pub item: NameKind, -} - -pub(super) trait HasDefinition { - type Def; - type Ref; - - fn definition(self, db: &RootDatabase) -> Definition; - fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option; - fn from_ref( - db: &RootDatabase, - analyzer: &SourceAnalyzer, - refer: Self::Ref, - ) -> Option; -} - -// fn decl_from_pat( -// db: &RootDatabase, -// file_id: HirFileId, -// pat: AstPtr, -// ) -> Option { -// let root = db.parse_or_expand(file_id)?; -// // FIXME: use match_ast! -// let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { -// if let Some(it) = ast::FnDef::cast(node.clone()) { -// let src = hir::Source { file_id, ast: it }; -// Some(hir::Function::from_source(db, src)?.into()) -// } else if let Some(it) = ast::ConstDef::cast(node.clone()) { -// let src = hir::Source { file_id, ast: it }; -// Some(hir::Const::from_source(db, src)?.into()) -// } else if let Some(it) = ast::StaticDef::cast(node.clone()) { -// let src = hir::Source { file_id, ast: it }; -// Some(hir::Static::from_source(db, src)?.into()) -// } else { -// None -// } -// })?; -// let item = NameKind::Pat((def, pat)); -// let container = def.module(db); -// Some(Definition { item, container, visibility: None }) -// } - -impl HasDefinition for StructField { - type Def = ast::RecordFieldDef; - type Ref = ast::FieldExpr; - - fn definition(self, db: &RootDatabase) -> Definition { - let item = NameKind::FieldAccess(self); - let parent = self.parent_def(db); - let container = parent.module(db); - let visibility = match parent { - VariantDef::Struct(s) => s.source(db).ast.visibility(), - VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), - }; - Definition { item, container, visibility } - } - - fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option { - let src = hir::Source { file_id, ast: hir::FieldSource::Named(def) }; - let field = StructField::from_source(db, src)?; - Some(field.definition(db)) - } - - fn from_ref( - db: &RootDatabase, - analyzer: &SourceAnalyzer, - refer: Self::Ref, - ) -> Option { - let field = analyzer.resolve_field(&refer)?; - Some(field.definition(db)) - } -} - -impl HasDefinition for AssocItem { - type Def = ast::ImplItem; - type Ref = ast::MethodCallExpr; - - fn definition(self, db: &RootDatabase) -> Definition { - let item = NameKind::AssocItem(self); - let container = self.module(db); - let visibility = match self { - AssocItem::Function(f) => f.source(db).ast.visibility(), - AssocItem::Const(c) => c.source(db).ast.visibility(), - AssocItem::TypeAlias(a) => a.source(db).ast.visibility(), - }; - Definition { item, container, visibility } - } - - fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option { - if def.syntax().parent().and_then(ast::ItemList::cast).is_none() { - return None; - } - let src = hir::Source { file_id, ast: def }; - let item = AssocItem::from_source(db, src)?; - Some(item.definition(db)) - } - - fn from_ref( - db: &RootDatabase, - analyzer: &SourceAnalyzer, - refer: Self::Ref, - ) -> Option { - let func: AssocItem = analyzer.resolve_method_call(&refer)?.into(); - Some(func.definition(db)) - } -} - -impl HasDefinition for ModuleDef { - type Def = ast::ModuleItem; - type Ref = ast::Path; - - fn definition(self, db: &RootDatabase) -> Definition { - let (container, visibility) = match self { - ModuleDef::Module(it) => { - let container = it.parent(db).or_else(|| Some(it)).unwrap(); - let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility()); - (container, visibility) - } - ModuleDef::EnumVariant(it) => { - let container = it.module(db); - let visibility = it.source(db).ast.parent_enum().visibility(); - (container, visibility) - } - ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()), - ModuleDef::BuiltinType(..) => unreachable!(), - }; - let item = NameKind::Def(self); - Definition { item, container, visibility } - } - - fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option { - let src = hir::Source { file_id, ast: def }; - let def = ModuleDef::from_source(db, src)?; - Some(def.definition(db)) - } - - fn from_ref( - db: &RootDatabase, - analyzer: &SourceAnalyzer, - refer: Self::Ref, - ) -> Option { - None - } -} - -// FIXME: impl HasDefinition for hir::MacroDef diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs new file mode 100644 index 000000000000..19702eba0509 --- /dev/null +++ b/crates/ra_ide_api/src/references/name_definition.rs @@ -0,0 +1,104 @@ +use hir::{ + db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef, + Module, ModuleDef, StructField, Ty, VariantDef, +}; +use ra_syntax::{ast, ast::VisibilityOwner, match_ast, AstNode, AstPtr}; + +use crate::db::RootDatabase; + +#[derive(Debug, PartialEq, Eq)] +pub enum NameKind { + Macro(MacroDef), + Field(StructField), + AssocItem(AssocItem), + Def(ModuleDef), + SelfType(Ty), + Pat((DefWithBody, AstPtr)), + SelfParam(AstPtr), + GenericParam(u32), +} + +#[derive(PartialEq, Eq)] +pub(crate) struct NameDefinition { + pub visibility: Option, + pub container: Module, + pub item: NameKind, +} + +pub(super) fn from_pat( + db: &RootDatabase, + file_id: HirFileId, + pat: AstPtr, +) -> Option { + let root = db.parse_or_expand(file_id)?; + let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { + match_ast! { + match node { + ast::FnDef(it) => { + let src = hir::Source { file_id, ast: it }; + Some(hir::Function::from_source(db, src)?.into()) + }, + ast::ConstDef(it) => { + let src = hir::Source { file_id, ast: it }; + Some(hir::Const::from_source(db, src)?.into()) + }, + ast::StaticDef(it) => { + let src = hir::Source { file_id, ast: it }; + Some(hir::Static::from_source(db, src)?.into()) + }, + _ => None, + } + } + })?; + let item = NameKind::Pat((def, pat)); + let container = def.module(db); + Some(NameDefinition { item, container, visibility: None }) +} + +pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition { + let container = item.module(db); + let visibility = match item { + AssocItem::Function(f) => f.source(db).ast.visibility(), + AssocItem::Const(c) => c.source(db).ast.visibility(), + AssocItem::TypeAlias(a) => a.source(db).ast.visibility(), + }; + let item = NameKind::AssocItem(item); + NameDefinition { item, container, visibility } +} + +pub(super) fn from_struct_field(db: &RootDatabase, field: StructField) -> NameDefinition { + let item = NameKind::Field(field); + let parent = field.parent_def(db); + let container = parent.module(db); + let visibility = match parent { + VariantDef::Struct(s) => s.source(db).ast.visibility(), + VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), + }; + NameDefinition { item, container, visibility } +} + +pub(super) fn from_module_def(db: &RootDatabase, def: ModuleDef) -> NameDefinition { + let item = NameKind::Def(def); + let (container, visibility) = match def { + ModuleDef::Module(it) => { + let container = it.parent(db).or_else(|| Some(it)).unwrap(); + let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility()); + (container, visibility) + } + ModuleDef::EnumVariant(it) => { + let container = it.module(db); + let visibility = it.source(db).ast.parent_enum().visibility(); + (container, visibility) + } + ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()), + ModuleDef::BuiltinType(..) => unreachable!(), + }; + NameDefinition { item, container, visibility } +} diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide_api/src/references/search_scope.rs index 557ee7b57684..346815d31229 100644 --- a/crates/ra_ide_api/src/references/search_scope.rs +++ b/crates/ra_ide_api/src/references/search_scope.rs @@ -4,13 +4,13 @@ use ra_syntax::{AstNode, TextRange}; use crate::db::RootDatabase; -use super::{Definition, NameKind}; +use super::{NameDefinition, NameKind}; pub(crate) struct SearchScope { pub scope: Vec<(FileId, Option)>, } -impl Definition { +impl NameDefinition { pub fn scope(&self, db: &RootDatabase) -> SearchScope { let module_src = self.container.definition_source(db); let file_id = module_src.file_id.original_file(db); diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 28c50102e06d..a27d9f367239 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs @@ -105,7 +105,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec "macro", - Some(FieldAccess(_)) => "field", + Some(Field(_)) => "field", Some(AssocItem(hir::AssocItem::Function(_))) => "function", Some(AssocItem(hir::AssocItem::Const(_))) => "constant", Some(AssocItem(hir::AssocItem::TypeAlias(_))) => "type",