Rename analyzer classes

This commit is contained in:
Shuhei Takahashi 2025-12-13 14:59:08 +09:00
parent fbb15967b0
commit ab0a77db5b
17 changed files with 99 additions and 117 deletions

View file

@ -60,18 +60,18 @@ mod tests;
mod toplevel;
mod utils;
pub struct AnalyzerSet {
pub struct Analyzer {
storage: Arc<Mutex<DocumentStorage>>,
finder: WorkspaceFinder,
analyzers: RwLock<BTreeMap<PathBuf, Arc<Mutex<Analyzer>>>>,
workspace_finder: WorkspaceFinder,
workspaces: RwLock<BTreeMap<PathBuf, Arc<Mutex<WorkspaceAnalyzer>>>>,
}
impl AnalyzerSet {
pub fn new(storage: &Arc<Mutex<DocumentStorage>>, finder: WorkspaceFinder) -> Self {
impl Analyzer {
pub fn new(storage: &Arc<Mutex<DocumentStorage>>, workspace_finder: WorkspaceFinder) -> Self {
Self {
storage: storage.clone(),
finder,
analyzers: Default::default(),
workspace_finder,
workspaces: Default::default(),
}
}
@ -81,7 +81,7 @@ impl AnalyzerSet {
request_time: Instant,
) -> Result<Pin<Arc<AnalyzedFile>>> {
Ok(self
.get_for(path)?
.workspace_for(path)?
.lock()
.unwrap()
.analyze_file(path, request_time))
@ -94,35 +94,27 @@ impl AnalyzerSet {
request_time: Instant,
) -> Result<Environment> {
Ok(self
.get_for(&file.document.path)?
.workspace_for(&file.document.path)?
.lock()
.unwrap()
.analyze_environment(file, pos, request_time))
}
pub fn cached_files(&self, workspace_root: &Path) -> Vec<Pin<Arc<AnalyzedFile>>> {
let Some(analyzer) = self.analyzers.read().unwrap().get(workspace_root).cloned() else {
return Vec::new();
};
let cached_files = analyzer.lock().unwrap().cached_files();
cached_files
pub fn workspaces(&self) -> BTreeMap<PathBuf, Arc<Mutex<WorkspaceAnalyzer>>> {
self.workspaces.read().unwrap().clone()
}
pub fn workspace_roots(&self) -> Vec<PathBuf> {
self.analyzers.read().unwrap().keys().cloned().collect()
pub fn workspace_finder(&self) -> &WorkspaceFinder {
&self.workspace_finder
}
pub fn finder(&self) -> &WorkspaceFinder {
&self.finder
}
pub fn get_for(&self, path: &Path) -> Result<Arc<Mutex<Analyzer>>> {
pub fn workspace_for(&self, path: &Path) -> Result<Arc<Mutex<WorkspaceAnalyzer>>> {
if !path.is_absolute() {
return Err(Error::General("Path must be absolute".to_string()));
}
let workspace_root = self
.finder
.workspace_finder
.find_for(path)
.ok_or(Error::General("Workspace not found".to_string()))?;
let dot_gn_path = workspace_root.join(".gn");
@ -132,7 +124,7 @@ impl AnalyzerSet {
};
{
let read_lock = self.analyzers.read().unwrap();
let read_lock = self.workspaces.read().unwrap();
if let Some(analyzer) = read_lock.get(workspace_root) {
if analyzer.lock().unwrap().context().dot_gn_version == dot_gn_version {
return Ok(analyzer.clone());
@ -152,9 +144,9 @@ impl AnalyzerSet {
build_config,
};
let analyzer = Arc::new(Mutex::new(Analyzer::new(&context, &self.storage)));
let analyzer = Arc::new(Mutex::new(WorkspaceAnalyzer::new(&context, &self.storage)));
let mut write_lock = self.analyzers.write().unwrap();
let mut write_lock = self.workspaces.write().unwrap();
Ok(write_lock
.entry(workspace_root.to_path_buf())
.or_insert(analyzer)
@ -162,14 +154,13 @@ impl AnalyzerSet {
}
}
pub struct Analyzer {
pub struct WorkspaceAnalyzer {
context: WorkspaceContext,
storage: Arc<Mutex<DocumentStorage>>,
#[allow(clippy::type_complexity)]
cache: BTreeMap<PathBuf, Pin<Arc<AnalyzedFile>>>,
}
impl Analyzer {
impl WorkspaceAnalyzer {
pub fn new(context: &WorkspaceContext, storage: &Arc<Mutex<DocumentStorage>>) -> Self {
Self {
context: context.clone(),

View file

@ -20,7 +20,7 @@ use std::{
};
use crate::{
analyzer::AnalyzerSet,
analyzer::Analyzer,
common::{storage::DocumentStorage, testutils::testdata, workspace::WorkspaceFinder},
parser::Statement,
};
@ -28,9 +28,9 @@ use crate::{
#[test]
fn test_analyze_smoke() {
let storage = Arc::new(Mutex::new(DocumentStorage::new()));
let analyzers = AnalyzerSet::new(&storage, WorkspaceFinder::new(None));
let analyzer = Analyzer::new(&storage, WorkspaceFinder::new(None));
let file = analyzers
let file = analyzer
.analyze_file(&testdata("workspaces/smoke/BUILD.gn"), Instant::now())
.unwrap();
@ -42,7 +42,7 @@ fn test_analyze_smoke() {
.all(|s| !matches!(s, Statement::Error(_))));
// Inspect the environment.
let environment = analyzers
let environment = analyzer
.analyze_environment(&file, 0, Instant::now())
.unwrap();
assert!(environment.variables.contains_key("enable_opt"));
@ -54,12 +54,12 @@ fn test_analyze_smoke() {
fn test_analyze_cycles() {
let request_time = Instant::now();
let storage = Arc::new(Mutex::new(DocumentStorage::new()));
let analyzers = AnalyzerSet::new(&storage, WorkspaceFinder::new(None));
let analyzer = Analyzer::new(&storage, WorkspaceFinder::new(None));
assert!(analyzers
assert!(analyzer
.analyze_file(&testdata("workspaces/cycles/ok1.gni"), request_time)
.is_ok());
assert!(analyzers
assert!(analyzer
.analyze_file(&testdata("workspaces/cycles/bad1.gni"), request_time)
.is_ok());
}

View file

@ -21,13 +21,13 @@ use std::{
use futures::future::join_all;
use crate::{
analyzer::AnalyzerSet,
analyzer::Analyzer,
common::{storage::DocumentStorage, utils::find_gn_files, workspace::WorkspaceFinder},
};
pub async fn run_bench(workspace_root: &Path) {
let storage = Arc::new(Mutex::new(DocumentStorage::new()));
let analyzers = Arc::new(AnalyzerSet::new(
let analyzer = Arc::new(Analyzer::new(
&storage,
WorkspaceFinder::new(Some(workspace_root)),
));
@ -37,9 +37,9 @@ pub async fn run_bench(workspace_root: &Path) {
let mut tasks = Vec::new();
for path in find_gn_files(workspace_root) {
let analyzers = analyzers.clone();
let analyzer = analyzer.clone();
tasks.push(tokio::spawn(async move {
analyzers.analyze_file(&path, start_time).ok();
analyzer.analyze_file(&path, start_time).ok();
eprint!(".");
}));
count += 1;

View file

@ -17,7 +17,7 @@ use std::time::Instant;
use tower_lsp::lsp_types::Diagnostic;
use crate::{
analyzer::{AnalyzedFile, AnalyzerSet},
analyzer::{AnalyzedFile, Analyzer},
common::config::Configurations,
diagnostics::{syntax::collect_syntax_errors, undefined::collect_undefined_identifiers},
};
@ -28,7 +28,7 @@ mod undefined;
pub fn compute_diagnostics(
file: &AnalyzedFile,
config: &Configurations,
analyzers: &AnalyzerSet,
analyzer: &Analyzer,
request_time: Instant,
) -> Vec<Diagnostic> {
let mut diagnostics = Vec::new();
@ -38,7 +38,7 @@ pub fn compute_diagnostics(
&mut diagnostics,
);
if config.experimental.undefined_variable_analysis {
collect_undefined_identifiers(file, analyzers, request_time, &mut diagnostics);
collect_undefined_identifiers(file, analyzer, request_time, &mut diagnostics);
}
diagnostics
}

View file

@ -22,8 +22,8 @@ use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
use crate::{
analyzer::{
AnalyzedBlock, AnalyzedFile, AnalyzedStatement, AnalyzerSet, TopLevelStatementsExt,
Variable, VariableMap,
AnalyzedBlock, AnalyzedFile, AnalyzedStatement, Analyzer, TopLevelStatementsExt, Variable,
VariableMap,
},
common::{builtins::BUILTINS, utils::is_exported},
parser::{Expr, Identifier, LValue, PrimaryExpr},
@ -106,7 +106,7 @@ impl<'i> PrimaryExpr<'i> {
fn collect_undefined_identifiers(
&self,
file: &'i AnalyzedFile,
analyzers: &AnalyzerSet,
analyzer: &Analyzer,
request_time: Instant,
tracker: &VariablesTracker<'i, '_>,
diagnostics: &mut Vec<Diagnostic>,
@ -121,7 +121,7 @@ impl<'i> PrimaryExpr<'i> {
for expr in &call.args {
expr.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -134,7 +134,7 @@ impl<'i> PrimaryExpr<'i> {
.collect_undefined_identifiers(file, tracker, diagnostics);
array_access.index.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -148,7 +148,7 @@ impl<'i> PrimaryExpr<'i> {
PrimaryExpr::ParenExpr(paren_expr) => {
paren_expr.expr.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -158,7 +158,7 @@ impl<'i> PrimaryExpr<'i> {
for expr in &list_literal.values {
expr.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -177,7 +177,7 @@ impl<'i> Expr<'i> {
fn collect_undefined_identifiers(
&self,
file: &'i AnalyzedFile,
analyzers: &AnalyzerSet,
analyzer: &Analyzer,
request_time: Instant,
tracker: &VariablesTracker<'i, '_>,
diagnostics: &mut Vec<Diagnostic>,
@ -186,7 +186,7 @@ impl<'i> Expr<'i> {
Expr::Primary(primary_expr) => {
primary_expr.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -195,7 +195,7 @@ impl<'i> Expr<'i> {
Expr::Unary(unary_expr) => {
unary_expr.expr.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -204,14 +204,14 @@ impl<'i> Expr<'i> {
Expr::Binary(binary_expr) => {
binary_expr.lhs.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
);
binary_expr.rhs.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -225,7 +225,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
fn collect_undefined_identifiers(
&self,
file: &AnalyzedFile,
analyzers: &AnalyzerSet,
analyzer: &Analyzer,
request_time: Instant,
tracker: &mut VariablesTracker<'i, 'p>,
diagnostics: &mut Vec<Diagnostic>,
@ -237,7 +237,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
if let LValue::ArrayAccess(array_access) = &assignment.assignment.lvalue {
array_access.index.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -245,7 +245,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
}
assignment.assignment.rvalue.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -259,7 +259,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
.condition
.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -275,7 +275,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
AnalyzedStatement::Foreach(foreach) => {
foreach.loop_items.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -285,7 +285,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
for expr in &forward_variables_from.call.args {
expr.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -296,7 +296,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
for expr in &target.call.args {
expr.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -307,7 +307,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
for expr in &template.call.args {
expr.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -323,7 +323,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
for expr in &builtin_call.call.args {
expr.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
tracker,
diagnostics,
@ -337,7 +337,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
for subscope in statement.subscopes() {
subscope.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
&mut tracker.clone(),
diagnostics,
@ -365,7 +365,7 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
}
}
AnalyzedStatement::Import(import) => {
if let Ok(analyzer) = analyzers.get_for(&import.path) {
if let Ok(analyzer) = analyzer.workspace_for(&import.path) {
let mut analyzer = analyzer.lock().unwrap();
let imported_file = analyzer.analyze_file(&import.path, request_time);
let imported_environment = analyzer.analyze_environment(
@ -393,13 +393,13 @@ impl<'i, 'p> AnalyzedBlock<'i, 'p> {
pub fn collect_undefined_identifiers(
file: &AnalyzedFile,
analyzers: &AnalyzerSet,
analyzer: &Analyzer,
request_time: Instant,
diagnostics: &mut Vec<Diagnostic>,
) {
file.analyzed_root.collect_undefined_identifiers(
file,
analyzers,
analyzer,
request_time,
&mut VariablesTracker::new(),
diagnostics,

View file

@ -38,7 +38,7 @@ pub async fn index(context: &RequestContext, workspace_root: &Path) {
for path in find_gn_files(workspace_root) {
context
.analyzers
.analyzer
.analyze_file(&path, context.request_time)
.ok();
count += 1;

View file

@ -35,7 +35,7 @@ use tower_lsp::{
};
use crate::{
analyzer::AnalyzerSet,
analyzer::Analyzer,
common::{
client::TestableClient, error::RpcResult, storage::DocumentStorage, utils::AsyncSignal,
workspace::WorkspaceFinder,
@ -47,7 +47,7 @@ mod providers;
struct ServerContext {
pub storage: Arc<Mutex<DocumentStorage>>,
pub analyzers: OnceLock<Arc<AnalyzerSet>>,
pub analyzer: OnceLock<Arc<Analyzer>>,
pub indexed: Arc<Mutex<BTreeMap<PathBuf, AsyncSignal>>>,
pub client: TestableClient,
}
@ -56,7 +56,7 @@ impl ServerContext {
pub fn new(storage: Arc<Mutex<DocumentStorage>>, client: TestableClient) -> Self {
Self {
storage,
analyzers: OnceLock::new(),
analyzer: OnceLock::new(),
indexed: Default::default(),
client,
}
@ -65,14 +65,14 @@ impl ServerContext {
#[cfg(test)]
pub fn new_for_testing() -> Self {
let storage = Arc::new(Mutex::new(DocumentStorage::new()));
let analyzers = OnceLock::new();
let _ = analyzers.set(Arc::new(AnalyzerSet::new(
let analyzer = OnceLock::new();
let _ = analyzer.set(Arc::new(Analyzer::new(
&storage,
WorkspaceFinder::new(None),
)));
Self {
storage,
analyzers,
analyzer,
indexed: Default::default(),
client: TestableClient::new_for_testing(),
}
@ -81,7 +81,7 @@ impl ServerContext {
pub fn request(&self) -> RequestContext {
RequestContext {
storage: self.storage.clone(),
analyzers: self.analyzers.get().unwrap().clone(),
analyzer: self.analyzer.get().unwrap().clone(),
indexed: self.indexed.clone(),
client: self.client.clone(),
request_time: Instant::now(),
@ -92,7 +92,7 @@ impl ServerContext {
#[derive(Clone)]
pub struct RequestContext {
pub storage: Arc<Mutex<DocumentStorage>>,
pub analyzers: Arc<AnalyzerSet>,
pub analyzer: Arc<Analyzer>,
pub indexed: Arc<Mutex<BTreeMap<PathBuf, AsyncSignal>>>,
pub client: TestableClient,
pub request_time: Instant,
@ -117,7 +117,7 @@ impl Backend {
}
async fn maybe_index_workspace_for(&self, context: &RequestContext, path: &Path) {
let Some(workspace_root) = context.analyzers.finder().find_for(path) else {
let Some(workspace_root) = context.analyzer.workspace_finder().find_for(path) else {
return;
};
let workspace_root = workspace_root.to_path_buf();
@ -149,8 +149,8 @@ impl LanguageServer for Backend {
.and_then(|root_uri| root_uri.to_file_path().ok())
.as_deref(),
);
let analyzers = Arc::new(AnalyzerSet::new(&self.context.storage, finder));
self.context.analyzers.set(analyzers).ok();
let analyzer = Arc::new(Analyzer::new(&self.context.storage, finder));
self.context.analyzer.set(analyzer).ok();
Ok(InitializeResult {
capabilities: ServerCapabilities {

View file

@ -47,7 +47,7 @@ fn compute_references_lens(
range: Range,
target_name: &str,
) -> Result<CodeLens> {
let current_file = context.analyzers.analyze_file(path, context.request_time)?;
let current_file = context.analyzer.analyze_file(path, context.request_time)?;
let references = target_references(context, &current_file, target_name)?;
let title = match references.len() {
0 => "No references".to_string(),
@ -78,9 +78,7 @@ pub async fn code_lens(
}
let path = get_text_document_path(&params.text_document)?;
let current_file = context
.analyzers
.analyze_file(&path, context.request_time)?;
let current_file = context.analyzer.analyze_file(&path, context.request_time)?;
let targets: Vec<_> = current_file.analyzed_root.targets().collect();
@ -148,9 +146,7 @@ pub async fn code_lens_resolve(
let data = serde_json::from_value::<CodeLensData>(partial_lens.data.unwrap())?;
match data {
CodeLensData::TargetReferences(CodeLensDataTargetReferences { path, target_name }) => {
let current_file = context
.analyzers
.analyze_file(&path, context.request_time)?;
let current_file = context.analyzer.analyze_file(&path, context.request_time)?;
wait_indexing(context, &current_file.workspace_root).await?;
compute_references_lens(context, &path, partial_lens.range, &target_name)
}

View file

@ -100,7 +100,7 @@ fn build_identifier_completions(
let environment =
context
.analyzers
.analyzer
.analyze_environment(current_file, offset, context.request_time)?;
// Enumerate variables at the current scope.
@ -180,9 +180,7 @@ pub async fn completion(
params: CompletionParams,
) -> Result<Option<CompletionResponse>> {
let path = get_text_document_path(&params.text_document_position.text_document)?;
let current_file = context
.analyzers
.analyze_file(&path, context.request_time)?;
let current_file = context.analyzer.analyze_file(&path, context.request_time)?;
let offset = current_file
.document

View file

@ -28,14 +28,14 @@ pub async fn publish_diagnostics(context: &RequestContext, uri: &Url) {
return;
}
let Ok(current_file) = context.analyzers.analyze_file(&path, context.request_time) else {
let Ok(current_file) = context.analyzer.analyze_file(&path, context.request_time) else {
return;
};
let diagnostics = compute_diagnostics(
&current_file,
&config,
&context.analyzers,
&context.analyzer,
context.request_time,
);

View file

@ -36,9 +36,7 @@ pub async fn document_link(
params: DocumentLinkParams,
) -> Result<Option<Vec<DocumentLink>>> {
let path = get_text_document_path(&params.text_document)?;
let current_file = context
.analyzers
.analyze_file(&path, context.request_time)?;
let current_file = context.analyzer.analyze_file(&path, context.request_time)?;
let links = current_file
.links_map
@ -82,7 +80,7 @@ pub async fn document_link_resolve(
};
let target_file = context
.analyzers
.analyzer
.analyze_file(&data.path, context.request_time)?;
let position = find_target(&target_file, &data.name)

View file

@ -24,9 +24,7 @@ pub async fn document_symbol(
params: DocumentSymbolParams,
) -> Result<Option<DocumentSymbolResponse>> {
let path = get_text_document_path(&params.text_document)?;
let current_file = context
.analyzers
.analyze_file(&path, context.request_time)?;
let current_file = context.analyzer.analyze_file(&path, context.request_time)?;
Ok(Some(DocumentSymbolResponse::Nested(
current_file.symbols.clone(),

View file

@ -45,7 +45,9 @@ pub async fn formatting(
gn_path.display()
)));
}
} else if let Some(gn_path) = find_gn_binary(context.analyzers.finder().find_for(&file_path)) {
} else if let Some(gn_path) =
find_gn_binary(context.analyzer.workspace_finder().find_for(&file_path))
{
gn_path
} else {
return Err(Error::General(

View file

@ -34,9 +34,7 @@ pub async fn goto_definition(
params: GotoDefinitionParams,
) -> Result<Option<GotoDefinitionResponse>> {
let path = get_text_document_path(&params.text_document_position_params.text_document)?;
let current_file = context
.analyzers
.analyze_file(&path, context.request_time)?;
let current_file = context.analyzer.analyze_file(&path, context.request_time)?;
let Some(pos) = current_file
.document
@ -56,7 +54,7 @@ pub async fn goto_definition(
let (path, position) = match link {
AnalyzedLink::File { path, .. } => (path, Position::default()),
AnalyzedLink::Target { path, name, .. } => {
let target_file = context.analyzers.analyze_file(path, context.request_time)?;
let target_file = context.analyzer.analyze_file(path, context.request_time)?;
(
path,
find_target(&target_file, name)
@ -97,7 +95,7 @@ pub async fn goto_definition(
let environment =
context
.analyzers
.analyzer
.analyze_environment(&current_file, pos, context.request_time)?;
let mut links: Vec<LocationLink> = Vec::new();

View file

@ -27,9 +27,7 @@ use crate::{
pub async fn hover(context: &RequestContext, params: HoverParams) -> Result<Option<Hover>> {
let path = get_text_document_path(&params.text_document_position_params.text_document)?;
let current_file = context
.analyzers
.analyze_file(&path, context.request_time)?;
let current_file = context.analyzer.analyze_file(&path, context.request_time)?;
let Some(pos) = current_file
.document
@ -45,7 +43,7 @@ pub async fn hover(context: &RequestContext, params: HoverParams) -> Result<Opti
let environment =
context
.analyzers
.analyzer
.analyze_environment(&current_file, pos, context.request_time)?;
let mut sections: Vec<Vec<MarkedString>> = Vec::new();

View file

@ -38,7 +38,12 @@ pub fn target_references(
) -> Result<Vec<Location>> {
let bad_prefixes = get_overlapping_targets(&current_file.analyzed_root, target_name);
let cached_files = context.analyzers.cached_files(&current_file.workspace_root);
let cached_files = context
.analyzer
.workspace_for(&current_file.workspace_root)?
.lock()
.unwrap()
.cached_files();
let mut references: Vec<Location> = Vec::new();
for file in cached_files {
@ -78,9 +83,7 @@ pub async fn references(
}
let path = get_text_document_path(&params.text_document_position.text_document)?;
let current_file = context
.analyzers
.analyze_file(&path, context.request_time)?;
let current_file = context.analyzer.analyze_file(&path, context.request_time)?;
let Some(pos) = current_file
.document

View file

@ -35,9 +35,9 @@ pub async fn workspace_symbol(
let mut symbols = Vec::new();
let query = params.query.to_lowercase();
let workspace_roots = context.analyzers.workspace_roots();
let workspaces = context.analyzer.workspaces();
for workspace_root in workspace_roots {
for (workspace_root, workspace) in workspaces {
let signal = context
.indexed
.lock()
@ -48,7 +48,7 @@ pub async fn workspace_symbol(
signal.wait().await;
}
let files = context.analyzers.cached_files(&workspace_root);
let files = workspace.lock().unwrap().cached_files();
for file in files {
symbols.extend(extract_symbols(&file, &query));
}