mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 17:28:09 +00:00
Make FromSource private
This commit is contained in:
parent
f4eeff2c82
commit
81a45ca1b3
8 changed files with 84 additions and 41 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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.
|
||||||
///
|
///
|
||||||
|
|
|
@ -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)]
|
||||||
|
@ -210,7 +211,7 @@ mod tests {
|
||||||
"
|
"
|
||||||
//- /lib.rs
|
//- /lib.rs
|
||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
struct Foo<|>;
|
struct Foo<|>;
|
||||||
",
|
",
|
||||||
&["impl IMPL_BLOCK FileId(1) [0; 15)"],
|
&["impl IMPL_BLOCK FileId(1) [0; 15)"],
|
||||||
);
|
);
|
||||||
|
|
|
@ -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))?;
|
||||||
|
|
Loading…
Reference in a new issue