Make FromSource private

This commit is contained in:
Aleksey Kladov 2020-01-16 16:08:46 +01:00
parent f4eeff2c82
commit 81a45ca1b3
8 changed files with 84 additions and 41 deletions

View file

@ -1,6 +1,6 @@
//! This module defines `AssistCtx` -- the API surface that is exposed to assists. //! This module defines `AssistCtx` -- the API surface that is exposed to assists.
use either::Either; use either::Either;
use hir::{db::HirDatabase, InFile, SourceAnalyzer}; use hir::{db::HirDatabase, InFile, SourceAnalyzer, SourceBinder};
use ra_db::FileRange; use ra_db::FileRange;
use ra_fmt::{leading_indent, reindent}; use ra_fmt::{leading_indent, reindent};
use ra_syntax::{ use ra_syntax::{
@ -142,12 +142,16 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
pub(crate) fn covering_element(&self) -> SyntaxElement { pub(crate) fn covering_element(&self) -> SyntaxElement {
find_covering_element(self.source_file.syntax(), self.frange.range) 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( pub(crate) fn source_analyzer(
&self, &self,
node: &SyntaxNode, node: &SyntaxNode,
offset: Option<TextUnit>, offset: Option<TextUnit>,
) -> SourceAnalyzer { ) -> 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 { pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement {

View file

@ -1,5 +1,5 @@
use format_buf::format; use format_buf::format;
use hir::{db::HirDatabase, FromSource, InFile}; use hir::{db::HirDatabase, InFile};
use join_to_string::join; use join_to_string::join;
use ra_syntax::{ use ra_syntax::{
ast::{ ast::{
@ -136,15 +136,16 @@ fn find_struct_impl(
let module = strukt.syntax().ancestors().find(|node| { let module = strukt.syntax().ancestors().find(|node| {
ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind()) ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind())
})?; })?;
let mut sb = ctx.source_binder();
let struct_ty = { let struct_ty = {
let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() };
hir::Struct::from_source(db, src)?.ty(db) sb.to_def::<hir::Struct, _>(src)?.ty(db)
}; };
let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| { 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 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::<hir::ImplBlock, _>(src)?;
let same_ty = blk.target_ty(db) == struct_ty; let same_ty = blk.target_ty(db) == struct_ty;
let not_trait_impl = blk.target_trait(db).is_none(); let not_trait_impl = blk.target_trait(db).is_none();

View file

@ -20,7 +20,7 @@ use crate::{
MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union,
}; };
pub trait FromSource: Sized { pub(crate) trait FromSource: Sized {
type Ast; type Ast;
fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self>; fn from_source(db: &impl DefDatabase, src: InFile<Self::Ast>) -> Option<Self>;
} }

View file

@ -45,7 +45,6 @@ pub use crate::{
MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias,
TypeParam, Union, VariantDef, TypeParam, Union, VariantDef,
}, },
from_source::FromSource,
has_source::HasSource, has_source::HasSource,
source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
source_binder::SourceBinder, source_binder::SourceBinder,

View file

@ -11,7 +11,7 @@ use hir_def::{
ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ImplId, ModuleId, StaticId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ImplId, ModuleId, StaticId,
StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
}; };
use hir_expand::InFile; use hir_expand::{AstId, InFile, MacroDefId, MacroDefKind};
use ra_prof::profile; use ra_prof::profile;
use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit}; use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, TextUnit};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -62,18 +62,7 @@ impl<DB: HirDatabase> SourceBinder<'_, DB> {
} }
fn to_id<T: ToId>(&mut self, src: InFile<T>) -> Option<T::ID> { fn to_id<T: ToId>(&mut self, src: InFile<T>) -> Option<T::ID> {
let container = self.find_container(src.as_ref().map(|it| it.syntax()))?; T::to_id(self, src)
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()
} }
fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
@ -145,20 +134,47 @@ impl_froms! {
} }
pub trait ToId: Sized + AstNode + 'static { pub trait ToId: Sized + AstNode + 'static {
type ID: Sized + Copy + 'static;
fn to_id<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>)
-> Option<Self::ID>;
}
pub trait ToIdByKey: Sized + AstNode + 'static {
type ID: Sized + Copy + 'static; type ID: Sized + Copy + 'static;
const KEY: Key<Self, Self::ID>; const KEY: Key<Self, Self::ID>;
} }
macro_rules! to_id_impls { impl<T: ToIdByKey> ToId for T {
type ID = <T as ToIdByKey>::ID;
fn to_id<DB: HirDatabase>(
sb: &mut SourceBinder<'_, DB>,
src: InFile<Self>,
) -> Option<Self::ID> {
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)),* ,) => {$( ($(($id:ident, $ast:path, $key:path)),* ,) => {$(
impl ToId for $ast { impl ToIdByKey for $ast {
type ID = $id; type ID = $id;
const KEY: Key<Self, Self::ID> = $key; const KEY: Key<Self, Self::ID> = $key;
} }
)*} )*}
} }
to_id_impls![ to_id_key_impls![
(StructId, ast::StructDef, keys::STRUCT), (StructId, ast::StructDef, keys::STRUCT),
(UnionId, ast::UnionDef, keys::UNION), (UnionId, ast::UnionDef, keys::UNION),
(EnumId, ast::EnumDef, keys::ENUM), (EnumId, ast::EnumDef, keys::ENUM),
@ -171,3 +187,23 @@ to_id_impls![
(StructFieldId, ast::RecordFieldDef, keys::RECORD_FIELD), (StructFieldId, ast::RecordFieldDef, keys::RECORD_FIELD),
(EnumVariantId, ast::EnumVariant, keys::ENUM_VARIANT), (EnumVariantId, ast::EnumVariant, keys::ENUM_VARIANT),
]; ];
// FIXME: use DynMap as well?
impl ToId for ast::MacroCall {
type ID = MacroDefId;
fn to_id<DB: HirDatabase>(
sb: &mut SourceBinder<'_, DB>,
src: InFile<Self>,
) -> Option<Self::ID> {
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 })
}
}

