Move hir to a separate crate

This commit is contained in:
Aleksey Kladov 2018-11-28 04:09:44 +03:00
parent 0e4b710af8
commit 59e29aef63
26 changed files with 202 additions and 2432 deletions

View file

@ -8,7 +8,7 @@ use std::{
marker::PhantomData,
};
pub(crate) struct Id<T> {
pub struct Id<T> {
idx: u32,
_ty: PhantomData<fn() -> T>,
}

View file

@ -10,14 +10,14 @@ use crate::{
DefLoc, DefId, FnId,
SourceFileItems, SourceItemId,
query_definitions,
function::{FnScopes},
FnScopes,
module::{ModuleId, ModuleTree, ModuleSource,
nameres::{ItemMap, InputModuleItems}},
};
salsa::query_group! {
pub(crate) trait HirDatabase: SyntaxDatabase
pub trait HirDatabase: SyntaxDatabase
+ AsRef<LocationIntener<DefLoc, DefId>>
+ AsRef<LocationIntener<SourceItemId, FnId>>
{

View file

@ -15,10 +15,10 @@ use crate::{
FnId, HirDatabase, SourceItemId,
};
pub(crate) use self::scope::FnScopes;
pub use self::scope::FnScopes;
impl FnId {
pub(crate) fn get(db: &impl HirDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId {
pub fn get(db: &impl HirDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId {
let file_items = db.file_items(file_id);
let item_id = file_items.id_of(fn_def.syntax());
let item_id = SourceItemId { file_id, item_id };
@ -26,12 +26,12 @@ impl FnId {
}
}
pub(crate) struct Function {
pub struct Function {
fn_id: FnId,
}
impl Function {
pub(crate) fn guess_from_source(
pub fn guess_from_source(
db: &impl HirDatabase,
file_id: FileId,
fn_def: ast::FnDef,
@ -40,7 +40,7 @@ impl Function {
Function { fn_id }
}
pub(crate) fn guess_for_name_ref(
pub fn guess_for_name_ref(
db: &impl HirDatabase,
file_id: FileId,
name_ref: ast::NameRef,
@ -48,7 +48,7 @@ impl Function {
Function::guess_for_node(db, file_id, name_ref.syntax())
}
pub(crate) fn guess_for_bind_pat(
pub fn guess_for_bind_pat(
db: &impl HirDatabase,
file_id: FileId,
bind_pat: ast::BindPat,
@ -66,11 +66,11 @@ impl Function {
Some(res)
}
pub(crate) fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> {
pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> {
db.fn_scopes(self.fn_id)
}
pub(crate) fn signature_info(&self, db: &impl HirDatabase) -> Option<FnSignatureInfo> {
pub fn signature_info(&self, db: &impl HirDatabase) -> Option<FnSignatureInfo> {
let syntax = db.fn_syntax(self.fn_id);
FnSignatureInfo::new(syntax.borrowed())
}

View file

@ -15,7 +15,7 @@ pub(crate) type ScopeId = Id<ScopeData>;
#[derive(Debug, PartialEq, Eq)]
pub struct FnScopes {
pub(crate) self_param: Option<LocalSyntaxPtr>,
pub self_param: Option<LocalSyntaxPtr>,
scopes: Arena<ScopeData>,
scope_for: FxHashMap<LocalSyntaxPtr, ScopeId>,
}
@ -27,13 +27,13 @@ pub struct ScopeEntry {
}
#[derive(Debug, PartialEq, Eq)]
pub(crate) struct ScopeData {
pub struct ScopeData {
parent: Option<ScopeId>,
entries: Vec<ScopeEntry>,
}
impl FnScopes {
pub(crate) fn new(fn_def: ast::FnDef) -> FnScopes {
pub fn new(fn_def: ast::FnDef) -> FnScopes {
let mut scopes = FnScopes {
self_param: fn_def
.param_list()
@ -49,7 +49,7 @@ impl FnScopes {
}
scopes
}
pub(crate) fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] {
&self.scopes[scope].entries
}
pub fn scope_chain<'a>(&'a self, node: SyntaxNodeRef) -> impl Iterator<Item = ScopeId> + 'a {
@ -57,10 +57,7 @@ impl FnScopes {
self.scopes[scope].parent
})
}
pub(crate) fn resolve_local_name<'a>(
&'a self,
name_ref: ast::NameRef,
) -> Option<&'a ScopeEntry> {
pub fn resolve_local_name<'a>(&'a self, name_ref: ast::NameRef) -> Option<&'a ScopeEntry> {
let mut shadowed = FxHashSet::default();
let ret = self
.scope_chain(name_ref.syntax())
@ -138,10 +135,10 @@ impl ScopeEntry {
};
Some(res)
}
pub(crate) fn name(&self) -> &SmolStr {
pub fn name(&self) -> &SmolStr {
&self.name
}
pub(crate) fn ptr(&self) -> LocalSyntaxPtr {
pub fn ptr(&self) -> LocalSyntaxPtr {
self.ptr
}
}

View file

@ -14,7 +14,7 @@ macro_rules! ctry {
};
}
pub(crate) mod db;
pub mod db;
mod query_definitions;
mod function;
mod module;
@ -31,36 +31,36 @@ use crate::{
arena::{Arena, Id},
};
pub(crate) use self::{
pub use self::{
path::{Path, PathKind},
module::{Module, ModuleId, Problem},
module::{Module, ModuleId, Problem, nameres::ItemMap},
function::{Function, FnScopes},
};
pub use self::function::FnSignatureInfo;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct FnId(u32);
pub struct FnId(u32);
ra_db::impl_numeric_id!(FnId);
impl FnId {
pub(crate) fn from_loc(
pub fn from_loc(
db: &impl AsRef<LocationIntener<SourceItemId, FnId>>,
loc: &SourceItemId,
) -> FnId {
db.as_ref().loc2id(loc)
}
pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
pub fn loc(self, db: &impl AsRef<LocationIntener<SourceItemId, FnId>>) -> SourceItemId {
db.as_ref().id2loc(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct DefId(u32);
pub struct DefId(u32);
ra_db::impl_numeric_id!(DefId);
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub(crate) enum DefLoc {
pub enum DefLoc {
Module {
id: ModuleId,
source_root: SourceRootId,
@ -71,24 +71,24 @@ pub(crate) enum DefLoc {
}
impl DefId {
pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
pub fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
db.as_ref().id2loc(self)
}
}
impl DefLoc {
pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
pub fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
db.as_ref().loc2id(&self)
}
}
pub(crate) enum Def {
pub enum Def {
Module(Module),
Item,
}
impl DefId {
pub(crate) fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
let loc = self.loc(db);
let res = match loc {
DefLoc::Module { id, source_root } => {
@ -106,14 +106,14 @@ impl DefId {
pub(crate) type SourceFileItemId = Id<SyntaxNode>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct SourceItemId {
pub struct SourceItemId {
file_id: FileId,
item_id: SourceFileItemId,
}
/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
#[derive(Debug, PartialEq, Eq, Default)]
pub(crate) struct SourceFileItems {
pub struct SourceFileItems {
arena: Arena<SyntaxNode>,
}
@ -121,7 +121,7 @@ impl SourceFileItems {
fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
self.arena.alloc(item)
}
fn id_of(&self, item: SyntaxNodeRef) -> SourceFileItemId {
pub fn id_of(&self, item: SyntaxNodeRef) -> SourceFileItemId {
let (id, _item) = self
.arena
.iter()

View file

@ -18,7 +18,7 @@ use super::{
};
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
pub(crate) enum Submodule {
pub enum Submodule {
Declaration(SmolStr),
Definition(SmolStr, ModuleSource),
}

View file

@ -18,15 +18,16 @@ use crate::{
arena::{Arena, Id},
};
pub(crate) use self::nameres::ModuleScope;
pub use self::nameres::ModuleScope;
/// `Module` is API entry point to get all the information
/// about a particular module.
#[derive(Debug, Clone)]
pub(crate) struct Module {
pub struct Module {
tree: Arc<ModuleTree>,
source_root_id: SourceRootId,
module_id: ModuleId,
//TODO: make private
pub module_id: ModuleId,
}
impl Module {
@ -145,17 +146,13 @@ impl Module {
}
/// Returns a `ModuleScope`: a set of items, visible in this module.
pub(crate) fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> {
pub fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> {
let item_map = db.item_map(self.source_root_id)?;
let res = item_map.per_module[&self.module_id].clone();
Ok(res)
}
pub(crate) fn resolve_path(
&self,
db: &impl HirDatabase,
path: Path,
) -> Cancelable<Option<DefId>> {
pub fn resolve_path(&self, db: &impl HirDatabase, path: Path) -> Cancelable<Option<DefId>> {
let mut curr = match path.kind {
PathKind::Crate => self.crate_root(),
PathKind::Self_ | PathKind::Plain => self.clone(),
@ -188,7 +185,7 @@ impl Module {
/// (which can have multiple parents) to the precise world of modules (which
/// always have one parent).
#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct ModuleTree {
pub struct ModuleTree {
mods: Arena<ModuleData>,
links: Arena<LinkData>,
}
@ -214,19 +211,19 @@ impl ModuleTree {
/// `ModuleSource` is the syntax tree element that produced this module:
/// either a file, or an inlinde module.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) enum ModuleSource {
pub enum ModuleSource {
SourceFile(FileId),
Module(SourceItemId),
}
/// An owned syntax node for a module. Unlike `ModuleSource`,
/// this holds onto the AST for the whole file.
pub(crate) enum ModuleSourceNode {
pub enum ModuleSourceNode {
SourceFile(ast::SourceFileNode),
Module(ast::ModuleNode),
}
pub(crate) type ModuleId = Id<ModuleData>;
pub type ModuleId = Id<ModuleData>;
type LinkId = Id<LinkData>;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
@ -308,7 +305,7 @@ impl LinkId {
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub(crate) struct ModuleData {
pub struct ModuleData {
source: ModuleSource,
parent: Option<LinkId>,
children: Vec<LinkId>,
@ -327,21 +324,21 @@ impl ModuleSource {
ModuleSource::Module(id)
}
pub(crate) fn as_file(self) -> Option<FileId> {
pub fn as_file(self) -> Option<FileId> {
match self {
ModuleSource::SourceFile(f) => Some(f),
ModuleSource::Module(..) => None,
}
}
pub(crate) fn file_id(self) -> FileId {
pub fn file_id(self) -> FileId {
match self {
ModuleSource::SourceFile(f) => f,
ModuleSource::Module(source_item_id) => source_item_id.file_id,
}
}
pub(crate) fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode {
pub fn resolve(self, db: &impl HirDatabase) -> ModuleSourceNode {
match self {
ModuleSource::SourceFile(file_id) => {
let syntax = db.source_file(file_id);

View file

@ -38,20 +38,20 @@ use crate::{
/// Item map is the result of the name resolution. Item map contains, for each
/// module, the set of visible items.
#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct ItemMap {
pub(crate) per_module: FxHashMap<ModuleId, ModuleScope>,
pub struct ItemMap {
pub per_module: FxHashMap<ModuleId, ModuleScope>,
}
#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub(crate) struct ModuleScope {
items: FxHashMap<SmolStr, Resolution>,
pub struct ModuleScope {
pub items: FxHashMap<SmolStr, Resolution>,
}
impl ModuleScope {
pub(crate) fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &Resolution)> + 'a {
pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &Resolution)> + 'a {
self.items.iter()
}
pub(crate) fn get(&self, name: &SmolStr) -> Option<&Resolution> {
pub fn get(&self, name: &SmolStr) -> Option<&Resolution> {
self.items.get(name)
}
}
@ -63,7 +63,7 @@ impl ModuleScope {
/// recomputing name res: if `InputModuleItems` are the same, we can avoid
/// running name resolution.
#[derive(Debug, Default, PartialEq, Eq)]
pub(crate) struct InputModuleItems {
pub struct InputModuleItems {
items: Vec<ModuleItem>,
imports: Vec<Import>,
}
@ -89,13 +89,13 @@ struct Import {
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct NamedImport {
file_item_id: SourceFileItemId,
relative_range: TextRange,
pub struct NamedImport {
pub file_item_id: SourceFileItemId,
pub relative_range: TextRange,
}
impl NamedImport {
pub(crate) fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange {
pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange {
let source_item_id = SourceItemId {
file_id,
item_id: self.file_item_id,
@ -115,11 +115,11 @@ enum ImportKind {
/// Resolution is basically `DefId` atm, but it should account for stuff like
/// multiple namespaces, ambiguity and errors.
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Resolution {
pub struct Resolution {
/// None for unresolved
pub(crate) def_id: Option<DefId>,
pub def_id: Option<DefId>,
/// ident by whitch this is imported into local scope.
pub(crate) import: Option<NamedImport>,
pub import: Option<NamedImport>,
}
// #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -336,109 +336,3 @@ where
f(module_items)
}
}
#[cfg(test)]
mod tests {
use ra_db::FilesDatabase;
use crate::{
AnalysisChange,
mock_analysis::{MockAnalysis, analysis_and_position},
hir::{self, HirDatabase},
};
use super::*;
fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
let (analysis, pos) = analysis_and_position(fixture);
let db = analysis.imp.db;
let source_root = db.file_source_root(pos.file_id);
let descr = hir::Module::guess_from_position(&*db, pos)
.unwrap()
.unwrap();
let module_id = descr.module_id;
(db.item_map(source_root).unwrap(), module_id)
}
#[test]
fn test_item_map() {
let (item_map, module_id) = item_map(
"
//- /lib.rs
mod foo;
use crate::foo::bar::Baz;
<|>
//- /foo/mod.rs
pub mod bar;
//- /foo/bar.rs
pub struct Baz;
",
);
let name = SmolStr::from("Baz");
let resolution = &item_map.per_module[&module_id].items[&name];
assert!(resolution.def_id.is_some());
}
#[test]
fn typing_inside_a_function_should_not_invalidate_item_map() {
let mock_analysis = MockAnalysis::with_files(
"
//- /lib.rs
mod foo;
use crate::foo::bar::Baz;
fn foo() -> i32 {
1 + 1
}
//- /foo/mod.rs
pub mod bar;
//- /foo/bar.rs
pub struct Baz;
",
);
let file_id = mock_analysis.id_of("/lib.rs");
let mut host = mock_analysis.analysis_host();
let source_root = host.analysis().imp.db.file_source_root(file_id);
{
let db = host.analysis().imp.db;
let events = db.log_executed(|| {
db.item_map(source_root).unwrap();
});
assert!(format!("{:?}", events).contains("item_map"))
}
let mut change = AnalysisChange::new();
change.change_file(
file_id,
"
mod foo;
use crate::foo::bar::Baz;
fn foo() -> i32 { 92 }
"
.to_string(),
);
host.apply_change(change);
{
let db = host.analysis().imp.db;
let events = db.log_executed(|| {
db.item_map(source_root).unwrap();
});
assert!(
!format!("{:?}", events).contains("_item_map"),
"{:#?}",
events
)
}
}
}

View file

@ -1,13 +1,13 @@
use ra_syntax::{SmolStr, ast, AstNode, TextRange};
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Path {
pub(crate) kind: PathKind,
pub(crate) segments: Vec<SmolStr>,
pub struct Path {
pub kind: PathKind,
pub segments: Vec<SmolStr>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PathKind {
pub enum PathKind {
Plain,
Self_,
Super,
@ -16,14 +16,14 @@ pub(crate) enum PathKind {
impl Path {
/// Calls `cb` with all paths, represented by this use item.
pub(crate) fn expand_use_item(item: ast::UseItem, mut cb: impl FnMut(Path, Option<TextRange>)) {
pub fn expand_use_item(item: ast::UseItem, mut cb: impl FnMut(Path, Option<TextRange>)) {
if let Some(tree) = item.use_tree() {
expand_use_tree(None, tree, &mut cb);
}
}
/// Converts an `ast::Path` to `Path`. Works with use trees.
pub(crate) fn from_ast(mut path: ast::Path) -> Option<Path> {
pub fn from_ast(mut path: ast::Path) -> Option<Path> {
let mut kind = PathKind::Plain;
let mut segments = Vec::new();
loop {
@ -64,7 +64,7 @@ impl Path {
}
/// `true` is this path is a single identifier, like `foo`
pub(crate) fn is_ident(&self) -> bool {
pub fn is_ident(&self) -> bool {
self.kind == PathKind::Plain && self.segments.len() == 1
}
}