move input module items to the lower module
This commit is contained in:
parent
3d7f188065
commit
789772e8e5
4 changed files with 211 additions and 204 deletions
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
FnSignature, FnScopes,
|
||||
macros::MacroExpansion,
|
||||
module_tree::{ModuleId, ModuleTree},
|
||||
nameres::{ItemMap, InputModuleItems},
|
||||
nameres::{ItemMap, lower::InputModuleItems},
|
||||
ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks},
|
||||
adt::{StructData, EnumData, EnumVariantData},
|
||||
impl_block::ModuleImplBlocks,
|
||||
|
|
@ -58,7 +58,7 @@ pub trait HirDatabase:
|
|||
#[salsa::invoke(crate::module_tree::Submodule::submodules_query)]
|
||||
fn submodules(&self, source: SourceItemId) -> Arc<Vec<crate::module_tree::Submodule>>;
|
||||
|
||||
#[salsa::invoke(query_definitions::input_module_items)]
|
||||
#[salsa::invoke(crate::nameres::lower::InputModuleItems::input_module_items_query)]
|
||||
fn input_module_items(
|
||||
&self,
|
||||
source_root_id: SourceRootId,
|
||||
|
|
|
|||
|
|
@ -14,23 +14,20 @@
|
|||
//! modifications (that is, typing inside a function should not change IMIs),
|
||||
//! so that the results of name resolution can be preserved unless the module
|
||||
//! structure itself is modified.
|
||||
pub(crate) mod lower;
|
||||
use lower::*;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use ra_syntax::{
|
||||
TextRange,
|
||||
SyntaxKind::{self, *},
|
||||
ast::{self, AstNode}
|
||||
};
|
||||
use ra_db::{SourceRootId, FileId};
|
||||
use ra_syntax::SyntaxKind::*;
|
||||
use ra_db::SourceRootId;
|
||||
|
||||
use crate::{
|
||||
HirFileId,
|
||||
DefId, DefLoc, DefKind,
|
||||
SourceItemId, SourceFileItemId, SourceFileItems,
|
||||
Path, PathKind,
|
||||
HirDatabase, Crate,
|
||||
Name, AsName,
|
||||
Name,
|
||||
module_tree::{ModuleId, ModuleTree},
|
||||
};
|
||||
|
||||
|
|
@ -56,64 +53,6 @@ impl ModuleScope {
|
|||
}
|
||||
}
|
||||
|
||||
/// A set of items and imports declared inside a module, without relation to
|
||||
/// other modules.
|
||||
///
|
||||
/// This sits in-between raw syntax and name resolution and allows us to avoid
|
||||
/// recomputing name res: if two instance of `InputModuleItems` are the same, we
|
||||
/// can avoid redoing name resolution.
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
pub struct InputModuleItems {
|
||||
pub(crate) items: Vec<ModuleItem>,
|
||||
imports: Vec<Import>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(crate) struct ModuleItem {
|
||||
pub(crate) id: SourceItemId,
|
||||
pub(crate) name: Name,
|
||||
kind: SyntaxKind,
|
||||
vis: Vis,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum Vis {
|
||||
// Priv,
|
||||
Other,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct Import {
|
||||
path: Path,
|
||||
kind: ImportKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct NamedImport {
|
||||
pub file_item_id: SourceFileItemId,
|
||||
pub relative_range: TextRange,
|
||||
}
|
||||
|
||||
impl NamedImport {
|
||||
// FIXME: this is only here for one use-case in completion. Seems like a
|
||||
// pretty gross special case.
|
||||
pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange {
|
||||
let source_item_id = SourceItemId {
|
||||
file_id: file_id.into(),
|
||||
item_id: Some(self.file_item_id),
|
||||
};
|
||||
let syntax = db.file_item(source_item_id);
|
||||
let offset = syntax.range().start();
|
||||
self.relative_range + offset
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum ImportKind {
|
||||
Glob,
|
||||
Named(NamedImport),
|
||||
}
|
||||
|
||||
/// `Resolution` is basically `DefId` atm, but it should account for stuff like
|
||||
/// multiple namespaces, ambiguity and errors.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
|
@ -210,86 +149,6 @@ impl<T> PerNs<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl InputModuleItems {
|
||||
pub(crate) fn add_item(
|
||||
&mut self,
|
||||
file_id: HirFileId,
|
||||
file_items: &SourceFileItems,
|
||||
item: &ast::ModuleItem,
|
||||
) -> Option<()> {
|
||||
match item.kind() {
|
||||
ast::ModuleItemKind::StructDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::EnumDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::FnDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::TraitDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::TypeDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::ImplBlock(_) => {
|
||||
// impls don't define items
|
||||
}
|
||||
ast::ModuleItemKind::UseItem(it) => self.add_use_item(file_items, it),
|
||||
ast::ModuleItemKind::ExternCrateItem(_) => {
|
||||
// TODO
|
||||
}
|
||||
ast::ModuleItemKind::ConstDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::StaticDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::Module(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn add_use_item(&mut self, file_items: &SourceFileItems, item: &ast::UseItem) {
|
||||
let file_item_id = file_items.id_of_unchecked(item.syntax());
|
||||
let start_offset = item.syntax().range().start();
|
||||
Path::expand_use_item(item, |path, range| {
|
||||
let kind = match range {
|
||||
None => ImportKind::Glob,
|
||||
Some(range) => ImportKind::Named(NamedImport {
|
||||
file_item_id,
|
||||
relative_range: range - start_offset,
|
||||
}),
|
||||
};
|
||||
self.imports.push(Import { kind, path })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleItem {
|
||||
fn new(
|
||||
file_id: HirFileId,
|
||||
file_items: &SourceFileItems,
|
||||
item: &impl ast::NameOwner,
|
||||
) -> Option<ModuleItem> {
|
||||
let name = item.name()?.as_name();
|
||||
let kind = item.syntax().kind();
|
||||
let vis = Vis::Other;
|
||||
let item_id = Some(file_items.id_of_unchecked(item.syntax()));
|
||||
let id = SourceItemId { file_id, item_id };
|
||||
let res = ModuleItem {
|
||||
id,
|
||||
name,
|
||||
kind,
|
||||
vis,
|
||||
};
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Resolver<'a, DB> {
|
||||
db: &'a DB,
|
||||
input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>,
|
||||
|
|
|
|||
200
crates/ra_hir/src/nameres/lower.rs
Normal file
200
crates/ra_hir/src/nameres/lower.rs
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use ra_syntax::{
|
||||
TextRange, SyntaxKind, AstNode,
|
||||
ast::{self, ModuleItemOwner},
|
||||
};
|
||||
use ra_db::{FileId, SourceRootId};
|
||||
|
||||
use crate::{
|
||||
SourceItemId, SourceFileItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems,
|
||||
HirFileId, MacroCallLoc, AsName,
|
||||
module_tree::ModuleId
|
||||
};
|
||||
/// A set of items and imports declared inside a module, without relation to
|
||||
/// other modules.
|
||||
///
|
||||
/// This sits in-between raw syntax and name resolution and allows us to avoid
|
||||
/// recomputing name res: if two instance of `InputModuleItems` are the same, we
|
||||
/// can avoid redoing name resolution.
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
pub struct InputModuleItems {
|
||||
pub(crate) items: Vec<ModuleItem>,
|
||||
pub(super) imports: Vec<Import>,
|
||||
}
|
||||
|
||||
impl InputModuleItems {
|
||||
pub(crate) fn input_module_items_query(
|
||||
db: &impl HirDatabase,
|
||||
source_root_id: SourceRootId,
|
||||
module_id: ModuleId,
|
||||
) -> Arc<InputModuleItems> {
|
||||
let module_tree = db.module_tree(source_root_id);
|
||||
let source = module_id.source(&module_tree);
|
||||
let file_id = source.file_id;
|
||||
let source = ModuleSource::from_source_item_id(db, source);
|
||||
let file_items = db.file_items(file_id);
|
||||
let fill = |acc: &mut InputModuleItems, items: &mut Iterator<Item = ast::ItemOrMacro>| {
|
||||
for item in items {
|
||||
match item {
|
||||
ast::ItemOrMacro::Item(it) => {
|
||||
acc.add_item(file_id, &file_items, it);
|
||||
}
|
||||
ast::ItemOrMacro::Macro(macro_call) => {
|
||||
let item_id = file_items.id_of_unchecked(macro_call.syntax());
|
||||
let loc = MacroCallLoc {
|
||||
source_root_id,
|
||||
module_id,
|
||||
source_item_id: SourceItemId {
|
||||
file_id,
|
||||
item_id: Some(item_id),
|
||||
},
|
||||
};
|
||||
let id = loc.id(db);
|
||||
let file_id = HirFileId::from(id);
|
||||
let file_items = db.file_items(file_id);
|
||||
//FIXME: expand recursively
|
||||
for item in db.hir_source_file(file_id).items() {
|
||||
acc.add_item(file_id, &file_items, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut res = InputModuleItems::default();
|
||||
match source {
|
||||
ModuleSource::SourceFile(it) => fill(&mut res, &mut it.items_with_macros()),
|
||||
ModuleSource::Module(it) => {
|
||||
if let Some(item_list) = it.item_list() {
|
||||
fill(&mut res, &mut item_list.items_with_macros())
|
||||
}
|
||||
}
|
||||
};
|
||||
Arc::new(res)
|
||||
}
|
||||
|
||||
pub(crate) fn add_item(
|
||||
&mut self,
|
||||
file_id: HirFileId,
|
||||
file_items: &SourceFileItems,
|
||||
item: &ast::ModuleItem,
|
||||
) -> Option<()> {
|
||||
match item.kind() {
|
||||
ast::ModuleItemKind::StructDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::EnumDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::FnDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::TraitDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::TypeDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::ImplBlock(_) => {
|
||||
// impls don't define items
|
||||
}
|
||||
ast::ModuleItemKind::UseItem(it) => self.add_use_item(file_items, it),
|
||||
ast::ModuleItemKind::ExternCrateItem(_) => {
|
||||
// TODO
|
||||
}
|
||||
ast::ModuleItemKind::ConstDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::StaticDef(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
ast::ModuleItemKind::Module(it) => {
|
||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn add_use_item(&mut self, file_items: &SourceFileItems, item: &ast::UseItem) {
|
||||
let file_item_id = file_items.id_of_unchecked(item.syntax());
|
||||
let start_offset = item.syntax().range().start();
|
||||
Path::expand_use_item(item, |path, range| {
|
||||
let kind = match range {
|
||||
None => ImportKind::Glob,
|
||||
Some(range) => ImportKind::Named(NamedImport {
|
||||
file_item_id,
|
||||
relative_range: range - start_offset,
|
||||
}),
|
||||
};
|
||||
self.imports.push(Import { kind, path })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(super) enum Vis {
|
||||
// Priv,
|
||||
Other,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(crate) struct ModuleItem {
|
||||
pub(crate) id: SourceItemId,
|
||||
pub(crate) name: Name,
|
||||
pub(super) kind: SyntaxKind,
|
||||
pub(super) vis: Vis,
|
||||
}
|
||||
|
||||
impl ModuleItem {
|
||||
fn new(
|
||||
file_id: HirFileId,
|
||||
file_items: &SourceFileItems,
|
||||
item: &impl ast::NameOwner,
|
||||
) -> Option<ModuleItem> {
|
||||
let name = item.name()?.as_name();
|
||||
let kind = item.syntax().kind();
|
||||
let vis = Vis::Other;
|
||||
let item_id = Some(file_items.id_of_unchecked(item.syntax()));
|
||||
let id = SourceItemId { file_id, item_id };
|
||||
let res = ModuleItem {
|
||||
id,
|
||||
name,
|
||||
kind,
|
||||
vis,
|
||||
};
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(super) struct Import {
|
||||
pub(super) path: Path,
|
||||
pub(super) kind: ImportKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct NamedImport {
|
||||
pub file_item_id: SourceFileItemId,
|
||||
pub relative_range: TextRange,
|
||||
}
|
||||
|
||||
impl NamedImport {
|
||||
// FIXME: this is only here for one use-case in completion. Seems like a
|
||||
// pretty gross special case.
|
||||
pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange {
|
||||
let source_item_id = SourceItemId {
|
||||
file_id: file_id.into(),
|
||||
item_id: Some(self.file_item_id),
|
||||
};
|
||||
let syntax = db.file_item(source_item_id);
|
||||
let offset = syntax.range().start();
|
||||
self.relative_range + offset
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(super) enum ImportKind {
|
||||
Glob,
|
||||
Named(NamedImport),
|
||||
}
|
||||
|
|
@ -6,16 +6,14 @@ use std::{
|
|||
use rustc_hash::FxHashMap;
|
||||
use ra_syntax::{
|
||||
AstNode, SyntaxNode, TreeArc,
|
||||
ast::{self, ModuleItemOwner}
|
||||
};
|
||||
use ra_db::SourceRootId;
|
||||
|
||||
use crate::{
|
||||
SourceFileItems, SourceItemId, DefId, HirFileId, ModuleSource,
|
||||
MacroCallLoc, FnScopes,
|
||||
SourceFileItems, SourceItemId, DefId, HirFileId,
|
||||
FnScopes,
|
||||
db::HirDatabase,
|
||||
module_tree::ModuleId,
|
||||
nameres::{InputModuleItems, ItemMap, Resolver},
|
||||
nameres::{ItemMap, Resolver},
|
||||
};
|
||||
|
||||
pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> {
|
||||
|
|
@ -43,56 +41,6 @@ pub(super) fn file_item(
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn input_module_items(
|
||||
db: &impl HirDatabase,
|
||||
source_root_id: SourceRootId,
|
||||
module_id: ModuleId,
|
||||
) -> Arc<InputModuleItems> {
|
||||
let module_tree = db.module_tree(source_root_id);
|
||||
let source = module_id.source(&module_tree);
|
||||
let file_id = source.file_id;
|
||||
let source = ModuleSource::from_source_item_id(db, source);
|
||||
let file_items = db.file_items(file_id);
|
||||
let fill = |acc: &mut InputModuleItems, items: &mut Iterator<Item = ast::ItemOrMacro>| {
|
||||
for item in items {
|
||||
match item {
|
||||
ast::ItemOrMacro::Item(it) => {
|
||||
acc.add_item(file_id, &file_items, it);
|
||||
}
|
||||
ast::ItemOrMacro::Macro(macro_call) => {
|
||||
let item_id = file_items.id_of_unchecked(macro_call.syntax());
|
||||
let loc = MacroCallLoc {
|
||||
source_root_id,
|
||||
module_id,
|
||||
source_item_id: SourceItemId {
|
||||
file_id,
|
||||
item_id: Some(item_id),
|
||||
},
|
||||
};
|
||||
let id = loc.id(db);
|
||||
let file_id = HirFileId::from(id);
|
||||
let file_items = db.file_items(file_id);
|
||||
//FIXME: expand recursively
|
||||
for item in db.hir_source_file(file_id).items() {
|
||||
acc.add_item(file_id, &file_items, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut res = InputModuleItems::default();
|
||||
match source {
|
||||
ModuleSource::SourceFile(it) => fill(&mut res, &mut it.items_with_macros()),
|
||||
ModuleSource::Module(it) => {
|
||||
if let Some(item_list) = it.item_list() {
|
||||
fill(&mut res, &mut item_list.items_with_macros())
|
||||
}
|
||||
}
|
||||
};
|
||||
Arc::new(res)
|
||||
}
|
||||
|
||||
pub(super) fn item_map(db: &impl HirDatabase, source_root: SourceRootId) -> Arc<ItemMap> {
|
||||
let start = Instant::now();
|
||||
let module_tree = db.module_tree(source_root);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue