mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 13:25:09 +00:00
ModuleTreeDescriptor
This commit is contained in:
parent
d59413c895
commit
58674dc3c4
8 changed files with 306 additions and 138 deletions
|
@ -68,22 +68,32 @@ pub(crate) fn file_set(ctx: QueryCtx) -> Arc<(Vec<FileId>, FileResolverImp)> {
|
||||||
pub(crate) use self::queries::file_syntax;
|
pub(crate) use self::queries::file_syntax;
|
||||||
|
|
||||||
mod queries {
|
mod queries {
|
||||||
|
use std::sync::Arc;
|
||||||
use libsyntax2::File;
|
use libsyntax2::File;
|
||||||
|
use libeditor::LineIndex;
|
||||||
use {FileId};
|
use {FileId};
|
||||||
use super::{Query, QueryCtx, QueryRegistry, file_text};
|
use super::{Query, QueryCtx, QueryRegistry, file_text};
|
||||||
|
|
||||||
pub(crate) fn register_queries(reg: &mut QueryRegistry) {
|
pub(crate) fn register_queries(reg: &mut QueryRegistry) {
|
||||||
reg.add(FILE_SYNTAX, "FILE_SYNTAX")
|
reg.add(FILE_SYNTAX, "FILE_SYNTAX");
|
||||||
|
reg.add(FILE_LINES, "FILE_LINES");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn file_syntax(ctx: QueryCtx, file_id: FileId) -> File {
|
pub(crate) fn file_syntax(ctx: QueryCtx, file_id: FileId) -> File {
|
||||||
(&*ctx.get(FILE_SYNTAX, file_id)).clone()
|
(&*ctx.get(FILE_SYNTAX, file_id)).clone()
|
||||||
}
|
}
|
||||||
|
pub(crate) fn file_lines(ctx: QueryCtx, file_id: FileId) -> Arc<LineIndex> {
|
||||||
|
ctx.get(FILE_LINES, file_id)
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) const FILE_SYNTAX: Query<FileId, File> = Query(16, |ctx, file_id: &FileId| {
|
pub(super) const FILE_SYNTAX: Query<FileId, File> = Query(16, |ctx, file_id: &FileId| {
|
||||||
let text = file_text(ctx, *file_id);
|
let text = file_text(ctx, *file_id);
|
||||||
File::parse(&*text)
|
File::parse(&*text)
|
||||||
});
|
});
|
||||||
|
pub(super) const FILE_LINES: Query<FileId, LineIndex> = Query(17, |ctx, file_id: &FileId| {
|
||||||
|
let text = file_text(ctx, *file_id);
|
||||||
|
LineIndex::new(&*text)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QueryRegistry {
|
impl QueryRegistry {
|
||||||
|
|
217
crates/libanalysis/src/descriptors.rs
Normal file
217
crates/libanalysis/src/descriptors.rs
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
};
|
||||||
|
use relative_path::RelativePathBuf;
|
||||||
|
use libsyntax2::{
|
||||||
|
SmolStr,
|
||||||
|
ast::{self, NameOwner},
|
||||||
|
};
|
||||||
|
use {
|
||||||
|
FileId,
|
||||||
|
imp::FileResolverImp,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Hash)]
|
||||||
|
pub struct ModuleDescriptor {
|
||||||
|
pub submodules: Vec<Submodule>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModuleDescriptor {
|
||||||
|
pub fn new(root: ast::Root) -> ModuleDescriptor {
|
||||||
|
let submodules = modules(root)
|
||||||
|
.map(|(name, _)| Submodule { name })
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
ModuleDescriptor { submodules } }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn modules<'a>(root: ast::Root<'a>) -> impl Iterator<Item=(SmolStr, ast::Module<'a>)> {
|
||||||
|
root
|
||||||
|
.modules()
|
||||||
|
.filter_map(|module| {
|
||||||
|
let name = module.name()?.text();
|
||||||
|
if !module.has_semi() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some((name, module))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
|
||||||
|
pub struct Submodule {
|
||||||
|
pub name: SmolStr,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Hash)]
|
||||||
|
pub(crate) struct ModuleTreeDescriptor {
|
||||||
|
nodes: Vec<NodeData>,
|
||||||
|
links: Vec<LinkData>,
|
||||||
|
file_id2node: BTreeMap<FileId, Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
struct Node(usize);
|
||||||
|
#[derive(Hash)]
|
||||||
|
struct NodeData {
|
||||||
|
file_id: FileId,
|
||||||
|
links: Vec<Link>,
|
||||||
|
parents: Vec<Link>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub(crate) struct Link(usize);
|
||||||
|
#[derive(Hash)]
|
||||||
|
struct LinkData {
|
||||||
|
owner: Node,
|
||||||
|
name: SmolStr,
|
||||||
|
points_to: Vec<Node>,
|
||||||
|
problem: Option<Problem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Hash)]
|
||||||
|
pub enum Problem {
|
||||||
|
UnresolvedModule {
|
||||||
|
candidate: RelativePathBuf,
|
||||||
|
},
|
||||||
|
NotDirOwner {
|
||||||
|
move_to: RelativePathBuf,
|
||||||
|
candidate: RelativePathBuf,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModuleTreeDescriptor {
|
||||||
|
pub(crate) fn new<'a>(
|
||||||
|
files: impl Iterator<Item=(FileId, &'a ModuleDescriptor)> + Clone,
|
||||||
|
file_resolver: &FileResolverImp,
|
||||||
|
) -> ModuleTreeDescriptor {
|
||||||
|
let mut file_id2node = BTreeMap::new();
|
||||||
|
let mut nodes: Vec<NodeData> = files.clone().enumerate()
|
||||||
|
.map(|(idx, (file_id, _))| {
|
||||||
|
file_id2node.insert(file_id, Node(idx));
|
||||||
|
NodeData {
|
||||||
|
file_id,
|
||||||
|
links: Vec::new(),
|
||||||
|
parents: Vec::new(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let mut links = Vec::new();
|
||||||
|
|
||||||
|
for (idx, (file_id, descr)) in files.enumerate() {
|
||||||
|
let owner = Node(idx);
|
||||||
|
for sub in descr.submodules.iter() {
|
||||||
|
let link = Link(links.len());
|
||||||
|
nodes[owner.0].links.push(link);
|
||||||
|
let (points_to, problem) = resolve_submodule(file_id, &sub.name, file_resolver);
|
||||||
|
let points_to = points_to
|
||||||
|
.into_iter()
|
||||||
|
.map(|file_id| {
|
||||||
|
let node = file_id2node[&file_id];
|
||||||
|
nodes[node.0].parents.push(link);
|
||||||
|
node
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
links.push(LinkData {
|
||||||
|
owner,
|
||||||
|
name: sub.name.clone(),
|
||||||
|
points_to,
|
||||||
|
problem,
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ModuleTreeDescriptor {
|
||||||
|
nodes, links, file_id2node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parent_modules(&self, file_id: FileId) -> Vec<Link> {
|
||||||
|
let node = self.file_id2node[&file_id];
|
||||||
|
self.node(node)
|
||||||
|
.parents
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
pub(crate) fn child_module_by_name(&self, file_id: FileId, name: &str) -> Vec<FileId> {
|
||||||
|
let node = self.file_id2node[&file_id];
|
||||||
|
self.node(node)
|
||||||
|
.links
|
||||||
|
.iter()
|
||||||
|
.filter(|it| it.name(self) == name)
|
||||||
|
.map(|link| link.owner(self))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
pub(crate) fn problems<'a, 'b>(&'b self, file_id: FileId, root: ast::Root<'a>) -> Vec<(ast::Name<'a>, &'b Problem)> {
|
||||||
|
let node = self.file_id2node[&file_id];
|
||||||
|
self.node(node)
|
||||||
|
.links
|
||||||
|
.iter()
|
||||||
|
.filter_map(|&link| {
|
||||||
|
let problem = self.link(link).problem.as_ref()?;
|
||||||
|
let name = link.bind_source(self, root).name()?;
|
||||||
|
Some((name, problem))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn node(&self, node: Node) -> &NodeData {
|
||||||
|
&self.nodes[node.0]
|
||||||
|
}
|
||||||
|
fn link(&self, link: Link) -> &LinkData {
|
||||||
|
&self.links[link.0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Link {
|
||||||
|
pub(crate) fn name(self, tree: &ModuleTreeDescriptor) -> SmolStr {
|
||||||
|
tree.link(self).name.clone()
|
||||||
|
}
|
||||||
|
pub(crate) fn owner(self, tree: &ModuleTreeDescriptor) -> FileId {
|
||||||
|
let owner = tree.link(self).owner;
|
||||||
|
tree.node(owner).file_id
|
||||||
|
}
|
||||||
|
pub(crate) fn bind_source<'a>(self, tree: &ModuleTreeDescriptor, root: ast::Root<'a>) -> ast::Module<'a> {
|
||||||
|
modules(root)
|
||||||
|
.filter(|(name, _)| name == &tree.link(self).name)
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn resolve_submodule(
|
||||||
|
file_id: FileId,
|
||||||
|
name: &SmolStr,
|
||||||
|
file_resolver: &FileResolverImp
|
||||||
|
) -> (Vec<FileId>, Option<Problem>) {
|
||||||
|
let mod_name = file_resolver.file_stem(file_id);
|
||||||
|
let is_dir_owner =
|
||||||
|
mod_name == "mod" || mod_name == "lib" || mod_name == "main";
|
||||||
|
|
||||||
|
let file_mod = RelativePathBuf::from(format!("../{}.rs", name));
|
||||||
|
let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name));
|
||||||
|
let points_to: Vec<FileId>;
|
||||||
|
let problem: Option<Problem>;
|
||||||
|
if is_dir_owner {
|
||||||
|
points_to = [&file_mod, &dir_mod].iter()
|
||||||
|
.filter_map(|path| file_resolver.resolve(file_id, path))
|
||||||
|
.collect();
|
||||||
|
problem = if points_to.is_empty() {
|
||||||
|
Some(Problem::UnresolvedModule {
|
||||||
|
candidate: file_mod,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
points_to = Vec::new();
|
||||||
|
problem = Some(Problem::NotDirOwner {
|
||||||
|
move_to: RelativePathBuf::from(format!("../{}/mod.rs", mod_name)),
|
||||||
|
candidate: file_mod,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
(points_to, problem)
|
||||||
|
}
|
|
@ -18,8 +18,8 @@ use libsyntax2::{
|
||||||
use {
|
use {
|
||||||
FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit,
|
FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit,
|
||||||
JobToken, CrateGraph, CrateId,
|
JobToken, CrateGraph, CrateId,
|
||||||
module_map::{ModuleMap, Problem},
|
|
||||||
roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot},
|
roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot},
|
||||||
|
descriptors::{ModuleTreeDescriptor, Problem},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,25 +148,24 @@ impl AnalysisImpl {
|
||||||
}
|
}
|
||||||
pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> {
|
pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> {
|
||||||
let root = self.root(file_id);
|
let root = self.root(file_id);
|
||||||
let module_map = root.module_map();
|
let module_tree = root.module_tree();
|
||||||
let id = module_map.file2module(file_id);
|
module_tree.parent_modules(file_id)
|
||||||
module_map
|
.iter()
|
||||||
.parent_modules(id, &|file_id| root.syntax(file_id))
|
.map(|link| {
|
||||||
.into_iter()
|
let file_id = link.owner(&module_tree);
|
||||||
.map(|(id, name, node)| {
|
let syntax = root.syntax(file_id);
|
||||||
let id = module_map.module2file(id);
|
let decl = link.bind_source(&module_tree, syntax.ast());
|
||||||
let sym = FileSymbol {
|
let sym = FileSymbol {
|
||||||
name,
|
name: link.name(&module_tree),
|
||||||
node_range: node.range(),
|
node_range: decl.syntax().range(),
|
||||||
kind: MODULE,
|
kind: MODULE,
|
||||||
};
|
};
|
||||||
(id, sym)
|
(file_id, sym)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn crate_for(&self, file_id: FileId) -> Vec<CrateId> {
|
pub fn crate_for(&self, file_id: FileId) -> Vec<CrateId> {
|
||||||
let module_map = self.root(file_id).module_map();
|
let module_tree = self.root(file_id).module_tree();
|
||||||
let crate_graph = &self.data.crate_graph;
|
let crate_graph = &self.data.crate_graph;
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
let mut work = VecDeque::new();
|
let mut work = VecDeque::new();
|
||||||
|
@ -177,11 +176,10 @@ impl AnalysisImpl {
|
||||||
res.push(crate_id);
|
res.push(crate_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mid = module_map.file2module(id);
|
let parents = module_tree
|
||||||
let parents = module_map
|
.parent_modules(id)
|
||||||
.parent_module_ids(mid, &|file_id| self.file_syntax(file_id))
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|id| module_map.module2file(id))
|
.map(|link| link.owner(&module_tree))
|
||||||
.filter(|&id| visited.insert(id));
|
.filter(|&id| visited.insert(id));
|
||||||
work.extend(parents);
|
work.extend(parents);
|
||||||
}
|
}
|
||||||
|
@ -197,7 +195,7 @@ impl AnalysisImpl {
|
||||||
token: &JobToken,
|
token: &JobToken,
|
||||||
) -> Vec<(FileId, FileSymbol)> {
|
) -> Vec<(FileId, FileSymbol)> {
|
||||||
let root = self.root(file_id);
|
let root = self.root(file_id);
|
||||||
let module_map = root.module_map();
|
let module_tree = root.module_tree();
|
||||||
let file = root.syntax(file_id);
|
let file = root.syntax(file_id);
|
||||||
let syntax = file.syntax();
|
let syntax = file.syntax();
|
||||||
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
|
if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
|
||||||
|
@ -206,7 +204,7 @@ impl AnalysisImpl {
|
||||||
if let Some(name) = find_node_at_offset::<ast::Name>(syntax, offset) {
|
if let Some(name) = find_node_at_offset::<ast::Name>(syntax, offset) {
|
||||||
if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
|
if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
|
||||||
if module.has_semi() {
|
if module.has_semi() {
|
||||||
let file_ids = self.resolve_module(module_map, file_id, module);
|
let file_ids = self.resolve_module(&*module_tree, file_id, module);
|
||||||
|
|
||||||
let res = file_ids.into_iter().map(|id| {
|
let res = file_ids.into_iter().map(|id| {
|
||||||
let name = module.name()
|
let name = module.name()
|
||||||
|
@ -229,7 +227,7 @@ impl AnalysisImpl {
|
||||||
|
|
||||||
pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
|
pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
|
||||||
let root = self.root(file_id);
|
let root = self.root(file_id);
|
||||||
let module_map = root.module_map();
|
let module_tree = root.module_tree();
|
||||||
let syntax = root.syntax(file_id);
|
let syntax = root.syntax(file_id);
|
||||||
|
|
||||||
let mut res = libeditor::diagnostics(&syntax)
|
let mut res = libeditor::diagnostics(&syntax)
|
||||||
|
@ -237,10 +235,7 @@ impl AnalysisImpl {
|
||||||
.map(|d| Diagnostic { range: d.range, message: d.msg, fix: None })
|
.map(|d| Diagnostic { range: d.range, message: d.msg, fix: None })
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
module_map.problems(
|
for (name_node, problem) in module_tree.problems(file_id, syntax.ast()) {
|
||||||
file_id,
|
|
||||||
&|file_id| self.file_syntax(file_id),
|
|
||||||
|name_node, problem| {
|
|
||||||
let diag = match problem {
|
let diag = match problem {
|
||||||
Problem::UnresolvedModule { candidate } => {
|
Problem::UnresolvedModule { candidate } => {
|
||||||
let create_file = FileSystemEdit::CreateFile {
|
let create_file = FileSystemEdit::CreateFile {
|
||||||
|
@ -277,7 +272,6 @@ impl AnalysisImpl {
|
||||||
};
|
};
|
||||||
res.push(diag)
|
res.push(diag)
|
||||||
}
|
}
|
||||||
);
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,20 +301,12 @@ impl AnalysisImpl {
|
||||||
self.world_symbols(query, token)
|
self.world_symbols(query, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_module(&self, module_map: &ModuleMap, file_id: FileId, module: ast::Module) -> Vec<FileId> {
|
fn resolve_module(&self, module_tree: &ModuleTreeDescriptor, file_id: FileId, module: ast::Module) -> Vec<FileId> {
|
||||||
let name = match module.name() {
|
let name = match module.name() {
|
||||||
Some(name) => name.text(),
|
Some(name) => name.text(),
|
||||||
None => return Vec::new(),
|
None => return Vec::new(),
|
||||||
};
|
};
|
||||||
let id = module_map.file2module(file_id);
|
module_tree.child_module_by_name(file_id, name.as_str())
|
||||||
module_map
|
|
||||||
.child_module_by_name(
|
|
||||||
id, name.as_str(),
|
|
||||||
&|file_id| self.file_syntax(file_id),
|
|
||||||
)
|
|
||||||
.into_iter()
|
|
||||||
.map(|id| module_map.module2file(id))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reindex(&self) {
|
fn reindex(&self) {
|
||||||
|
|
|
@ -19,6 +19,7 @@ mod imp;
|
||||||
mod job;
|
mod job;
|
||||||
mod roots;
|
mod roots;
|
||||||
mod db;
|
mod db;
|
||||||
|
mod descriptors;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
use libsyntax2::{
|
|
||||||
SmolStr,
|
|
||||||
ast::{self, NameOwner},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Hash)]
|
|
||||||
pub struct ModuleDescr {
|
|
||||||
pub submodules: Vec<Submodule>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModuleDescr {
|
|
||||||
pub fn new(root: ast::Root) -> ModuleDescr {
|
|
||||||
let submodules = root
|
|
||||||
.modules()
|
|
||||||
.filter_map(|module| {
|
|
||||||
let name = module.name()?.text();
|
|
||||||
if !module.has_semi() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(Submodule { name })
|
|
||||||
}).collect();
|
|
||||||
|
|
||||||
ModuleDescr { submodules } }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
|
|
||||||
pub struct Submodule {
|
|
||||||
pub name: SmolStr,
|
|
||||||
}
|
|
|
@ -1,5 +1,3 @@
|
||||||
mod descr;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use {
|
use {
|
||||||
FileId,
|
FileId,
|
||||||
|
@ -7,49 +5,36 @@ use {
|
||||||
Query, QueryRegistry, QueryCtx,
|
Query, QueryRegistry, QueryCtx,
|
||||||
file_syntax, file_set
|
file_syntax, file_set
|
||||||
},
|
},
|
||||||
module_map::resolve_submodule,
|
descriptors::{ModuleDescriptor, ModuleTreeDescriptor}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn register_queries(reg: &mut QueryRegistry) {
|
pub(crate) fn register_queries(reg: &mut QueryRegistry) {
|
||||||
reg.add(MODULE_DESCR, "MODULE_DESCR");
|
reg.add(MODULE_DESCR, "MODULE_DESCR");
|
||||||
reg.add(RESOLVE_SUBMODULE, "RESOLVE_SUBMODULE");
|
}
|
||||||
reg.add(PARENT_MODULE, "PARENT_MODULE");
|
|
||||||
|
pub(crate) fn module_tree(ctx: QueryCtx) -> Arc<ModuleTreeDescriptor> {
|
||||||
|
ctx.get(MODULE_TREE, ())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> QueryCtx<'a> {
|
impl<'a> QueryCtx<'a> {
|
||||||
fn module_descr(&self, file_id: FileId) -> Arc<descr::ModuleDescr> {
|
fn module_descr(&self, file_id: FileId) -> Arc<ModuleDescriptor> {
|
||||||
self.get(MODULE_DESCR, file_id)
|
self.get(MODULE_DESCR, file_id)
|
||||||
}
|
}
|
||||||
fn resolve_submodule(&self, file_id: FileId, submod: descr::Submodule) -> Arc<Vec<FileId>> {
|
|
||||||
self.get(RESOLVE_SUBMODULE, (file_id, submod))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const MODULE_DESCR: Query<FileId, descr::ModuleDescr> = Query(30, |ctx, &file_id| {
|
const MODULE_DESCR: Query<FileId, ModuleDescriptor> = Query(30, |ctx, &file_id| {
|
||||||
let file = file_syntax(ctx, file_id);
|
let file = file_syntax(ctx, file_id);
|
||||||
descr::ModuleDescr::new(file.ast())
|
ModuleDescriptor::new(file.ast())
|
||||||
});
|
});
|
||||||
|
|
||||||
const RESOLVE_SUBMODULE: Query<(FileId, descr::Submodule), Vec<FileId>> = Query(31, |ctx, params| {
|
const MODULE_TREE: Query<(), ModuleTreeDescriptor> = Query(31, |ctx, _| {
|
||||||
let files = file_set(ctx);
|
let file_set = file_set(ctx);
|
||||||
resolve_submodule(params.0, ¶ms.1.name, &files.1).0
|
let mut files = Vec::new();
|
||||||
});
|
for &file_id in file_set.0.iter() {
|
||||||
|
let module_descr = ctx.get(MODULE_DESCR, file_id);
|
||||||
const PARENT_MODULE: Query<FileId, Vec<FileId>> = Query(40, |ctx, file_id| {
|
files.push((file_id, module_descr));
|
||||||
let files = file_set(ctx);
|
}
|
||||||
let res = files.0.iter()
|
ModuleTreeDescriptor::new(files.iter().map(|(file_id, descr)| (*file_id, &**descr)), &file_set.1)
|
||||||
.map(|&parent_id| (parent_id, ctx.module_descr(parent_id)))
|
|
||||||
.filter(|(parent_id, descr)| {
|
|
||||||
descr.submodules.iter()
|
|
||||||
.any(|subm| {
|
|
||||||
ctx.resolve_submodule(*parent_id, subm.clone())
|
|
||||||
.iter()
|
|
||||||
.any(|it| it == file_id)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.map(|(id, _)| id)
|
|
||||||
.collect();
|
|
||||||
res
|
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -15,11 +15,15 @@ use {
|
||||||
imp::FileResolverImp,
|
imp::FileResolverImp,
|
||||||
module_map::{ModuleMap, ChangeKind},
|
module_map::{ModuleMap, ChangeKind},
|
||||||
symbol_index::SymbolIndex,
|
symbol_index::SymbolIndex,
|
||||||
|
descriptors::ModuleTreeDescriptor,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) trait SourceRoot {
|
pub(crate) trait SourceRoot {
|
||||||
fn contains(&self, file_id: FileId) -> bool;
|
fn contains(&self, file_id: FileId) -> bool;
|
||||||
fn module_map(&self) -> &ModuleMap;
|
fn module_tree(&self) -> Arc<ModuleTreeDescriptor> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
// fn module_map(&self) -> &ModuleMap;
|
||||||
fn lines(&self, file_id: FileId) -> &LineIndex;
|
fn lines(&self, file_id: FileId) -> &LineIndex;
|
||||||
fn syntax(&self, file_id: FileId) -> &File;
|
fn syntax(&self, file_id: FileId) -> &File;
|
||||||
fn symbols<'a>(&'a self, acc: &mut Vec<&'a SymbolIndex>);
|
fn symbols<'a>(&'a self, acc: &mut Vec<&'a SymbolIndex>);
|
||||||
|
@ -74,9 +78,6 @@ impl SourceRoot for WritableSourceRoot {
|
||||||
fn contains(&self, file_id: FileId) -> bool {
|
fn contains(&self, file_id: FileId) -> bool {
|
||||||
self.file_map.contains_key(&file_id)
|
self.file_map.contains_key(&file_id)
|
||||||
}
|
}
|
||||||
fn module_map(&self) -> &ModuleMap {
|
|
||||||
&self.module_map
|
|
||||||
}
|
|
||||||
fn lines(&self, file_id: FileId) -> &LineIndex {
|
fn lines(&self, file_id: FileId) -> &LineIndex {
|
||||||
self.data(file_id).lines()
|
self.data(file_id).lines()
|
||||||
}
|
}
|
||||||
|
@ -175,9 +176,6 @@ impl SourceRoot for ReadonlySourceRoot {
|
||||||
fn contains(&self, file_id: FileId) -> bool {
|
fn contains(&self, file_id: FileId) -> bool {
|
||||||
self.file_map.contains_key(&file_id)
|
self.file_map.contains_key(&file_id)
|
||||||
}
|
}
|
||||||
fn module_map(&self) -> &ModuleMap {
|
|
||||||
&self.module_map
|
|
||||||
}
|
|
||||||
fn lines(&self, file_id: FileId) -> &LineIndex {
|
fn lines(&self, file_id: FileId) -> &LineIndex {
|
||||||
self.data(file_id).lines()
|
self.data(file_id).lines()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use superslice::Ext;
|
use superslice::Ext;
|
||||||
use ::TextUnit;
|
use ::TextUnit;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Hash)]
|
||||||
pub struct LineIndex {
|
pub struct LineIndex {
|
||||||
newlines: Vec<TextUnit>,
|
newlines: Vec<TextUnit>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue