245: File items r=matklad a=matklad



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2018-11-27 12:03:14 +00:00
commit 0bc6f5802f
7 changed files with 175 additions and 87 deletions

View file

@ -46,9 +46,12 @@ pub(super) fn completions(
.iter() .iter()
.filter(|(_name, res)| { .filter(|(_name, res)| {
// Don't expose this item // Don't expose this item
match res.import_name { match res.import {
None => true, None => true,
Some(ptr) => !ptr.range().is_subrange(&name_ref.syntax().range()), Some(import) => {
let range = import.range(db, module.source().file_id());
!range.is_subrange(&name_ref.syntax().range())
}
} }
}) })
.map(|(name, _res)| CompletionItem { .map(|(name, _res)| CompletionItem {

View file

@ -7,10 +7,7 @@ use salsa::{self, Database};
use crate::{ use crate::{
db, db,
descriptors::{ descriptors,
DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleTreeQuery,
SubmodulesQuery, ItemMapQuery, InputModuleItemsQuery,
},
symbol_index::SymbolIndex, symbol_index::SymbolIndex,
syntax_ptr::SyntaxPtr, syntax_ptr::SyntaxPtr,
loc2id::{IdMaps, IdDatabase}, loc2id::{IdMaps, IdDatabase},
@ -125,13 +122,15 @@ salsa::database_storage! {
fn file_symbols() for FileSymbolsQuery; fn file_symbols() for FileSymbolsQuery;
fn resolve_syntax_ptr() for ResolveSyntaxPtrQuery; fn resolve_syntax_ptr() for ResolveSyntaxPtrQuery;
} }
impl DescriptorDatabase { impl descriptors::DescriptorDatabase {
fn module_tree() for ModuleTreeQuery; fn module_tree() for descriptors::ModuleTreeQuery;
fn fn_scopes() for FnScopesQuery; fn fn_scopes() for descriptors::FnScopesQuery;
fn _input_module_items() for InputModuleItemsQuery; fn _file_items() for descriptors::FileItemsQuery;
fn _item_map() for ItemMapQuery; fn _file_item() for descriptors::FileItemQuery;
fn _fn_syntax() for FnSyntaxQuery; fn _input_module_items() for descriptors::InputModuleItemsQuery;
fn _submodules() for SubmodulesQuery; fn _item_map() for descriptors::ItemMapQuery;
fn _fn_syntax() for descriptors::FnSyntaxQuery;
fn _submodules() for descriptors::SubmodulesQuery;
} }
} }
} }

View file

@ -6,13 +6,14 @@ use std::sync::Arc;
use ra_syntax::{ use ra_syntax::{
ast::{self, FnDefNode, AstNode}, ast::{self, FnDefNode, AstNode},
TextRange, TextRange, SyntaxNode,
}; };
use crate::{ use crate::{
FileId,
db::SyntaxDatabase, db::SyntaxDatabase,
descriptors::function::{resolve_local_name, FnId, FnScopes}, descriptors::function::{resolve_local_name, FnId, FnScopes},
descriptors::module::{ModuleId, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems}}, descriptors::module::{ModuleId, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems, FileItems}},
input::SourceRootId, input::SourceRootId,
loc2id::IdDatabase, loc2id::IdDatabase,
syntax_ptr::LocalSyntaxPtr, syntax_ptr::LocalSyntaxPtr,
@ -20,6 +21,7 @@ use crate::{
}; };
pub(crate) use self::path::{Path, PathKind}; pub(crate) use self::path::{Path, PathKind};
pub(crate) use self::module::nameres::FileItemId;
salsa::query_group! { salsa::query_group! {
pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase { pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase {
@ -28,6 +30,18 @@ salsa::query_group! {
use fn function::imp::fn_scopes; use fn function::imp::fn_scopes;
} }
fn _file_items(file_id: FileId) -> Arc<FileItems> {
type FileItemsQuery;
storage volatile;
use fn module::nameres::file_items;
}
fn _file_item(file_id: FileId, file_item_id: FileItemId) -> SyntaxNode {
type FileItemQuery;
storage volatile;
use fn module::nameres::file_item;
}
fn _input_module_items(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<InputModuleItems>> { fn _input_module_items(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<InputModuleItems>> {
type InputModuleItemsQuery; type InputModuleItemsQuery;
use fn module::nameres::input_module_items; use fn module::nameres::input_module_items;

View file

@ -17,27 +17,83 @@
use std::{ use std::{
sync::Arc, sync::Arc,
time::Instant, time::Instant,
ops::Index,
}; };
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use ra_syntax::{ use ra_syntax::{
SyntaxNode, SyntaxNodeRef, TextRange,
SmolStr, SyntaxKind::{self, *}, SmolStr, SyntaxKind::{self, *},
ast::{self, ModuleItemOwner} ast::{self, ModuleItemOwner, AstNode}
}; };
use crate::{ use crate::{
Cancelable, Cancelable, FileId,
loc2id::{DefId, DefLoc}, loc2id::{DefId, DefLoc},
descriptors::{ descriptors::{
Path, PathKind, Path, PathKind,
DescriptorDatabase, DescriptorDatabase,
module::{ModuleId, ModuleTree, ModuleSourceNode}, module::{ModuleId, ModuleTree, ModuleSourceNode},
}, },
syntax_ptr::{LocalSyntaxPtr},
input::SourceRootId, input::SourceRootId,
arena::{Arena, Id}
}; };
/// Identifier of item within a specific file. This is stable over reparses, so
/// it's OK to use it as a salsa key/value.
pub(crate) type FileItemId = Id<SyntaxNode>;
/// Maps item's `SyntaxNode`s to `FileItemId` and back.
#[derive(Debug, PartialEq, Eq, Default)]
pub(crate) struct FileItems {
arena: Arena<SyntaxNode>,
}
impl FileItems {
fn alloc(&mut self, item: SyntaxNode) -> FileItemId {
self.arena.alloc(item)
}
fn id_of(&self, item: SyntaxNodeRef) -> FileItemId {
let (id, _item) = self
.arena
.iter()
.find(|(_id, i)| i.borrowed() == item)
.unwrap();
id
}
}
impl Index<FileItemId> for FileItems {
type Output = SyntaxNode;
fn index(&self, idx: FileItemId) -> &SyntaxNode {
&self.arena[idx]
}
}
pub(crate) fn file_items(db: &impl DescriptorDatabase, file_id: FileId) -> Arc<FileItems> {
let source_file = db.file_syntax(file_id);
let source_file = source_file.borrowed();
let mut res = FileItems::default();
source_file
.syntax()
.descendants()
.filter_map(ast::ModuleItem::cast)
.map(|it| it.syntax().owned())
.for_each(|it| {
res.alloc(it);
});
Arc::new(res)
}
pub(crate) fn file_item(
db: &impl DescriptorDatabase,
file_id: FileId,
file_item_id: FileItemId,
) -> SyntaxNode {
db._file_items(file_id)[file_item_id].clone()
}
/// Item map is the result of the name resolution. Item map contains, for each /// Item map is the result of the name resolution. Item map contains, for each
/// module, the set of visible items. /// module, the set of visible items.
#[derive(Default, Debug, PartialEq, Eq)] #[derive(Default, Debug, PartialEq, Eq)]
@ -62,17 +118,44 @@ pub(crate) struct InputModuleItems {
imports: Vec<Import>, imports: Vec<Import>,
} }
#[derive(Debug, PartialEq, Eq)]
struct ModuleItem {
id: FileItemId,
name: SmolStr,
kind: SyntaxKind,
vis: Vis,
}
#[derive(Debug, PartialEq, Eq)]
enum Vis {
// Priv,
Other,
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
struct Import { struct Import {
path: Path, path: Path,
kind: ImportKind, kind: ImportKind,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct NamedImport {
file_item_id: FileItemId,
relative_range: TextRange,
}
impl NamedImport {
pub(crate) fn range(&self, db: &impl DescriptorDatabase, file_id: FileId) -> TextRange {
let syntax = db._file_item(file_id, self.file_item_id);
let offset = syntax.borrowed().range().start();
self.relative_range + offset
}
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
enum ImportKind { enum ImportKind {
Glob, Glob,
// TODO: make offset independent Named(NamedImport),
Named(LocalSyntaxPtr),
} }
pub(crate) fn input_module_items( pub(crate) fn input_module_items(
@ -82,10 +165,11 @@ pub(crate) fn input_module_items(
) -> Cancelable<Arc<InputModuleItems>> { ) -> Cancelable<Arc<InputModuleItems>> {
let module_tree = db._module_tree(source_root)?; let module_tree = db._module_tree(source_root)?;
let source = module_id.source(&module_tree); let source = module_id.source(&module_tree);
let file_items = db._file_items(source.file_id());
let res = match source.resolve(db) { let res = match source.resolve(db) {
ModuleSourceNode::SourceFile(it) => { ModuleSourceNode::SourceFile(it) => {
let items = it.borrowed().items(); let items = it.borrowed().items();
InputModuleItems::new(items) InputModuleItems::new(&file_items, items)
} }
ModuleSourceNode::Module(it) => { ModuleSourceNode::Module(it) => {
let items = it let items = it
@ -93,7 +177,7 @@ pub(crate) fn input_module_items(
.item_list() .item_list()
.into_iter() .into_iter()
.flat_map(|it| it.items()); .flat_map(|it| it.items());
InputModuleItems::new(items) InputModuleItems::new(&file_items, items)
} }
}; };
Ok(Arc::new(res)) Ok(Arc::new(res))
@ -112,7 +196,6 @@ pub(crate) fn item_map(
Ok((id, items)) Ok((id, items))
}) })
.collect::<Cancelable<FxHashMap<_, _>>>()?; .collect::<Cancelable<FxHashMap<_, _>>>()?;
let mut resolver = Resolver { let mut resolver = Resolver {
db: db, db: db,
input: &input, input: &input,
@ -134,8 +217,7 @@ pub(crate) struct Resolution {
/// None for unresolved /// None for unresolved
pub(crate) def_id: Option<DefId>, pub(crate) def_id: Option<DefId>,
/// ident by whitch this is imported into local scope. /// ident by whitch this is imported into local scope.
/// TODO: make this offset-independent. pub(crate) import: Option<NamedImport>,
pub(crate) import_name: Option<LocalSyntaxPtr>,
} }
// #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] // #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -150,55 +232,49 @@ pub(crate) struct Resolution {
// values: Option<T>, // values: Option<T>,
// } // }
#[derive(Debug, PartialEq, Eq)]
struct ModuleItem {
ptr: LocalSyntaxPtr,
name: SmolStr,
kind: SyntaxKind,
vis: Vis,
}
#[derive(Debug, PartialEq, Eq)]
enum Vis {
// Priv,
Other,
}
impl InputModuleItems { impl InputModuleItems {
fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> InputModuleItems { fn new<'a>(
file_items: &FileItems,
items: impl Iterator<Item = ast::ModuleItem<'a>>,
) -> InputModuleItems {
let mut res = InputModuleItems::default(); let mut res = InputModuleItems::default();
for item in items { for item in items {
res.add_item(item); res.add_item(file_items, item);
} }
res res
} }
fn add_item(&mut self, item: ast::ModuleItem) -> Option<()> { fn add_item(&mut self, file_items: &FileItems, item: ast::ModuleItem) -> Option<()> {
match item { match item {
ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
ast::ModuleItem::ImplItem(_) => { ast::ModuleItem::ImplItem(_) => {
// impls don't define items // impls don't define items
} }
ast::ModuleItem::UseItem(it) => self.add_use_item(it), ast::ModuleItem::UseItem(it) => self.add_use_item(file_items, it),
ast::ModuleItem::ExternCrateItem(_) => { ast::ModuleItem::ExternCrateItem(_) => {
// TODO // TODO
} }
ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(file_items, it)?),
ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?), ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(file_items, it)?),
} }
Some(()) Some(())
} }
fn add_use_item(&mut self, item: ast::UseItem) { fn add_use_item(&mut self, file_items: &FileItems, item: ast::UseItem) {
Path::expand_use_item(item, |path, ptr| { let file_item_id = file_items.id_of(item.syntax());
let kind = match ptr { let start_offset = item.syntax().range().start();
Path::expand_use_item(item, |path, range| {
let kind = match range {
None => ImportKind::Glob, None => ImportKind::Glob,
Some(ptr) => ImportKind::Named(ptr), Some(range) => ImportKind::Named(NamedImport {
file_item_id,
relative_range: range - start_offset,
}),
}; };
self.imports.push(Import { kind, path }) self.imports.push(Import { kind, path })
}) })
@ -206,13 +282,13 @@ impl InputModuleItems {
} }
impl ModuleItem { impl ModuleItem {
fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> { fn new<'a>(file_items: &FileItems, item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
let name = item.name()?.text(); let name = item.name()?.text();
let ptr = LocalSyntaxPtr::new(item.syntax());
let kind = item.syntax().kind(); let kind = item.syntax().kind();
let vis = Vis::Other; let vis = Vis::Other;
let id = file_items.id_of(item.syntax());
let res = ModuleItem { let res = ModuleItem {
ptr, id,
name, name,
kind, kind,
vis, vis,
@ -252,12 +328,12 @@ where
for import in input.imports.iter() { for import in input.imports.iter() {
if let Some(name) = import.path.segments.iter().last() { if let Some(name) = import.path.segments.iter().last() {
if let ImportKind::Named(ptr) = import.kind { if let ImportKind::Named(import) = import.kind {
module_items.items.insert( module_items.items.insert(
name.clone(), name.clone(),
Resolution { Resolution {
def_id: None, def_id: None,
import_name: Some(ptr), import: Some(import),
}, },
); );
} }
@ -269,12 +345,14 @@ where
// handle submodules separatelly // handle submodules separatelly
continue; continue;
} }
let ptr = item.ptr.into_global(file_id); let def_loc = DefLoc::Item {
let def_loc = DefLoc::Item { ptr }; file_id,
id: item.id,
};
let def_id = self.db.id_maps().def_id(def_loc); let def_id = self.db.id_maps().def_id(def_loc);
let resolution = Resolution { let resolution = Resolution {
def_id: Some(def_id), def_id: Some(def_id),
import_name: None, import: None,
}; };
module_items.items.insert(item.name.clone(), resolution); module_items.items.insert(item.name.clone(), resolution);
} }
@ -287,7 +365,7 @@ where
let def_id = self.db.id_maps().def_id(def_loc); let def_id = self.db.id_maps().def_id(def_loc);
let resolution = Resolution { let resolution = Resolution {
def_id: Some(def_id), def_id: Some(def_id),
import_name: None, import: None,
}; };
module_items.items.insert(name, resolution); module_items.items.insert(name, resolution);
} }
@ -341,7 +419,7 @@ where
self.update(module_id, |items| { self.update(module_id, |items| {
let res = Resolution { let res = Resolution {
def_id: Some(def_id), def_id: Some(def_id),
import_name: Some(ptr), import: Some(ptr),
}; };
items.items.insert(name.clone(), res); items.items.insert(name.clone(), res);
}) })
@ -452,10 +530,11 @@ mod tests {
let events = db.log_executed(|| { let events = db.log_executed(|| {
db._item_map(source_root).unwrap(); db._item_map(source_root).unwrap();
}); });
// assert!( assert!(
// !format!("{:?}", events).contains("_item_map"), !format!("{:?}", events).contains("_item_map"),
// "{:#?}", events "{:#?}",
// ) events
)
} }
} }
} }

View file

@ -1,6 +1,4 @@
use ra_syntax::{SmolStr, ast, AstNode}; use ra_syntax::{SmolStr, ast, AstNode, TextRange};
use crate::syntax_ptr::LocalSyntaxPtr;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Path { pub(crate) struct Path {
@ -18,10 +16,7 @@ pub(crate) enum PathKind {
impl Path { impl Path {
/// Calls `cb` with all paths, represented by this use item. /// Calls `cb` with all paths, represented by this use item.
pub(crate) fn expand_use_item( pub(crate) fn expand_use_item(item: ast::UseItem, mut cb: impl FnMut(Path, Option<TextRange>)) {
item: ast::UseItem,
mut cb: impl FnMut(Path, Option<LocalSyntaxPtr>),
) {
if let Some(tree) = item.use_tree() { if let Some(tree) = item.use_tree() {
expand_use_tree(None, tree, &mut cb); expand_use_tree(None, tree, &mut cb);
} }
@ -77,7 +72,7 @@ impl Path {
fn expand_use_tree( fn expand_use_tree(
prefix: Option<Path>, prefix: Option<Path>,
tree: ast::UseTree, tree: ast::UseTree,
cb: &mut impl FnMut(Path, Option<LocalSyntaxPtr>), cb: &mut impl FnMut(Path, Option<TextRange>),
) { ) {
if let Some(use_tree_list) = tree.use_tree_list() { if let Some(use_tree_list) = tree.use_tree_list() {
let prefix = match tree.path() { let prefix = match tree.path() {
@ -93,13 +88,13 @@ fn expand_use_tree(
} else { } else {
if let Some(ast_path) = tree.path() { if let Some(ast_path) = tree.path() {
if let Some(path) = convert_path(prefix, ast_path) { if let Some(path) = convert_path(prefix, ast_path) {
let ptr = if tree.has_star() { let range = if tree.has_star() {
None None
} else { } else {
let ptr = LocalSyntaxPtr::new(ast_path.segment().unwrap().syntax()); let range = ast_path.segment().unwrap().syntax().range();
Some(ptr) Some(range)
}; };
cb(path, ptr) cb(path, range)
} }
} }
} }

View file

@ -8,6 +8,8 @@ use std::{
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use crate::{ use crate::{
FileId,
descriptors::FileItemId,
descriptors::module::ModuleId, descriptors::module::ModuleId,
syntax_ptr::SyntaxPtr, syntax_ptr::SyntaxPtr,
input::SourceRootId, input::SourceRootId,
@ -102,7 +104,8 @@ pub(crate) enum DefLoc {
source_root: SourceRootId, source_root: SourceRootId,
}, },
Item { Item {
ptr: SyntaxPtr, file_id: FileId,
id: FileItemId,
}, },
} }

View file

@ -62,11 +62,6 @@ impl LocalSyntaxPtr {
local: self, local: self,
} }
} }
// Seems unfortunate to expose
pub(crate) fn range(self) -> TextRange {
self.range
}
} }
#[test] #[test]