View file

@ -2,7 +2,7 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use hir_expand::InFile; use hir_expand::{InFile, MacroDefId};
use ra_syntax::{ast, AstNode, AstPtr}; use ra_syntax::{ast, AstNode, AstPtr};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -29,6 +29,8 @@ pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new();
pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new(); pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new();
pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
/// equal if they point to exactly the same object. /// equal if they point to exactly the same object.
/// ///

View file

@ -1,6 +1,6 @@
//! FIXME: write short doc here //! FIXME: write short doc here
use hir::{FromSource, ImplBlock}; use hir::{ImplBlock, SourceBinder};
use ra_db::SourceDatabase; use ra_db::SourceDatabase;
use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
@ -12,6 +12,7 @@ pub(crate) fn goto_implementation(
) -> Option<RangeInfo<Vec<NavigationTarget>>> { ) -> Option<RangeInfo<Vec<NavigationTarget>>> {
let parse = db.parse(position.file_id); let parse = db.parse(position.file_id);
let syntax = parse.tree().syntax().clone(); let syntax = parse.tree().syntax().clone();
let mut sb = SourceBinder::new(db);
let src = hir::ModuleSource::from_position(db, position); let src = hir::ModuleSource::from_position(db, position);
let module = hir::Module::from_definition( let module = hir::Module::from_definition(
@ -22,12 +23,12 @@ pub(crate) fn goto_implementation(
if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) {
return Some(RangeInfo::new( return Some(RangeInfo::new(
nominal_def.syntax().text_range(), 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::<ast::TraitDef>(&syntax, position.offset) { } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) {
return Some(RangeInfo::new( return Some(RangeInfo::new(
trait_def.syntax().text_range(), 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( fn impls_for_def(
db: &RootDatabase, sb: &mut SourceBinder<RootDatabase>,
position: FilePosition, position: FilePosition,
node: &ast::NominalDef, node: &ast::NominalDef,
module: hir::Module, module: hir::Module,
@ -43,43 +44,43 @@ fn impls_for_def(
let ty = match node { let ty = match node {
ast::NominalDef::StructDef(def) => { ast::NominalDef::StructDef(def) => {
let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() };
hir::Struct::from_source(db, src)?.ty(db) sb.to_def::<hir::Struct, _>(src)?.ty(sb.db)
} }
ast::NominalDef::EnumDef(def) => { ast::NominalDef::EnumDef(def) => {
let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() };
hir::Enum::from_source(db, src)?.ty(db) sb.to_def::<hir::Enum, _>(src)?.ty(sb.db)
} }
ast::NominalDef::UnionDef(def) => { ast::NominalDef::UnionDef(def) => {
let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() };
hir::Union::from_source(db, src)?.ty(db) sb.to_def::<hir::Union, _>(src)?.ty(sb.db)
} }
}; };
let krate = module.krate(); let krate = module.krate();
let impls = ImplBlock::all_in_crate(db, krate); let impls = ImplBlock::all_in_crate(sb.db, krate);
Some( Some(
impls impls
.into_iter() .into_iter()
.filter(|impl_block| ty.is_equal_for_find_impls(&impl_block.target_ty(db))) .filter(|impl_block| ty.is_equal_for_find_impls(&impl_block.target_ty(sb.db)))
.map(|imp| imp.to_nav(db)) .map(|imp| imp.to_nav(sb.db))
.collect(), .collect(),
) )
} }
fn impls_for_trait( fn impls_for_trait(
db: &RootDatabase, sb: &mut SourceBinder<RootDatabase>,
position: FilePosition, position: FilePosition,
node: &ast::TraitDef, node: &ast::TraitDef,
module: hir::Module, module: hir::Module,
) -> Option<Vec<NavigationTarget>> { ) -> Option<Vec<NavigationTarget>> {
let src = hir::InFile { file_id: position.file_id.into(), value: node.clone() }; 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 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)] #[cfg(test)]

View file

@ -1,6 +1,6 @@
//! Functions that are used to classify an element from its definition or reference. //! 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_prof::profile;
use ra_syntax::{ast, match_ast, AstNode}; use ra_syntax::{ast, match_ast, AstNode};
use test_utils::tested_by; use test_utils::tested_by;
@ -101,7 +101,7 @@ pub(crate) fn classify_name(
}, },
ast::MacroCall(it) => { ast::MacroCall(it) => {
let src = name.with_value(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_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))?; let module = Module::from_definition(sb.db, src.with_value(module_src))?;