store file rsovler
This commit is contained in:
parent
4f64709666
commit
505895a25f
@ -7,6 +7,7 @@
|
||||
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 @@
|
||||
roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot},
|
||||
};
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct FileResolverImp {
|
||||
inner: Arc<FileResolver>
|
||||
}
|
||||
|
||||
impl FileResolverImp {
|
||||
pub(crate) fn new(inner: Arc<FileResolver>) -> 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<FileId> {
|
||||
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<FileId> {
|
||||
panic!("file resolver not set")
|
||||
}
|
||||
}
|
||||
FileResolverImp { inner: Arc::new(DummyResolver) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct AnalysisHostImpl {
|
||||
data: Arc<WorldData>
|
||||
@ -32,13 +67,9 @@ pub fn new() -> AnalysisHostImpl {
|
||||
data: Arc::new(WorldData::default()),
|
||||
}
|
||||
}
|
||||
pub fn analysis(
|
||||
&self,
|
||||
file_resolver: Arc<dyn FileResolver>,
|
||||
) -> AnalysisImpl {
|
||||
pub fn analysis(&self) -> AnalysisImpl {
|
||||
AnalysisImpl {
|
||||
needs_reindex: AtomicBool::new(false),
|
||||
file_resolver,
|
||||
data: self.data.clone(),
|
||||
}
|
||||
}
|
||||
@ -48,6 +79,11 @@ pub fn change_files(&mut self, changes: &mut dyn Iterator<Item=(FileId, Option<S
|
||||
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 @@ fn data_mut(&mut self) -> &mut WorldData {
|
||||
|
||||
pub(crate) struct AnalysisImpl {
|
||||
needs_reindex: AtomicBool,
|
||||
file_resolver: Arc<dyn FileResolver>,
|
||||
data: Arc<WorldData>,
|
||||
}
|
||||
|
||||
@ -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 @@ pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> {
|
||||
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 @@ pub fn crate_for(&self, file_id: FileId) -> Vec<CrateId> {
|
||||
}
|
||||
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 @@ pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
|
||||
|
||||
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 @@ fn resolve_module(&self, module_map: &ModuleMap, file_id: FileId, module: ast::M
|
||||
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 @@ fn reindex(&self) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
#[derive(Default, Clone, Debug)]
|
||||
struct WorldData {
|
||||
file_resolver: FileResolverImp,
|
||||
crate_graph: CrateGraph,
|
||||
root: WritableSourceRoot,
|
||||
libs: Vec<Arc<ReadonlySourceRoot>>,
|
||||
|
@ -19,11 +19,12 @@
|
||||
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<CrateId, FileId>,
|
||||
}
|
||||
|
||||
pub trait FileResolver: Send + Sync + 'static {
|
||||
fn file_stem(&self, id: FileId) -> String;
|
||||
fn resolve(&self, id: FileId, path: &RelativePath) -> Option<FileId>;
|
||||
pub trait FileResolver: Debug + Send + Sync + 'static {
|
||||
fn file_stem(&self, file_id: FileId) -> String;
|
||||
fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId>;
|
||||
}
|
||||
|
||||
#[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<String>) {
|
||||
self.change_files(::std::iter::once((file_id, text)));
|
||||
@ -65,6 +66,9 @@ pub fn change_file(&mut self, file_id: FileId, text: Option<String>) {
|
||||
pub fn change_files(&mut self, mut changes: impl Iterator<Item=(FileId, Option<String>)>) {
|
||||
self.imp.change_files(&mut changes)
|
||||
}
|
||||
pub fn set_file_resolver(&mut self, resolver: Arc<FileResolver>) {
|
||||
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<FileResolver>) -> LibraryData {
|
||||
let file_resolver = FileResolverImp::new(file_resolver);
|
||||
let root = roots::ReadonlySourceRoot::new(files, file_resolver);
|
||||
LibraryData { root }
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ fn clone(&self) -> ModuleMap {
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct State {
|
||||
file_resolver: FileResolverImp,
|
||||
changes: Vec<(FileId, ChangeKind)>,
|
||||
links: Vec<Link>,
|
||||
}
|
||||
@ -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<ModuleId> {
|
||||
self.links(file_resolver, syntax_provider)
|
||||
self.links(syntax_provider)
|
||||
.links
|
||||
.iter()
|
||||
.filter(|link| link.owner == parent_mod)
|
||||
@ -92,11 +90,10 @@ pub fn child_module_by_name<'a>(
|
||||
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 @@ pub fn parent_modules(
|
||||
pub fn parent_module_ids(
|
||||
&self,
|
||||
m: ModuleId,
|
||||
file_resolver: &FileResolver,
|
||||
syntax_provider: &SyntaxProvider,
|
||||
) -> Vec<ModuleId> {
|
||||
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 @@ fn for_each_parent_link(
|
||||
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 @@ pub fn problems(
|
||||
|
||||
fn links(
|
||||
&self,
|
||||
file_resolver: &FileResolver,
|
||||
syntax_provider: &SyntaxProvider,
|
||||
) -> RwLockReadGuard<State> {
|
||||
{
|
||||
@ -162,7 +155,7 @@ fn links(
|
||||
}
|
||||
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 @@ fn links(
|
||||
impl State {
|
||||
pub fn apply_changes(
|
||||
&mut self,
|
||||
file_resolver: &FileResolver,
|
||||
syntax_provider: &SyntaxProvider,
|
||||
) {
|
||||
let mut reresolve = false;
|
||||
@ -197,13 +189,14 @@ pub fn apply_changes(
|
||||
}
|
||||
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 @@ pub fn apply_changes(
|
||||
}
|
||||
if reresolve {
|
||||
for link in self.links.iter_mut() {
|
||||
link.resolve(file_resolver)
|
||||
link.resolve(&self.file_resolver)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -245,7 +238,7 @@ fn ast(&self) -> ast::Module {
|
||||
.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();
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
use {
|
||||
FileId,
|
||||
imp::FileResolverImp,
|
||||
module_map::{ModuleMap, ChangeKind},
|
||||
symbol_index::SymbolIndex,
|
||||
};
|
||||
@ -48,6 +49,9 @@ pub fn update(&mut self, file_id: FileId, text: Option<String>) {
|
||||
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))
|
||||
|
@ -3,21 +3,38 @@
|
||||
extern crate test_utils;
|
||||
|
||||
use std::{
|
||||
sync::Arc,
|
||||
collections::HashMap,
|
||||
};
|
||||
|
||||
use relative_path::{RelativePath};
|
||||
use libanalysis::{AnalysisHost, FileId, FileResolver, JobHandle, CrateGraph, CrateId};
|
||||
use relative_path::{RelativePath, RelativePathBuf};
|
||||
use libanalysis::{Analysis, AnalysisHost, FileId, FileResolver, JobHandle, CrateGraph, CrateId};
|
||||
use test_utils::assert_eq_dbg;
|
||||
|
||||
struct FileMap(&'static [(u32, &'static str)]);
|
||||
#[derive(Debug)]
|
||||
struct FileMap(Vec<(FileId, RelativePathBuf)>);
|
||||
|
||||
fn analysis_host(files: &'static [(&'static str, &'static str)]) -> AnalysisHost {
|
||||
let mut host = AnalysisHost::new();
|
||||
let mut file_map = Vec::new();
|
||||
for (id, &(path, contents)) in files.iter().enumerate() {
|
||||
let file_id = FileId((id + 1) as u32);
|
||||
assert!(path.starts_with('/'));
|
||||
let path = RelativePathBuf::from_path(&path[1..]).unwrap();
|
||||
host.change_file(file_id, Some(contents.to_string()));
|
||||
file_map.push((file_id, path));
|
||||
}
|
||||
host.set_file_resolver(Arc::new(FileMap(file_map)));
|
||||
host
|
||||
}
|
||||
|
||||
fn analysis(files: &'static [(&'static str, &'static str)]) -> Analysis {
|
||||
analysis_host(files).analysis()
|
||||
}
|
||||
|
||||
impl FileMap {
|
||||
fn iter<'a>(&'a self) -> impl Iterator<Item=(FileId, &'a RelativePath)> + 'a {
|
||||
self.0.iter().map(|&(id, path)| {
|
||||
assert!(path.starts_with('/'));
|
||||
(FileId(id), RelativePath::new(&path[1..]))
|
||||
})
|
||||
self.0.iter().map(|(id, path)| (*id, path.as_relative_path()))
|
||||
}
|
||||
|
||||
fn path(&self, id: FileId) -> &RelativePath {
|
||||
@ -42,14 +59,10 @@ fn resolve(&self, id: FileId, rel: &RelativePath) -> Option<FileId> {
|
||||
|
||||
#[test]
|
||||
fn test_resolve_module() {
|
||||
let mut world = AnalysisHost::new();
|
||||
world.change_file(FileId(1), Some("mod foo;".to_string()));
|
||||
world.change_file(FileId(2), Some("".to_string()));
|
||||
|
||||
let snap = world.analysis(FileMap(&[
|
||||
(1, "/lib.rs"),
|
||||
(2, "/foo.rs"),
|
||||
]));
|
||||
let snap = analysis(&[
|
||||
("/lib.rs", "mod foo;"),
|
||||
("/foo.rs", "")
|
||||
]);
|
||||
let (_handle, token) = JobHandle::new();
|
||||
let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into(), &token);
|
||||
assert_eq_dbg(
|
||||
@ -57,10 +70,10 @@ fn test_resolve_module() {
|
||||
&symbols,
|
||||
);
|
||||
|
||||
let snap = world.analysis(FileMap(&[
|
||||
(1, "/lib.rs"),
|
||||
(2, "/foo/mod.rs")
|
||||
]));
|
||||
let snap = analysis(&[
|
||||
("/lib.rs", "mod foo;"),
|
||||
("/foo/mod.rs", "")
|
||||
]);
|
||||
let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into(), &token);
|
||||
assert_eq_dbg(
|
||||
r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#,
|
||||
@ -70,10 +83,7 @@ fn test_resolve_module() {
|
||||
|
||||
#[test]
|
||||
fn test_unresolved_module_diagnostic() {
|
||||
let mut world = AnalysisHost::new();
|
||||
world.change_file(FileId(1), Some("mod foo;".to_string()));
|
||||
|
||||
let snap = world.analysis(FileMap(&[(1, "/lib.rs")]));
|
||||
let snap = analysis(&[("/lib.rs", "mod foo;")]);
|
||||
let diagnostics = snap.diagnostics(FileId(1));
|
||||
assert_eq_dbg(
|
||||
r#"[Diagnostic {
|
||||
@ -90,10 +100,7 @@ fn test_unresolved_module_diagnostic() {
|
||||
|
||||
#[test]
|
||||
fn test_unresolved_module_diagnostic_no_diag_for_inline_mode() {
|
||||
let mut world = AnalysisHost::new();
|
||||
world.change_file(FileId(1), Some("mod foo {}".to_string()));
|
||||
|
||||
let snap = world.analysis(FileMap(&[(1, "/lib.rs")]));
|
||||
let snap = analysis(&[("/lib.rs", "mod foo {}")]);
|
||||
let diagnostics = snap.diagnostics(FileId(1));
|
||||
assert_eq_dbg(
|
||||
r#"[]"#,
|
||||
@ -103,14 +110,10 @@ fn test_unresolved_module_diagnostic_no_diag_for_inline_mode() {
|
||||
|
||||
#[test]
|
||||
fn test_resolve_parent_module() {
|
||||
let mut world = AnalysisHost::new();
|
||||
world.change_file(FileId(1), Some("mod foo;".to_string()));
|
||||
world.change_file(FileId(2), Some("".to_string()));
|
||||
|
||||
let snap = world.analysis(FileMap(&[
|
||||
(1, "/lib.rs"),
|
||||
(2, "/foo.rs"),
|
||||
]));
|
||||
let snap = analysis(&[
|
||||
("/lib.rs", "mod foo;"),
|
||||
("/foo.rs", ""),
|
||||
]);
|
||||
let symbols = snap.parent_module(FileId(2));
|
||||
assert_eq_dbg(
|
||||
r#"[(FileId(1), FileSymbol { name: "foo", node_range: [0; 8), kind: MODULE })]"#,
|
||||
@ -120,14 +123,11 @@ fn test_resolve_parent_module() {
|
||||
|
||||
#[test]
|
||||
fn test_resolve_crate_root() {
|
||||
let mut world = AnalysisHost::new();
|
||||
world.change_file(FileId(1), Some("mod foo;".to_string()));
|
||||
world.change_file(FileId(2), Some("".to_string()));
|
||||
|
||||
let snap = world.analysis(FileMap(&[
|
||||
(1, "/lib.rs"),
|
||||
(2, "/foo.rs"),
|
||||
]));
|
||||
let mut host = analysis_host(&[
|
||||
("/lib.rs", "mod foo;"),
|
||||
("/foo.rs", ""),
|
||||
]);
|
||||
let snap = host.analysis();
|
||||
assert!(snap.crate_for(FileId(2)).is_empty());
|
||||
|
||||
let crate_graph = CrateGraph {
|
||||
@ -137,12 +137,9 @@ fn test_resolve_crate_root() {
|
||||
m
|
||||
},
|
||||
};
|
||||
world.set_crate_graph(crate_graph);
|
||||
host.set_crate_graph(crate_graph);
|
||||
let snap = host.analysis();
|
||||
|
||||
let snap = world.analysis(FileMap(&[
|
||||
(1, "/lib.rs"),
|
||||
(2, "/foo.rs"),
|
||||
]));
|
||||
assert_eq!(
|
||||
snap.crate_for(FileId(2)),
|
||||
vec![CrateId(1)],
|
||||
|
@ -135,12 +135,12 @@ enum Event {
|
||||
if root == ws_root {
|
||||
state.apply_fs_changes(events);
|
||||
} else {
|
||||
let files = state.events_to_files(events);
|
||||
let (files, resolver) = state.events_to_files(events);
|
||||
let sender = libdata_sender.clone();
|
||||
pool.spawn(move || {
|
||||
let start = ::std::time::Instant::now();
|
||||
info!("indexing {} ... ", root.display());
|
||||
let data = LibraryData::prepare(files);
|
||||
let data = LibraryData::prepare(files, resolver);
|
||||
info!("indexed {:?} {}", start.elapsed(), root.display());
|
||||
sender.send(data);
|
||||
});
|
||||
|
@ -6,7 +6,7 @@
|
||||
};
|
||||
|
||||
use languageserver_types::Url;
|
||||
use libanalysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId, LibraryData};
|
||||
use libanalysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId, LibraryData, FileResolver};
|
||||
|
||||
use {
|
||||
Result,
|
||||
@ -64,17 +64,21 @@ pub fn apply_fs_changes(&mut self, events: Vec<FileEvent>) {
|
||||
|
||||
self.analysis_host.change_files(changes);
|
||||
}
|
||||
pub fn events_to_files(&mut self, events: Vec<FileEvent>) -> Vec<(FileId, String)> {
|
||||
let pm = &mut self.path_map;
|
||||
events.into_iter()
|
||||
.map(|event| {
|
||||
let text = match event.kind {
|
||||
FileEventKind::Add(text) => text,
|
||||
};
|
||||
(event.path, text)
|
||||
})
|
||||
.map(|(path, text)| (pm.get_or_insert(path, Root::Lib), text))
|
||||
.collect()
|
||||
pub fn events_to_files(&mut self, events: Vec<FileEvent>) -> (Vec<(FileId, String)>, Arc<FileResolver>) {
|
||||
let files = {
|
||||
let pm = &mut self.path_map;
|
||||
events.into_iter()
|
||||
.map(|event| {
|
||||
let text = match event.kind {
|
||||
FileEventKind::Add(text) => text,
|
||||
};
|
||||
(event.path, text)
|
||||
})
|
||||
.map(|(path, text)| (pm.get_or_insert(path, Root::Lib), text))
|
||||
.collect()
|
||||
};
|
||||
let resolver = Arc::new(self.path_map.clone());
|
||||
(files, resolver)
|
||||
}
|
||||
pub fn add_lib(&mut self, data: LibraryData) {
|
||||
self.analysis_host.add_library(data);
|
||||
@ -82,6 +86,7 @@ pub fn add_lib(&mut self, data: LibraryData) {
|
||||
|
||||
pub fn add_mem_file(&mut self, path: PathBuf, text: String) -> FileId {
|
||||
let file_id = self.path_map.get_or_insert(path, Root::Workspace);
|
||||
self.analysis_host.set_file_resolver(Arc::new(self.path_map.clone()));
|
||||
self.mem_map.insert(file_id, None);
|
||||
if self.path_map.get_root(file_id) != Root::Lib {
|
||||
self.analysis_host.change_file(file_id, Some(text));
|
||||
@ -135,7 +140,7 @@ pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) {
|
||||
pub fn snapshot(&self) -> ServerWorld {
|
||||
ServerWorld {
|
||||
workspaces: Arc::clone(&self.workspaces),
|
||||
analysis: self.analysis_host.analysis(self.path_map.clone()),
|
||||
analysis: self.analysis_host.analysis(),
|
||||
path_map: self.path_map.clone()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user