mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Remove special casing for library symbols
We might as well handle them internally, via queries. I am not sure, but it looks like the current LibraryData setup might even predate salsa? It's not really needed and creates a bunch of complexity.
This commit is contained in:
parent
1ce8c2b5a0
commit
d1d0b5a88c
6 changed files with 69 additions and 212 deletions
|
@ -82,7 +82,7 @@ pub use ra_db::{
|
||||||
Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId,
|
Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId,
|
||||||
};
|
};
|
||||||
pub use ra_ide_db::{
|
pub use ra_ide_db::{
|
||||||
change::{AnalysisChange, LibraryData},
|
change::AnalysisChange,
|
||||||
line_index::{LineCol, LineIndex},
|
line_index::{LineCol, LineIndex},
|
||||||
search::SearchScope,
|
search::SearchScope,
|
||||||
source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
|
source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
|
||||||
|
|
|
@ -16,6 +16,7 @@ use ra_prof::{memory_usage, Bytes};
|
||||||
use ra_syntax::{ast, Parse, SyntaxNode};
|
use ra_syntax::{ast, Parse, SyntaxNode};
|
||||||
|
|
||||||
use crate::FileId;
|
use crate::FileId;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
|
fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
|
||||||
db.query(ra_db::ParseQuery).entries::<SyntaxTreeStats>()
|
db.query(ra_db::ParseQuery).entries::<SyntaxTreeStats>()
|
||||||
|
@ -123,20 +124,24 @@ struct LibrarySymbolsStats {
|
||||||
|
|
||||||
impl fmt::Display for LibrarySymbolsStats {
|
impl fmt::Display for LibrarySymbolsStats {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(fmt, "{} ({}) symbols", self.total, self.size,)
|
write!(fmt, "{} ({}) symbols", self.total, self.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromIterator<TableEntry<SourceRootId, Arc<SymbolIndex>>> for LibrarySymbolsStats {
|
impl FromIterator<TableEntry<(), Arc<FxHashMap<SourceRootId, SymbolIndex>>>>
|
||||||
|
for LibrarySymbolsStats
|
||||||
|
{
|
||||||
fn from_iter<T>(iter: T) -> LibrarySymbolsStats
|
fn from_iter<T>(iter: T) -> LibrarySymbolsStats
|
||||||
where
|
where
|
||||||
T: IntoIterator<Item = TableEntry<SourceRootId, Arc<SymbolIndex>>>,
|
T: IntoIterator<Item = TableEntry<(), Arc<FxHashMap<SourceRootId, SymbolIndex>>>>,
|
||||||
{
|
{
|
||||||
let mut res = LibrarySymbolsStats::default();
|
let mut res = LibrarySymbolsStats::default();
|
||||||
for entry in iter {
|
for entry in iter {
|
||||||
let value = entry.value.unwrap();
|
let value = entry.value.unwrap();
|
||||||
res.total += value.len();
|
for symbols in value.values() {
|
||||||
res.size += value.memory_size();
|
res.total += symbols.len();
|
||||||
|
res.size += symbols.memory_size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,22 +9,15 @@ use ra_db::{
|
||||||
SourceRootId,
|
SourceRootId,
|
||||||
};
|
};
|
||||||
use ra_prof::{memory_usage, profile, Bytes};
|
use ra_prof::{memory_usage, profile, Bytes};
|
||||||
use ra_syntax::SourceFile;
|
|
||||||
#[cfg(not(feature = "wasm"))]
|
|
||||||
use rayon::prelude::*;
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{symbol_index::SymbolsDatabase, RootDatabase};
|
||||||
symbol_index::{SymbolIndex, SymbolsDatabase},
|
|
||||||
RootDatabase,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct AnalysisChange {
|
pub struct AnalysisChange {
|
||||||
new_roots: Vec<(SourceRootId, bool)>,
|
new_roots: Vec<(SourceRootId, bool)>,
|
||||||
roots_changed: FxHashMap<SourceRootId, RootChange>,
|
roots_changed: FxHashMap<SourceRootId, RootChange>,
|
||||||
files_changed: Vec<(FileId, Arc<String>)>,
|
files_changed: Vec<(FileId, Arc<String>)>,
|
||||||
libraries_added: Vec<LibraryData>,
|
|
||||||
crate_graph: Option<CrateGraph>,
|
crate_graph: Option<CrateGraph>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +33,6 @@ impl fmt::Debug for AnalysisChange {
|
||||||
if !self.files_changed.is_empty() {
|
if !self.files_changed.is_empty() {
|
||||||
d.field("files_changed", &self.files_changed.len());
|
d.field("files_changed", &self.files_changed.len());
|
||||||
}
|
}
|
||||||
if !self.libraries_added.is_empty() {
|
|
||||||
d.field("libraries_added", &self.libraries_added.len());
|
|
||||||
}
|
|
||||||
if self.crate_graph.is_some() {
|
if self.crate_graph.is_some() {
|
||||||
d.field("crate_graph", &self.crate_graph);
|
d.field("crate_graph", &self.crate_graph);
|
||||||
}
|
}
|
||||||
|
@ -79,10 +69,6 @@ impl AnalysisChange {
|
||||||
self.roots_changed.entry(root_id).or_default().removed.push(file);
|
self.roots_changed.entry(root_id).or_default().removed.push(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_library(&mut self, data: LibraryData) {
|
|
||||||
self.libraries_added.push(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_crate_graph(&mut self, graph: CrateGraph) {
|
pub fn set_crate_graph(&mut self, graph: CrateGraph) {
|
||||||
self.crate_graph = Some(graph);
|
self.crate_graph = Some(graph);
|
||||||
}
|
}
|
||||||
|
@ -116,47 +102,6 @@ impl fmt::Debug for RootChange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LibraryData {
|
|
||||||
root_id: SourceRootId,
|
|
||||||
root_change: RootChange,
|
|
||||||
symbol_index: SymbolIndex,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for LibraryData {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
f.debug_struct("LibraryData")
|
|
||||||
.field("root_id", &self.root_id)
|
|
||||||
.field("root_change", &self.root_change)
|
|
||||||
.field("n_symbols", &self.symbol_index.len())
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LibraryData {
|
|
||||||
pub fn prepare(
|
|
||||||
root_id: SourceRootId,
|
|
||||||
files: Vec<(FileId, RelativePathBuf, Arc<String>)>,
|
|
||||||
) -> LibraryData {
|
|
||||||
let _p = profile("LibraryData::prepare");
|
|
||||||
|
|
||||||
#[cfg(not(feature = "wasm"))]
|
|
||||||
let iter = files.par_iter();
|
|
||||||
#[cfg(feature = "wasm")]
|
|
||||||
let iter = files.iter();
|
|
||||||
|
|
||||||
let symbol_index = SymbolIndex::for_files(iter.map(|(file_id, _, text)| {
|
|
||||||
let parse = SourceFile::parse(text);
|
|
||||||
(*file_id, parse)
|
|
||||||
}));
|
|
||||||
let mut root_change = RootChange::default();
|
|
||||||
root_change.added = files
|
|
||||||
.into_iter()
|
|
||||||
.map(|(file_id, path, text)| AddFile { file_id, path, text })
|
|
||||||
.collect();
|
|
||||||
LibraryData { root_id, root_change, symbol_index }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);
|
const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);
|
||||||
|
|
||||||
impl RootDatabase {
|
impl RootDatabase {
|
||||||
|
@ -171,6 +116,7 @@ impl RootDatabase {
|
||||||
log::info!("apply_change {:?}", change);
|
log::info!("apply_change {:?}", change);
|
||||||
if !change.new_roots.is_empty() {
|
if !change.new_roots.is_empty() {
|
||||||
let mut local_roots = Vec::clone(&self.local_roots());
|
let mut local_roots = Vec::clone(&self.local_roots());
|
||||||
|
let mut libraries = Vec::clone(&self.library_roots());
|
||||||
for (root_id, is_local) in change.new_roots {
|
for (root_id, is_local) in change.new_roots {
|
||||||
let root =
|
let root =
|
||||||
if is_local { SourceRoot::new_local() } else { SourceRoot::new_library() };
|
if is_local { SourceRoot::new_local() } else { SourceRoot::new_library() };
|
||||||
|
@ -178,9 +124,12 @@ impl RootDatabase {
|
||||||
self.set_source_root_with_durability(root_id, Arc::new(root), durability);
|
self.set_source_root_with_durability(root_id, Arc::new(root), durability);
|
||||||
if is_local {
|
if is_local {
|
||||||
local_roots.push(root_id);
|
local_roots.push(root_id);
|
||||||
|
} else {
|
||||||
|
libraries.push(root_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
|
self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
|
||||||
|
self.set_library_roots_with_durability(Arc::new(libraries), Durability::HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (root_id, root_change) in change.roots_changed {
|
for (root_id, root_change) in change.roots_changed {
|
||||||
|
@ -192,24 +141,6 @@ impl RootDatabase {
|
||||||
let durability = durability(&source_root);
|
let durability = durability(&source_root);
|
||||||
self.set_file_text_with_durability(file_id, text, durability)
|
self.set_file_text_with_durability(file_id, text, durability)
|
||||||
}
|
}
|
||||||
if !change.libraries_added.is_empty() {
|
|
||||||
let mut libraries = Vec::clone(&self.library_roots());
|
|
||||||
for library in change.libraries_added {
|
|
||||||
libraries.push(library.root_id);
|
|
||||||
self.set_source_root_with_durability(
|
|
||||||
library.root_id,
|
|
||||||
Arc::new(SourceRoot::new_library()),
|
|
||||||
Durability::HIGH,
|
|
||||||
);
|
|
||||||
self.set_library_symbols_with_durability(
|
|
||||||
library.root_id,
|
|
||||||
Arc::new(library.symbol_index),
|
|
||||||
Durability::HIGH,
|
|
||||||
);
|
|
||||||
self.apply_root_change(library.root_id, library.root_change);
|
|
||||||
}
|
|
||||||
self.set_library_roots_with_durability(Arc::new(libraries), Durability::HIGH);
|
|
||||||
}
|
|
||||||
if let Some(crate_graph) = change.crate_graph {
|
if let Some(crate_graph) = change.crate_graph {
|
||||||
self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
|
self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,15 @@ use ra_db::{
|
||||||
salsa::{self, ParallelDatabase},
|
salsa::{self, ParallelDatabase},
|
||||||
CrateId, FileId, SourceDatabaseExt, SourceRootId,
|
CrateId, FileId, SourceDatabaseExt, SourceRootId,
|
||||||
};
|
};
|
||||||
|
use ra_prof::profile;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, NameOwner},
|
ast::{self, NameOwner},
|
||||||
match_ast, AstNode, Parse, SmolStr, SourceFile,
|
match_ast, AstNode, Parse, SmolStr, SourceFile,
|
||||||
SyntaxKind::{self, *},
|
SyntaxKind::{self, *},
|
||||||
SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent,
|
SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent,
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "wasm"))]
|
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::RootDatabase;
|
use crate::RootDatabase;
|
||||||
|
|
||||||
|
@ -86,10 +87,9 @@ impl Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[salsa::query_group(SymbolsDatabaseStorage)]
|
#[salsa::query_group(SymbolsDatabaseStorage)]
|
||||||
pub trait SymbolsDatabase: hir::db::HirDatabase {
|
pub trait SymbolsDatabase: hir::db::HirDatabase + SourceDatabaseExt + ParallelDatabase {
|
||||||
fn file_symbols(&self, file_id: FileId) -> Arc<SymbolIndex>;
|
fn file_symbols(&self, file_id: FileId) -> Arc<SymbolIndex>;
|
||||||
#[salsa::input]
|
fn library_symbols(&self) -> Arc<FxHashMap<SourceRootId, SymbolIndex>>;
|
||||||
fn library_symbols(&self, id: SourceRootId) -> Arc<SymbolIndex>;
|
|
||||||
/// The set of "local" (that is, from the current workspace) roots.
|
/// The set of "local" (that is, from the current workspace) roots.
|
||||||
/// Files in local roots are assumed to change frequently.
|
/// Files in local roots are assumed to change frequently.
|
||||||
#[salsa::input]
|
#[salsa::input]
|
||||||
|
@ -100,6 +100,29 @@ pub trait SymbolsDatabase: hir::db::HirDatabase {
|
||||||
fn library_roots(&self) -> Arc<Vec<SourceRootId>>;
|
fn library_roots(&self) -> Arc<Vec<SourceRootId>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn library_symbols(
|
||||||
|
db: &(impl SymbolsDatabase + ParallelDatabase),
|
||||||
|
) -> Arc<FxHashMap<SourceRootId, SymbolIndex>> {
|
||||||
|
let _p = profile("library_symbols");
|
||||||
|
|
||||||
|
let roots = db.library_roots();
|
||||||
|
let res = roots
|
||||||
|
.iter()
|
||||||
|
.map(|&root_id| {
|
||||||
|
let root = db.source_root(root_id);
|
||||||
|
let files = root
|
||||||
|
.walk()
|
||||||
|
.map(|it| (it, SourceDatabaseExt::file_text(db, it)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let symbol_index = SymbolIndex::for_files(
|
||||||
|
files.into_par_iter().map(|(file, text)| (file, SourceFile::parse(&text))),
|
||||||
|
);
|
||||||
|
(root_id, symbol_index)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Arc::new(res)
|
||||||
|
}
|
||||||
|
|
||||||
fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> {
|
fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> {
|
||||||
db.check_canceled();
|
db.check_canceled();
|
||||||
let parse = db.parse(file_id);
|
let parse = db.parse(file_id);
|
||||||
|
@ -112,9 +135,9 @@ fn file_symbols(db: &impl SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
|
/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
|
||||||
struct Snap(salsa::Snapshot<RootDatabase>);
|
struct Snap<DB>(DB);
|
||||||
impl Clone for Snap {
|
impl<DB: ParallelDatabase> Clone for Snap<salsa::Snapshot<DB>> {
|
||||||
fn clone(&self) -> Snap {
|
fn clone(&self) -> Snap<salsa::Snapshot<DB>> {
|
||||||
Snap(self.0.snapshot())
|
Snap(self.0.snapshot())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,19 +166,11 @@ impl Clone for Snap {
|
||||||
pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
|
pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
|
||||||
let _p = ra_prof::profile("world_symbols").detail(|| query.query.clone());
|
let _p = ra_prof::profile("world_symbols").detail(|| query.query.clone());
|
||||||
|
|
||||||
let buf: Vec<Arc<SymbolIndex>> = if query.libs {
|
let tmp1;
|
||||||
let snap = Snap(db.snapshot());
|
let tmp2;
|
||||||
#[cfg(not(feature = "wasm"))]
|
let buf: Vec<&SymbolIndex> = if query.libs {
|
||||||
let buf = db
|
tmp1 = db.library_symbols();
|
||||||
.library_roots()
|
tmp1.values().collect()
|
||||||
.par_iter()
|
|
||||||
.map_with(snap, |db, &lib_id| db.0.library_symbols(lib_id))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
#[cfg(feature = "wasm")]
|
|
||||||
let buf = db.library_roots().iter().map(|&lib_id| snap.0.library_symbols(lib_id)).collect();
|
|
||||||
|
|
||||||
buf
|
|
||||||
} else {
|
} else {
|
||||||
let mut files = Vec::new();
|
let mut files = Vec::new();
|
||||||
for &root in db.local_roots().iter() {
|
for &root in db.local_roots().iter() {
|
||||||
|
@ -164,14 +179,11 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let snap = Snap(db.snapshot());
|
let snap = Snap(db.snapshot());
|
||||||
#[cfg(not(feature = "wasm"))]
|
tmp2 = files
|
||||||
let buf =
|
.par_iter()
|
||||||
files.par_iter().map_with(snap, |db, &file_id| db.0.file_symbols(file_id)).collect();
|
.map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
#[cfg(feature = "wasm")]
|
tmp2.iter().map(|it| &**it).collect()
|
||||||
let buf = files.iter().map(|&file_id| snap.0.file_symbols(file_id)).collect();
|
|
||||||
|
|
||||||
buf
|
|
||||||
};
|
};
|
||||||
query.search(&buf)
|
query.search(&buf)
|
||||||
}
|
}
|
||||||
|
@ -191,14 +203,11 @@ pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<Fil
|
||||||
|
|
||||||
let snap = Snap(db.snapshot());
|
let snap = Snap(db.snapshot());
|
||||||
|
|
||||||
#[cfg(not(feature = "wasm"))]
|
|
||||||
let buf = files
|
let buf = files
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
|
.map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
let buf = buf.iter().map(|it| &**it).collect::<Vec<_>>();
|
||||||
#[cfg(feature = "wasm")]
|
|
||||||
let buf = files.iter().map(|&file_id| snap.0.file_symbols(file_id)).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
query.search(&buf)
|
query.search(&buf)
|
||||||
}
|
}
|
||||||
|
@ -245,12 +254,8 @@ impl SymbolIndex {
|
||||||
lhs_chars.cmp(rhs_chars)
|
lhs_chars.cmp(rhs_chars)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "wasm"))]
|
|
||||||
symbols.par_sort_by(cmp);
|
symbols.par_sort_by(cmp);
|
||||||
|
|
||||||
#[cfg(feature = "wasm")]
|
|
||||||
symbols.sort_by(cmp);
|
|
||||||
|
|
||||||
let mut builder = fst::MapBuilder::memory();
|
let mut builder = fst::MapBuilder::memory();
|
||||||
|
|
||||||
let mut last_batch_start = 0;
|
let mut last_batch_start = 0;
|
||||||
|
@ -284,7 +289,6 @@ impl SymbolIndex {
|
||||||
self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>()
|
self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "wasm"))]
|
|
||||||
pub(crate) fn for_files(
|
pub(crate) fn for_files(
|
||||||
files: impl ParallelIterator<Item = (FileId, Parse<ast::SourceFile>)>,
|
files: impl ParallelIterator<Item = (FileId, Parse<ast::SourceFile>)>,
|
||||||
) -> SymbolIndex {
|
) -> SymbolIndex {
|
||||||
|
@ -294,16 +298,6 @@ impl SymbolIndex {
|
||||||
SymbolIndex::new(symbols)
|
SymbolIndex::new(symbols)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wasm")]
|
|
||||||
pub(crate) fn for_files(
|
|
||||||
files: impl Iterator<Item = (FileId, Parse<ast::SourceFile>)>,
|
|
||||||
) -> SymbolIndex {
|
|
||||||
let symbols = files
|
|
||||||
.flat_map(|(file_id, file)| source_file_to_file_symbols(&file.tree(), file_id))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
SymbolIndex::new(symbols)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn range_to_map_value(start: usize, end: usize) -> u64 {
|
fn range_to_map_value(start: usize, end: usize) -> u64 {
|
||||||
debug_assert![start <= (std::u32::MAX as usize)];
|
debug_assert![start <= (std::u32::MAX as usize)];
|
||||||
debug_assert![end <= (std::u32::MAX as usize)];
|
debug_assert![end <= (std::u32::MAX as usize)];
|
||||||
|
@ -319,7 +313,7 @@ impl SymbolIndex {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Query {
|
impl Query {
|
||||||
pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<FileSymbol> {
|
pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> {
|
||||||
let mut op = fst::map::OpBuilder::new();
|
let mut op = fst::map::OpBuilder::new();
|
||||||
for file_symbols in indices.iter() {
|
for file_symbols in indices.iter() {
|
||||||
let automaton = fst::automaton::Subsequence::new(&self.lowercased);
|
let automaton = fst::automaton::Subsequence::new(&self.lowercased);
|
||||||
|
|
|
@ -12,12 +12,9 @@ use crossbeam_channel::{unbounded, Receiver};
|
||||||
use lsp_types::Url;
|
use lsp_types::Url;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use ra_flycheck::{Flycheck, FlycheckConfig};
|
use ra_flycheck::{Flycheck, FlycheckConfig};
|
||||||
use ra_ide::{
|
use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, SourceRootId};
|
||||||
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId,
|
|
||||||
};
|
|
||||||
use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target};
|
use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target};
|
||||||
use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsTask, Watch};
|
use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsTask, Watch};
|
||||||
use relative_path::RelativePathBuf;
|
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -195,32 +192,18 @@ impl GlobalState {
|
||||||
|
|
||||||
/// Returns a vec of libraries
|
/// Returns a vec of libraries
|
||||||
/// FIXME: better API here
|
/// FIXME: better API here
|
||||||
pub fn process_changes(
|
pub fn process_changes(&mut self, roots_scanned: &mut usize) -> bool {
|
||||||
&mut self,
|
|
||||||
roots_scanned: &mut usize,
|
|
||||||
) -> Option<Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc<String>)>)>> {
|
|
||||||
let changes = self.vfs.write().commit_changes();
|
let changes = self.vfs.write().commit_changes();
|
||||||
if changes.is_empty() {
|
if changes.is_empty() {
|
||||||
return None;
|
return false;
|
||||||
}
|
}
|
||||||
let mut libs = Vec::new();
|
|
||||||
let mut change = AnalysisChange::new();
|
let mut change = AnalysisChange::new();
|
||||||
for c in changes {
|
for c in changes {
|
||||||
match c {
|
match c {
|
||||||
VfsChange::AddRoot { root, files } => {
|
VfsChange::AddRoot { root, files } => {
|
||||||
let root_path = self.vfs.read().root2path(root);
|
*roots_scanned += 1;
|
||||||
let is_local = self.local_roots.iter().any(|r| root_path.starts_with(r));
|
for (file, path, text) in files {
|
||||||
if is_local {
|
change.add_file(SourceRootId(root.0), FileId(file.0), path, text);
|
||||||
*roots_scanned += 1;
|
|
||||||
for (file, path, text) in files {
|
|
||||||
change.add_file(SourceRootId(root.0), FileId(file.0), path, text);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let files = files
|
|
||||||
.into_iter()
|
|
||||||
.map(|(vfsfile, path, text)| (FileId(vfsfile.0), path, text))
|
|
||||||
.collect();
|
|
||||||
libs.push((SourceRootId(root.0), files));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VfsChange::AddFile { root, file, path, text } => {
|
VfsChange::AddFile { root, file, path, text } => {
|
||||||
|
@ -235,13 +218,7 @@ impl GlobalState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.analysis_host.apply_change(change);
|
self.analysis_host.apply_change(change);
|
||||||
Some(libs)
|
true
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_lib(&mut self, data: LibraryData) {
|
|
||||||
let mut change = AnalysisChange::new();
|
|
||||||
change.add_library(data);
|
|
||||||
self.analysis_host.apply_change(change);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn snapshot(&self) -> GlobalStateSnapshot {
|
pub fn snapshot(&self) -> GlobalStateSnapshot {
|
||||||
|
|
|
@ -24,11 +24,10 @@ use lsp_types::{
|
||||||
WorkDoneProgressReport,
|
WorkDoneProgressReport,
|
||||||
};
|
};
|
||||||
use ra_flycheck::{CheckTask, Status};
|
use ra_flycheck::{CheckTask, Status};
|
||||||
use ra_ide::{Canceled, FileId, LibraryData, LineIndex, SourceRootId};
|
use ra_ide::{Canceled, FileId, LineIndex};
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use ra_project_model::{PackageRoot, ProjectWorkspace};
|
use ra_project_model::{PackageRoot, ProjectWorkspace};
|
||||||
use ra_vfs::{VfsTask, Watch};
|
use ra_vfs::{VfsTask, Watch};
|
||||||
use relative_path::RelativePathBuf;
|
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
use threadpool::ThreadPool;
|
use threadpool::ThreadPool;
|
||||||
|
@ -174,12 +173,10 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
|
||||||
|
|
||||||
let pool = ThreadPool::default();
|
let pool = ThreadPool::default();
|
||||||
let (task_sender, task_receiver) = unbounded::<Task>();
|
let (task_sender, task_receiver) = unbounded::<Task>();
|
||||||
let (libdata_sender, libdata_receiver) = unbounded::<LibraryData>();
|
|
||||||
|
|
||||||
log::info!("server initialized, serving requests");
|
log::info!("server initialized, serving requests");
|
||||||
{
|
{
|
||||||
let task_sender = task_sender;
|
let task_sender = task_sender;
|
||||||
let libdata_sender = libdata_sender;
|
|
||||||
loop {
|
loop {
|
||||||
log::trace!("selecting");
|
log::trace!("selecting");
|
||||||
let event = select! {
|
let event = select! {
|
||||||
|
@ -192,7 +189,6 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
|
||||||
Ok(task) => Event::Vfs(task),
|
Ok(task) => Event::Vfs(task),
|
||||||
Err(RecvError) => return Err("vfs died".into()),
|
Err(RecvError) => return Err("vfs died".into()),
|
||||||
},
|
},
|
||||||
recv(libdata_receiver) -> data => Event::Lib(data.unwrap()),
|
|
||||||
recv(global_state.flycheck.as_ref().map_or(&never(), |it| &it.task_recv)) -> task => match task {
|
recv(global_state.flycheck.as_ref().map_or(&never(), |it| &it.task_recv)) -> task => match task {
|
||||||
Ok(task) => Event::CheckWatcher(task),
|
Ok(task) => Event::CheckWatcher(task),
|
||||||
Err(RecvError) => return Err("check watcher died".into()),
|
Err(RecvError) => return Err("check watcher died".into()),
|
||||||
|
@ -203,15 +199,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
loop_turn(
|
loop_turn(&pool, &task_sender, &connection, &mut global_state, &mut loop_state, event)?;
|
||||||
&pool,
|
|
||||||
&task_sender,
|
|
||||||
&libdata_sender,
|
|
||||||
&connection,
|
|
||||||
&mut global_state,
|
|
||||||
&mut loop_state,
|
|
||||||
event,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
global_state.analysis_host.request_cancellation();
|
global_state.analysis_host.request_cancellation();
|
||||||
|
@ -219,7 +207,6 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
|
||||||
task_receiver.into_iter().for_each(|task| {
|
task_receiver.into_iter().for_each(|task| {
|
||||||
on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut global_state)
|
on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut global_state)
|
||||||
});
|
});
|
||||||
libdata_receiver.into_iter().for_each(drop);
|
|
||||||
log::info!("...tasks have finished");
|
log::info!("...tasks have finished");
|
||||||
log::info!("joining threadpool...");
|
log::info!("joining threadpool...");
|
||||||
pool.join();
|
pool.join();
|
||||||
|
@ -243,7 +230,6 @@ enum Event {
|
||||||
Msg(Message),
|
Msg(Message),
|
||||||
Task(Task),
|
Task(Task),
|
||||||
Vfs(VfsTask),
|
Vfs(VfsTask),
|
||||||
Lib(LibraryData),
|
|
||||||
CheckWatcher(CheckTask),
|
CheckWatcher(CheckTask),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +265,6 @@ impl fmt::Debug for Event {
|
||||||
Event::Msg(it) => fmt::Debug::fmt(it, f),
|
Event::Msg(it) => fmt::Debug::fmt(it, f),
|
||||||
Event::Task(it) => fmt::Debug::fmt(it, f),
|
Event::Task(it) => fmt::Debug::fmt(it, f),
|
||||||
Event::Vfs(it) => fmt::Debug::fmt(it, f),
|
Event::Vfs(it) => fmt::Debug::fmt(it, f),
|
||||||
Event::Lib(it) => fmt::Debug::fmt(it, f),
|
|
||||||
Event::CheckWatcher(it) => fmt::Debug::fmt(it, f),
|
Event::CheckWatcher(it) => fmt::Debug::fmt(it, f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,10 +276,6 @@ struct LoopState {
|
||||||
pending_responses: FxHashSet<RequestId>,
|
pending_responses: FxHashSet<RequestId>,
|
||||||
pending_requests: PendingRequests,
|
pending_requests: PendingRequests,
|
||||||
subscriptions: Subscriptions,
|
subscriptions: Subscriptions,
|
||||||
// We try not to index more than MAX_IN_FLIGHT_LIBS libraries at the same
|
|
||||||
// time to always have a thread ready to react to input.
|
|
||||||
in_flight_libraries: usize,
|
|
||||||
pending_libraries: Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc<String>)>)>,
|
|
||||||
workspace_loaded: bool,
|
workspace_loaded: bool,
|
||||||
roots_progress_reported: Option<usize>,
|
roots_progress_reported: Option<usize>,
|
||||||
roots_scanned: usize,
|
roots_scanned: usize,
|
||||||
|
@ -315,7 +296,6 @@ impl LoopState {
|
||||||
fn loop_turn(
|
fn loop_turn(
|
||||||
pool: &ThreadPool,
|
pool: &ThreadPool,
|
||||||
task_sender: &Sender<Task>,
|
task_sender: &Sender<Task>,
|
||||||
libdata_sender: &Sender<LibraryData>,
|
|
||||||
connection: &Connection,
|
connection: &Connection,
|
||||||
global_state: &mut GlobalState,
|
global_state: &mut GlobalState,
|
||||||
loop_state: &mut LoopState,
|
loop_state: &mut LoopState,
|
||||||
|
@ -339,12 +319,6 @@ fn loop_turn(
|
||||||
Event::Vfs(task) => {
|
Event::Vfs(task) => {
|
||||||
global_state.vfs.write().handle_task(task);
|
global_state.vfs.write().handle_task(task);
|
||||||
}
|
}
|
||||||
Event::Lib(lib) => {
|
|
||||||
global_state.add_lib(lib);
|
|
||||||
global_state.maybe_collect_garbage();
|
|
||||||
loop_state.in_flight_libraries -= 1;
|
|
||||||
loop_state.roots_scanned += 1;
|
|
||||||
}
|
|
||||||
Event::CheckWatcher(task) => on_check_task(task, global_state, task_sender)?,
|
Event::CheckWatcher(task) => on_check_task(task, global_state, task_sender)?,
|
||||||
Event::Msg(msg) => match msg {
|
Event::Msg(msg) => match msg {
|
||||||
Message::Request(req) => on_request(
|
Message::Request(req) => on_request(
|
||||||
|
@ -390,36 +364,12 @@ fn loop_turn(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut state_changed = false;
|
let mut state_changed = global_state.process_changes(&mut loop_state.roots_scanned);
|
||||||
if let Some(changes) = global_state.process_changes(&mut loop_state.roots_scanned) {
|
|
||||||
state_changed = true;
|
|
||||||
loop_state.pending_libraries.extend(changes);
|
|
||||||
}
|
|
||||||
|
|
||||||
let max_in_flight_libs = pool.max_count().saturating_sub(2).max(1);
|
|
||||||
while loop_state.in_flight_libraries < max_in_flight_libs {
|
|
||||||
let (root, files) = match loop_state.pending_libraries.pop() {
|
|
||||||
Some(it) => it,
|
|
||||||
None => break,
|
|
||||||
};
|
|
||||||
|
|
||||||
loop_state.in_flight_libraries += 1;
|
|
||||||
let sender = libdata_sender.clone();
|
|
||||||
pool.execute(move || {
|
|
||||||
log::info!("indexing {:?} ... ", root);
|
|
||||||
let data = LibraryData::prepare(root, files);
|
|
||||||
sender.send(data).unwrap();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let show_progress =
|
let show_progress =
|
||||||
!loop_state.workspace_loaded && global_state.config.client_caps.work_done_progress;
|
!loop_state.workspace_loaded && global_state.config.client_caps.work_done_progress;
|
||||||
|
|
||||||
if !loop_state.workspace_loaded
|
if !loop_state.workspace_loaded && loop_state.roots_scanned == loop_state.roots_total {
|
||||||
&& loop_state.roots_scanned == loop_state.roots_total
|
|
||||||
&& loop_state.pending_libraries.is_empty()
|
|
||||||
&& loop_state.in_flight_libraries == 0
|
|
||||||
{
|
|
||||||
state_changed = true;
|
state_changed = true;
|
||||||
loop_state.workspace_loaded = true;
|
loop_state.workspace_loaded = true;
|
||||||
if let Some(flycheck) = &global_state.flycheck {
|
if let Some(flycheck) = &global_state.flycheck {
|
||||||
|
|
Loading…
Reference in a new issue