From c0aeb5204c010a11db2015113a7858b517415de1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 18 Jan 2019 16:36:56 +0300 Subject: switched to lowerd module --- crates/ra_hir/src/nameres/lower.rs | 213 +++++++++++++++++++++++++++++++++---- 1 file changed, 193 insertions(+), 20 deletions(-) (limited to 'crates/ra_hir/src/nameres') diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 35bdbafbf..6bca14444 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs @@ -1,10 +1,11 @@ use std::sync::Arc; use ra_syntax::{ - TextRange, SyntaxKind, AstNode, + TextRange, SyntaxKind, AstNode, SourceFile, TreeArc, ast::{self, ModuleItemOwner}, }; -use ra_db::{FileId, SourceRootId}; +use ra_db::{SourceRootId, LocalSyntaxPtr}; +use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; use crate::{ SourceItemId, SourceFileItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, @@ -139,12 +140,12 @@ impl InputModuleItems { 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 { + Path::expand_use_item(item, |path, segment| { + let kind = match segment { None => ImportKind::Glob, - Some(range) => ImportKind::Named(NamedImport { + Some(segment) => ImportKind::Named(NamedImport { file_item_id, - relative_range: range - start_offset, + relative_range: segment.syntax().range() - start_offset, }), }; self.imports.push(Import { kind, path }) @@ -199,22 +200,194 @@ pub struct NamedImport { 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), } + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LoweredImport(RawId); +impl_arena_id!(LoweredImport); + +#[derive(Debug, PartialEq, Eq)] +pub(super) struct ImportData { + pub(super) path: Path, + pub(super) is_glob: bool, +} + +#[derive(Debug, Default, PartialEq, Eq)] +pub struct LoweredModule { + pub(super) items: Vec, + pub(super) imports: Arena, +} + +#[derive(Debug, Default, PartialEq, Eq)] +pub struct ImportSourceMap { + map: ArenaMap, +} + +impl ImportSourceMap { + fn insert(&mut self, import: LoweredImport, segment: &ast::PathSegment) { + self.map + .insert(import, LocalSyntaxPtr::new(segment.syntax())) + } + + pub fn get(&self, source: &ModuleSource, import: LoweredImport) -> TreeArc { + let file = match source { + ModuleSource::SourceFile(file) => &*file, + ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), + }; + + ast::PathSegment::cast(&self.map[import].resolve(file)) + .unwrap() + .to_owned() + } +} + +impl LoweredModule { + pub(crate) fn lower_module_module_query( + db: &impl HirDatabase, + source_root_id: SourceRootId, + module_id: ModuleId, + ) -> Arc { + db.lower_module(source_root_id, module_id).0 + } + + pub(crate) fn lower_module_source_map_query( + db: &impl HirDatabase, + source_root_id: SourceRootId, + module_id: ModuleId, + ) -> Arc { + db.lower_module(source_root_id, module_id).1 + } + + pub(crate) fn lower_module_query( + db: &impl HirDatabase, + source_root_id: SourceRootId, + module_id: ModuleId, + ) -> (Arc, Arc) { + 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 mut source_map = ImportSourceMap::default(); + let mut res = LoweredModule::default(); + match source { + ModuleSource::SourceFile(it) => res.fill( + &mut source_map, + db, + source_root_id, + module_id, + file_id, + &mut it.items_with_macros(), + ), + ModuleSource::Module(it) => { + if let Some(item_list) = it.item_list() { + res.fill( + &mut source_map, + db, + source_root_id, + module_id, + file_id, + &mut item_list.items_with_macros(), + ) + } + } + }; + (Arc::new(res), Arc::new(source_map)) + } + + fn fill( + &mut self, + source_map: &mut ImportSourceMap, + db: &impl HirDatabase, + source_root_id: SourceRootId, + module_id: ModuleId, + file_id: HirFileId, + items: &mut Iterator, + ) { + let file_items = db.file_items(file_id); + + for item in items { + match item { + ast::ItemOrMacro::Item(it) => { + self.add_item(source_map, 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() { + self.add_item(source_map, file_id, &file_items, item); + } + } + } + } + } + + fn add_item( + &mut self, + source_map: &mut ImportSourceMap, + 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(source_map, 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, source_map: &mut ImportSourceMap, item: &ast::UseItem) { + Path::expand_use_item(item, |path, segment| { + let import = self.imports.alloc(ImportData { + path, + is_glob: segment.is_none(), + }); + if let Some(segment) = segment { + source_map.insert(import, segment) + } + }) + } +} -- cgit v1.2.3