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.
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<TextUnit>,
) -> 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 {

View file

@ -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::<hir::Struct, _>(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::<hir::ImplBlock, _>(src)?;
let same_ty = blk.target_ty(db) == struct_ty;
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,
};
pub trait FromSource: Sized {
pub(crate) trait FromSource: Sized {
type Ast;
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,
TypeParam, Union, VariantDef,
},
from_source::FromSource,
has_source::HasSource,
source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
source_binder::SourceBinder,

View file

@ -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<DB: HirDatabase> SourceBinder<'_, DB> {
}
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()))?;
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<ChildContainer> {
@ -145,20 +134,47 @@ impl_froms! {
}
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;
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)),* ,) => {$(
impl ToId for $ast {
impl ToIdByKey for $ast {
type ID = $id;
const KEY: Key<Self, Self::ID> = $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<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 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<ast::TupleFieldDef, 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 MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
/// equal if they point to exactly the same object.
///

View file

@ -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<RangeInfo<Vec<NavigationTarget>>> {
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::<ast::NominalDef>(&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::<ast::TraitDef>(&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<RootDatabase>,
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::<hir::Struct, _>(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::<hir::Enum, _>(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::<hir::Union, _>(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<RootDatabase>,
position: FilePosition,
node: &ast::TraitDef,
module: hir::Module,
) -> Option<Vec<NavigationTarget>> {
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)"],
);

View file

@ -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))?;