From 81a45ca1b3606d2c328740aa7e2dc989b9e128a5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 16 Jan 2020 16:08:46 +0100 Subject: [PATCH] Make FromSource private --- crates/ra_assists/src/assist_ctx.rs | 8 ++- crates/ra_assists/src/assists/add_new.rs | 7 +-- crates/ra_hir/src/from_source.rs | 2 +- crates/ra_hir/src/lib.rs | 1 - crates/ra_hir/src/source_binder.rs | 68 ++++++++++++++++++------ crates/ra_hir_def/src/keys.rs | 4 +- crates/ra_ide/src/impls.rs | 31 +++++------ crates/ra_ide/src/references/classify.rs | 4 +- 8 files changed, 84 insertions(+), 41 deletions(-) diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 9d533fa0c16..43f0d664b47 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -1,6 +1,6 @@ //! This module defines `AssistCtx` -- the API surface that is exposed to assists. use either::Either; -use hir::{db::HirDatabase, InFile, SourceAnalyzer}; +use hir::{db::HirDatabase, InFile, SourceAnalyzer, SourceBinder}; use ra_db::FileRange; use ra_fmt::{leading_indent, reindent}; use ra_syntax::{ @@ -142,12 +142,16 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> { pub(crate) fn covering_element(&self) -> SyntaxElement { find_covering_element(self.source_file.syntax(), self.frange.range) } + pub(crate) fn source_binder(&self) -> SourceBinder<'a, DB> { + SourceBinder::new(self.db) + } pub(crate) fn source_analyzer( &self, node: &SyntaxNode, offset: Option, ) -> SourceAnalyzer { - SourceAnalyzer::new(self.db, InFile::new(self.frange.file_id.into(), node), offset) + let src = InFile::new(self.frange.file_id.into(), node); + self.source_binder().analyze(src, offset) } pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement { diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs index d148d6e7311..aedcd628636 100644 --- a/crates/ra_assists/src/assists/add_new.rs +++ b/crates/ra_assists/src/assists/add_new.rs @@ -1,5 +1,5 @@ use format_buf::format; -use hir::{db::HirDatabase, FromSource, InFile}; +use hir::{db::HirDatabase, InFile}; use join_to_string::join; use ra_syntax::{ ast::{ @@ -136,15 +136,16 @@ fn find_struct_impl( let module = strukt.syntax().ancestors().find(|node| { ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind()) })?; + let mut sb = ctx.source_binder(); let struct_ty = { let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; - hir::Struct::from_source(db, src)?.ty(db) + sb.to_def::(src)?.ty(db) }; let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| { let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; - let blk = hir::ImplBlock::from_source(db, src)?; + let blk = sb.to_def::(src)?; let same_ty = blk.target_ty(db) == struct_ty; let not_trait_impl = blk.target_trait(db).is_none(); diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 6314be8d4c6..59722eba3f4 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -20,7 +20,7 @@ use crate::{ MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, }; -pub trait FromSource: Sized { +pub(crate) trait FromSource: Sized { type Ast; fn from_source(db: &impl DefDatabase, src: InFile) -> Option; } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index a2350573c7c..11829f42a1a 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -45,7 +45,6 @@ pub use crate::{ MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, }, - from_source::FromSource, has_source::HasSource, source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, source_binder::SourceBinder, diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 00541dbe120..66930e492bc 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -11,7 +11,7 @@ use hir_def::{ ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ImplId, ModuleId, StaticId, StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, }; -use hir_expand::InFile; +use hir_expand::{AstId, InFile, MacroDefId, MacroDefKind}; use ra_prof::profile; use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit}; use rustc_hash::FxHashMap; @@ -62,18 +62,7 @@ impl SourceBinder<'_, DB> { } fn to_id(&mut self, src: InFile) -> Option { - let container = self.find_container(src.as_ref().map(|it| it.syntax()))?; - let db = self.db; - let dyn_map = - &*self.child_by_source_cache.entry(container).or_insert_with(|| match container { - ChildContainer::DefWithBodyId(it) => it.child_by_source(db), - ChildContainer::ModuleId(it) => it.child_by_source(db), - ChildContainer::TraitId(it) => it.child_by_source(db), - ChildContainer::ImplId(it) => it.child_by_source(db), - ChildContainer::EnumId(it) => it.child_by_source(db), - ChildContainer::VariantId(it) => it.child_by_source(db), - }); - dyn_map[T::KEY].get(&src).copied() + T::to_id(self, src) } fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option { @@ -145,20 +134,47 @@ impl_froms! { } pub trait ToId: Sized + AstNode + 'static { + type ID: Sized + Copy + 'static; + fn to_id(sb: &mut SourceBinder<'_, DB>, src: InFile) + -> Option; +} + +pub trait ToIdByKey: Sized + AstNode + 'static { type ID: Sized + Copy + 'static; const KEY: Key; } -macro_rules! to_id_impls { +impl ToId for T { + type ID = ::ID; + fn to_id( + sb: &mut SourceBinder<'_, DB>, + src: InFile, + ) -> Option { + let container = sb.find_container(src.as_ref().map(|it| it.syntax()))?; + let db = sb.db; + let dyn_map = + &*sb.child_by_source_cache.entry(container).or_insert_with(|| match container { + ChildContainer::DefWithBodyId(it) => it.child_by_source(db), + ChildContainer::ModuleId(it) => it.child_by_source(db), + ChildContainer::TraitId(it) => it.child_by_source(db), + ChildContainer::ImplId(it) => it.child_by_source(db), + ChildContainer::EnumId(it) => it.child_by_source(db), + ChildContainer::VariantId(it) => it.child_by_source(db), + }); + dyn_map[T::KEY].get(&src).copied() + } +} + +macro_rules! to_id_key_impls { ($(($id:ident, $ast:path, $key:path)),* ,) => {$( - impl ToId for $ast { + impl ToIdByKey for $ast { type ID = $id; const KEY: Key = $key; } )*} } -to_id_impls![ +to_id_key_impls![ (StructId, ast::StructDef, keys::STRUCT), (UnionId, ast::UnionDef, keys::UNION), (EnumId, ast::EnumDef, keys::ENUM), @@ -171,3 +187,23 @@ to_id_impls![ (StructFieldId, ast::RecordFieldDef, keys::RECORD_FIELD), (EnumVariantId, ast::EnumVariant, keys::ENUM_VARIANT), ]; + +// FIXME: use DynMap as well? +impl ToId for ast::MacroCall { + type ID = MacroDefId; + fn to_id( + sb: &mut SourceBinder<'_, DB>, + src: InFile, + ) -> Option { + let kind = MacroDefKind::Declarative; + + let module_src = ModuleSource::from_child_node(sb.db, src.as_ref().map(|it| it.syntax())); + let module = crate::Module::from_definition(sb.db, InFile::new(src.file_id, module_src))?; + let krate = Some(module.krate().id); + + let ast_id = + Some(AstId::new(src.file_id, sb.db.ast_id_map(src.file_id).ast_id(&src.value))); + + Some(MacroDefId { krate, ast_id, kind }) + } +} diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index d844f7a627c..5913f12b16f 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; -use hir_expand::InFile; +use hir_expand::{InFile, MacroDefId}; use ra_syntax::{ast, AstNode, AstPtr}; use rustc_hash::FxHashMap; @@ -29,6 +29,8 @@ pub const TUPLE_FIELD: Key = Key::new(); pub const RECORD_FIELD: Key = Key::new(); pub const TYPE_PARAM: Key = Key::new(); +pub const MACRO: Key = Key::new(); + /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are /// equal if they point to exactly the same object. /// diff --git a/crates/ra_ide/src/impls.rs b/crates/ra_ide/src/impls.rs index 31195036ea7..bd14a6d135e 100644 --- a/crates/ra_ide/src/impls.rs +++ b/crates/ra_ide/src/impls.rs @@ -1,6 +1,6 @@ //! FIXME: write short doc here -use hir::{FromSource, ImplBlock}; +use hir::{ImplBlock, SourceBinder}; use ra_db::SourceDatabase; use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; @@ -12,6 +12,7 @@ pub(crate) fn goto_implementation( ) -> Option>> { let parse = db.parse(position.file_id); let syntax = parse.tree().syntax().clone(); + let mut sb = SourceBinder::new(db); let src = hir::ModuleSource::from_position(db, position); let module = hir::Module::from_definition( @@ -22,12 +23,12 @@ pub(crate) fn goto_implementation( if let Some(nominal_def) = find_node_at_offset::(&syntax, position.offset) { return Some(RangeInfo::new( nominal_def.syntax().text_range(), - impls_for_def(db, position, &nominal_def, module)?, + impls_for_def(&mut sb, position, &nominal_def, module)?, )); } else if let Some(trait_def) = find_node_at_offset::(&syntax, position.offset) { return Some(RangeInfo::new( trait_def.syntax().text_range(), - impls_for_trait(db, position, &trait_def, module)?, + impls_for_trait(&mut sb, position, &trait_def, module)?, )); } @@ -35,7 +36,7 @@ pub(crate) fn goto_implementation( } fn impls_for_def( - db: &RootDatabase, + sb: &mut SourceBinder, position: FilePosition, node: &ast::NominalDef, module: hir::Module, @@ -43,43 +44,43 @@ fn impls_for_def( let ty = match node { ast::NominalDef::StructDef(def) => { let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; - hir::Struct::from_source(db, src)?.ty(db) + sb.to_def::(src)?.ty(sb.db) } ast::NominalDef::EnumDef(def) => { let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; - hir::Enum::from_source(db, src)?.ty(db) + sb.to_def::(src)?.ty(sb.db) } ast::NominalDef::UnionDef(def) => { let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; - hir::Union::from_source(db, src)?.ty(db) + sb.to_def::(src)?.ty(sb.db) } }; let krate = module.krate(); - let impls = ImplBlock::all_in_crate(db, krate); + let impls = ImplBlock::all_in_crate(sb.db, krate); Some( impls .into_iter() - .filter(|impl_block| ty.is_equal_for_find_impls(&impl_block.target_ty(db))) - .map(|imp| imp.to_nav(db)) + .filter(|impl_block| ty.is_equal_for_find_impls(&impl_block.target_ty(sb.db))) + .map(|imp| imp.to_nav(sb.db)) .collect(), ) } fn impls_for_trait( - db: &RootDatabase, + sb: &mut SourceBinder, position: FilePosition, node: &ast::TraitDef, module: hir::Module, ) -> Option> { let src = hir::InFile { file_id: position.file_id.into(), value: node.clone() }; - let tr = hir::Trait::from_source(db, src)?; + let tr = sb.to_def(src)?; let krate = module.krate(); - let impls = ImplBlock::for_trait(db, krate, tr); + let impls = ImplBlock::for_trait(sb.db, krate, tr); - Some(impls.into_iter().map(|imp| imp.to_nav(db)).collect()) + Some(impls.into_iter().map(|imp| imp.to_nav(sb.db)).collect()) } #[cfg(test)] @@ -210,7 +211,7 @@ mod tests { " //- /lib.rs #[derive(Copy)] - struct Foo<|>; + struct Foo<|>; ", &["impl IMPL_BLOCK FileId(1) [0; 15)"], ); diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index 4a6e11e27ec..dcffc3df223 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs @@ -1,6 +1,6 @@ //! Functions that are used to classify an element from its definition or reference. -use hir::{FromSource, InFile, Module, ModuleSource, PathResolution, SourceBinder}; +use hir::{InFile, Module, ModuleSource, PathResolution, SourceBinder}; use ra_prof::profile; use ra_syntax::{ast, match_ast, AstNode}; use test_utils::tested_by; @@ -101,7 +101,7 @@ pub(crate) fn classify_name( }, ast::MacroCall(it) => { let src = name.with_value(it); - let def = hir::MacroDef::from_source(sb.db, src.clone())?; + let def = sb.to_def(src.clone())?; let module_src = ModuleSource::from_child_node(sb.db, src.as_ref().map(|it| it.syntax())); let module = Module::from_definition(sb.db, src.with_value(module_src))?;