glua_ls 1.0.27

Language server for Garry's Mod Lua (GLua).
Documentation
use std::collections::HashMap;

use lsp_types::{
    FullDocumentDiagnosticReport, WorkspaceDiagnosticParams, WorkspaceDiagnosticReport,
    WorkspaceFullDocumentDiagnosticReport,
};
use tokio_util::sync::CancellationToken;

use crate::context::{ServerContextSnapshot, WorkspaceDiagnosticLevel};

pub async fn on_pull_workspace_diagnostic(
    context: ServerContextSnapshot,
    _: WorkspaceDiagnosticParams,
    token: CancellationToken,
) -> WorkspaceDiagnosticReport {
    // Wait for any pending/in-flight document changes to finish before diagnosing.
    if !context.debounced_analysis().wait_until_fresh(&token).await {
        // Cancellation — return empty items rather than stale data,
        // since workspace diagnostics replace per-URI state and
        // returning stale could mask real issues. The client will
        // re-pull after the next refresh signal.
        return WorkspaceDiagnosticReport { items: vec![] };
    }

    let Some(workspace_manager) = context.read_workspace_manager(&token).await else {
        return WorkspaceDiagnosticReport { items: vec![] };
    };
    let status = workspace_manager.get_workspace_diagnostic_level();
    if status == WorkspaceDiagnosticLevel::None {
        return WorkspaceDiagnosticReport { items: vec![] };
    }
    let client_id = workspace_manager.client_config.client_id;
    let open_files = workspace_manager.current_open_files.clone();
    workspace_manager.update_workspace_version(WorkspaceDiagnosticLevel::None, false);
    drop(workspace_manager);

    if client_id.is_vscode() && context.lsp_features().supports_refresh_diagnostic() {
        context.client().refresh_workspace_diagnostics();
    }

    // let emmyrc = context.analysis().read().await.get_emmyrc();
    let file_diagnostics = match status {
        WorkspaceDiagnosticLevel::None => Vec::new(),
        WorkspaceDiagnosticLevel::Fast => {
            context
                .file_diagnostic()
                .pull_workspace_diagnostics_fast(token)
                .await
        }
        WorkspaceDiagnosticLevel::Slow => {
            context
                .file_diagnostic()
                .pull_workspace_diagnostics_slow(token)
                .await
        }
    };
    let open_file_versions = {
        let analysis = context.analysis().read().await;
        file_diagnostics
            .iter()
            .filter_map(|(uri, _)| {
                if !open_files.contains(uri) {
                    return None;
                }

                let version = analysis.get_file_id(uri).and_then(|file_id| {
                    analysis
                        .compilation
                        .get_db()
                        .get_vfs()
                        .get_file_version(&file_id)
                });
                Some((uri.clone(), version))
            })
            .collect::<HashMap<_, _>>()
    };

    WorkspaceDiagnosticReport {
        items: file_diagnostics
            .into_iter()
            .map(|(uri, diagnostics)| {
                WorkspaceFullDocumentDiagnosticReport {
                    version: open_file_versions
                        .get(&uri)
                        .copied()
                        .flatten()
                        .map(i64::from),
                    uri,
                    full_document_diagnostic_report: FullDocumentDiagnosticReport {
                        items: diagnostics,
                        result_id: None,
                    },
                }
                .into()
            })
            .collect(),
    }
}