From 505895a25f98423de07c3cec4793b66a19d098c7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 10 Sep 2018 12:57:40 +0300 Subject: store file rsovler --- crates/libanalysis/src/imp.rs | 65 +++++++++++++++++++++++++----------- crates/libanalysis/src/lib.rs | 21 +++++++----- crates/libanalysis/src/module_map.rs | 41 ++++++++++------------- crates/libanalysis/src/roots.rs | 7 +++- 4 files changed, 81 insertions(+), 53 deletions(-) (limited to 'crates/libanalysis/src') diff --git a/crates/libanalysis/src/imp.rs b/crates/libanalysis/src/imp.rs index 47b0d79ff..3e65ee14a 100644 --- a/crates/libanalysis/src/imp.rs +++ b/crates/libanalysis/src/imp.rs @@ -7,6 +7,7 @@ use std::{ collections::{HashSet, VecDeque}, }; +use relative_path::RelativePath; use libeditor::{self, FileSymbol, LineIndex, find_node_at_offset, LocalEdit}; use libsyntax2::{ TextUnit, TextRange, SmolStr, File, AstNode, @@ -21,6 +22,40 @@ use { roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot}, }; + +#[derive(Clone, Debug)] +pub(crate) struct FileResolverImp { + inner: Arc +} + +impl FileResolverImp { + pub(crate) fn new(inner: Arc) -> FileResolverImp { + FileResolverImp { inner } + } + pub(crate) fn file_stem(&self, file_id: FileId) -> String { + self.inner.file_stem(file_id) + } + pub(crate) fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option { + self.inner.resolve(file_id, path) + } +} + +impl Default for FileResolverImp { + fn default() -> FileResolverImp { + #[derive(Debug)] + struct DummyResolver; + impl FileResolver for DummyResolver { + fn file_stem(&self, _file_: FileId) -> String { + panic!("file resolver not set") + } + fn resolve(&self, _file_id: FileId, _path: &::relative_path::RelativePath) -> Option { + panic!("file resolver not set") + } + } + FileResolverImp { inner: Arc::new(DummyResolver) } + } +} + #[derive(Debug)] pub(crate) struct AnalysisHostImpl { data: Arc @@ -32,13 +67,9 @@ impl AnalysisHostImpl { data: Arc::new(WorldData::default()), } } - pub fn analysis( - &self, - file_resolver: Arc, - ) -> AnalysisImpl { + pub fn analysis(&self) -> AnalysisImpl { AnalysisImpl { needs_reindex: AtomicBool::new(false), - file_resolver, data: self.data.clone(), } } @@ -48,6 +79,11 @@ impl AnalysisHostImpl { data.root.update(file_id, text); } } + pub fn set_file_resolver(&mut self, resolver: FileResolverImp) { + let data = self.data_mut(); + data.file_resolver = resolver.clone(); + data.root.set_file_resolver(resolver); + } pub fn set_crate_graph(&mut self, graph: CrateGraph) { let mut visited = HashSet::new(); for &file_id in graph.crate_roots.values() { @@ -67,7 +103,6 @@ impl AnalysisHostImpl { pub(crate) struct AnalysisImpl { needs_reindex: AtomicBool, - file_resolver: Arc, data: Arc, } @@ -81,7 +116,6 @@ impl Clone for AnalysisImpl { fn clone(&self) -> AnalysisImpl { AnalysisImpl { needs_reindex: AtomicBool::new(self.needs_reindex.load(SeqCst)), - file_resolver: Arc::clone(&self.file_resolver), data: Arc::clone(&self.data), } } @@ -117,11 +151,7 @@ impl AnalysisImpl { let module_map = root.module_map(); let id = module_map.file2module(file_id); module_map - .parent_modules( - id, - &*self.file_resolver, - &|file_id| root.syntax(file_id), - ) + .parent_modules(id, &|file_id| root.syntax(file_id)) .into_iter() .map(|(id, name, node)| { let id = module_map.module2file(id); @@ -149,11 +179,7 @@ impl AnalysisImpl { } let mid = module_map.file2module(id); let parents = module_map - .parent_module_ids( - mid, - &*self.file_resolver, - &|file_id| self.file_syntax(file_id), - ) + .parent_module_ids(mid, &|file_id| self.file_syntax(file_id)) .into_iter() .map(|id| module_map.module2file(id)) .filter(|&id| visited.insert(id)); @@ -213,7 +239,6 @@ impl AnalysisImpl { module_map.problems( file_id, - &*self.file_resolver, &|file_id| self.file_syntax(file_id), |name_node, problem| { let diag = match problem { @@ -291,7 +316,6 @@ impl AnalysisImpl { module_map .child_module_by_name( id, name.as_str(), - &*self.file_resolver, &|file_id| self.file_syntax(file_id), ) .into_iter() @@ -306,8 +330,9 @@ impl AnalysisImpl { } } -#[derive(Clone, Default, Debug)] +#[derive(Default, Clone, Debug)] struct WorldData { + file_resolver: FileResolverImp, crate_graph: CrateGraph, root: WritableSourceRoot, libs: Vec>, diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs index ff4fc709b..80cde079f 100644 --- a/crates/libanalysis/src/lib.rs +++ b/crates/libanalysis/src/lib.rs @@ -19,11 +19,12 @@ mod roots; use std::{ sync::Arc, collections::HashMap, + fmt::Debug, }; use relative_path::{RelativePath, RelativePathBuf}; use libsyntax2::{File, TextRange, TextUnit, AtomEdit}; -use imp::{AnalysisImpl, AnalysisHostImpl}; +use imp::{AnalysisImpl, AnalysisHostImpl, FileResolverImp}; pub use libeditor::{ StructureNode, LineIndex, FileSymbol, @@ -42,9 +43,9 @@ pub struct CrateGraph { pub crate_roots: HashMap, } -pub trait FileResolver: Send + Sync + 'static { - fn file_stem(&self, id: FileId) -> String; - fn resolve(&self, id: FileId, path: &RelativePath) -> Option; +pub trait FileResolver: Debug + Send + Sync + 'static { + fn file_stem(&self, file_id: FileId) -> String; + fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option; } #[derive(Debug)] @@ -56,8 +57,8 @@ impl AnalysisHost { pub fn new() -> AnalysisHost { AnalysisHost { imp: AnalysisHostImpl::new() } } - pub fn analysis(&self, file_resolver: impl FileResolver) -> Analysis { - Analysis { imp: self.imp.analysis(Arc::new(file_resolver)) } + pub fn analysis(&self) -> Analysis { + Analysis { imp: self.imp.analysis() } } pub fn change_file(&mut self, file_id: FileId, text: Option) { self.change_files(::std::iter::once((file_id, text))); @@ -65,6 +66,9 @@ impl AnalysisHost { pub fn change_files(&mut self, mut changes: impl Iterator)>) { self.imp.change_files(&mut changes) } + pub fn set_file_resolver(&mut self, resolver: Arc) { + self.imp.set_file_resolver(FileResolverImp::new(resolver)); + } pub fn set_crate_graph(&mut self, graph: CrateGraph) { self.imp.set_crate_graph(graph) } @@ -223,8 +227,9 @@ pub struct LibraryData { } impl LibraryData { - pub fn prepare(files: Vec<(FileId, String)>) -> LibraryData { - let root = roots::ReadonlySourceRoot::new(files); + pub fn prepare(files: Vec<(FileId, String)>, file_resolver: Arc) -> LibraryData { + let file_resolver = FileResolverImp::new(file_resolver); + let root = roots::ReadonlySourceRoot::new(files, file_resolver); LibraryData { root } } } diff --git a/crates/libanalysis/src/module_map.rs b/crates/libanalysis/src/module_map.rs index 1b225ecee..9acebd6e2 100644 --- a/crates/libanalysis/src/module_map.rs +++ b/crates/libanalysis/src/module_map.rs @@ -1,12 +1,11 @@ use relative_path::RelativePathBuf; - use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use libsyntax2::{ File, ast::{self, AstNode, NameOwner}, SyntaxNode, SmolStr, }; -use {FileId, FileResolver}; +use {FileId, imp::FileResolverImp}; type SyntaxProvider<'a> = dyn Fn(FileId) -> &'a File + 'a; @@ -32,6 +31,7 @@ impl Clone for ModuleMap { #[derive(Clone, Debug, Default)] struct State { + file_resolver: FileResolverImp, changes: Vec<(FileId, ChangeKind)>, links: Vec, } @@ -59,27 +59,25 @@ impl ModuleMap { pub fn new() -> ModuleMap { Default::default() } - - pub fn update_file(&mut self, file: FileId, change_kind: ChangeKind) { - self.state.get_mut().changes.push((file, change_kind)); + pub fn update_file(&mut self, file_id: FileId, change_kind: ChangeKind) { + self.state.get_mut().changes.push((file_id, change_kind)); + } + pub(crate) fn set_file_resolver(&mut self, file_resolver: FileResolverImp) { + self.state.get_mut().file_resolver = file_resolver; } - pub fn module2file(&self, m: ModuleId) -> FileId { m.0 } - pub fn file2module(&self, file_id: FileId) -> ModuleId { ModuleId(file_id) } - pub fn child_module_by_name<'a>( &self, parent_mod: ModuleId, child_mod: &str, - file_resolver: &FileResolver, syntax_provider: &SyntaxProvider, ) -> Vec { - self.links(file_resolver, syntax_provider) + self.links(syntax_provider) .links .iter() .filter(|link| link.owner == parent_mod) @@ -92,11 +90,10 @@ impl ModuleMap { pub fn parent_modules( &self, m: ModuleId, - file_resolver: &FileResolver, syntax_provider: &SyntaxProvider, ) -> Vec<(ModuleId, SmolStr, SyntaxNode)> { let mut res = Vec::new(); - self.for_each_parent_link(m, file_resolver, syntax_provider, |link| { + self.for_each_parent_link(m, syntax_provider, |link| { res.push( (link.owner, link.name().clone(), link.syntax.clone()) ) @@ -107,22 +104,20 @@ impl ModuleMap { pub fn parent_module_ids( &self, m: ModuleId, - file_resolver: &FileResolver, syntax_provider: &SyntaxProvider, ) -> Vec { let mut res = Vec::new(); - self.for_each_parent_link(m, file_resolver, syntax_provider, |link| res.push(link.owner)); + self.for_each_parent_link(m, syntax_provider, |link| res.push(link.owner)); res } fn for_each_parent_link( &self, m: ModuleId, - file_resolver: &FileResolver, syntax_provider: &SyntaxProvider, f: impl FnMut(&Link) ) { - self.links(file_resolver, syntax_provider) + self.links(syntax_provider) .links .iter() .filter(move |link| link.points_to.iter().any(|&it| it == m)) @@ -132,12 +127,11 @@ impl ModuleMap { pub fn problems( &self, file: FileId, - file_resolver: &FileResolver, syntax_provider: &SyntaxProvider, mut cb: impl FnMut(ast::Name, &Problem), ) { let module = self.file2module(file); - let links = self.links(file_resolver, syntax_provider); + let links = self.links(syntax_provider); links .links .iter() @@ -151,7 +145,6 @@ impl ModuleMap { fn links( &self, - file_resolver: &FileResolver, syntax_provider: &SyntaxProvider, ) -> RwLockReadGuard { { @@ -162,7 +155,7 @@ impl ModuleMap { } let mut guard = self.state.write(); if !guard.changes.is_empty() { - guard.apply_changes(file_resolver, syntax_provider); + guard.apply_changes(syntax_provider); } assert!(guard.changes.is_empty()); RwLockWriteGuard::downgrade(guard) @@ -172,7 +165,6 @@ impl ModuleMap { impl State { pub fn apply_changes( &mut self, - file_resolver: &FileResolver, syntax_provider: &SyntaxProvider, ) { let mut reresolve = false; @@ -197,13 +189,14 @@ impl State { } ChangeKind::Update => { let file = syntax_provider(file_id); + let resolver = &self.file_resolver; self.links.extend( file .ast() .modules() .filter_map(|it| Link::new(mod_id, it)) .map(|mut link| { - link.resolve(file_resolver); + link.resolve(resolver); link }) ); @@ -212,7 +205,7 @@ impl State { } if reresolve { for link in self.links.iter_mut() { - link.resolve(file_resolver) + link.resolve(&self.file_resolver) } } } @@ -245,7 +238,7 @@ impl Link { .unwrap() } - fn resolve(&mut self, file_resolver: &FileResolver) { + fn resolve(&mut self, file_resolver: &FileResolverImp) { if !self.ast().has_semi() { self.problem = None; self.points_to = Vec::new(); diff --git a/crates/libanalysis/src/roots.rs b/crates/libanalysis/src/roots.rs index 6d1375f88..629a697c5 100644 --- a/crates/libanalysis/src/roots.rs +++ b/crates/libanalysis/src/roots.rs @@ -12,6 +12,7 @@ use libsyntax2::File; use { FileId, + imp::FileResolverImp, module_map::{ModuleMap, ChangeKind}, symbol_index::SymbolIndex, }; @@ -48,6 +49,9 @@ impl WritableSourceRoot { self.file_map.insert(file_id, Arc::new((file_data, Default::default()))); } } + pub fn set_file_resolver(&mut self, file_resolver: FileResolverImp) { + self.module_map.set_file_resolver(file_resolver) + } pub fn reindex(&self) { let now = Instant::now(); self.file_map @@ -136,8 +140,9 @@ pub(crate) struct ReadonlySourceRoot { } impl ReadonlySourceRoot { - pub fn new(files: Vec<(FileId, String)>) -> ReadonlySourceRoot { + pub(crate) fn new(files: Vec<(FileId, String)>, file_resolver: FileResolverImp) -> ReadonlySourceRoot { let mut module_map = ModuleMap::new(); + module_map.set_file_resolver(file_resolver); let symbol_index = SymbolIndex::for_files( files.par_iter().map(|(file_id, text)| { (*file_id, File::parse(text)) -- cgit v1.2.3