You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: diagnostics.rs
    path of file: ./repos/erg/crates/els
    
    the code of the file until where you have to start completion: use std::env::current_dir;
use std::ffi::OsStr;
use std::path::PathBuf;
use std::sync::atomic::Ordering;
use std::sync::mpsc::Receiver;
use std::thread::sleep;
use std::time::Duration;

use erg_common::consts::PYTHON_MODE;
use erg_common::dict::Dict;
use erg_common::pathutil::{project_entry_file_of, project_root_dir_of};
use erg_common::spawn::{safe_yield, spawn_new_thread};
use erg_common::style::*;
use erg_common::traits::Stream;
use erg_common::{fn_name, lsp_log};
use erg_compiler::artifact::BuildRunnable;
use erg_compiler::build_package::CheckStatus;
use erg_compiler::erg_parser::ast::Module;
use erg_compiler::erg_parser::error::IncompleteArtifact;
use erg_compiler::erg_parser::parse::Parsable;
use erg_compiler::error::CompileErrors;

use lsp_types::{
    ConfigurationParams, Diagnostic, DiagnosticSeverity, NumberOrString, Position, ProgressParams,
    ProgressParamsValue, PublishDiagnosticsParams, Range, Url, WorkDoneProgress,
    WorkDoneProgressBegin, WorkDoneProgressCreateParams, WorkDoneProgressEnd,
};
use serde_json::json;

use crate::_log;
use crate::channels::WorkerMessage;
use crate::diff::{ASTDiff, HIRDiff};
use crate::server::{DefaultFeatures, ELSResult, RedirectableStdout, Server};
use crate::server::{ASK_AUTO_SAVE_ID, HEALTH_CHECKER_ID};
use crate::util::{self, NormalizedUrl};

#[derive(Debug)]
pub enum BuildASTError {
    NoFile,
    ParseError(IncompleteArtifact),
}

#[derive(Debug)]
pub enum ChangeKind {
    New,
    NoChange,
    Valid,
    Invalid,
}

impl ChangeKind {
    pub const fn is_no_change(&self) -> bool {
        matches!(self, Self::NoChange)
    }
}

impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
    pub(crate) fn build_ast(&self, uri: &NormalizedUrl) -> Result<Module, BuildASTError> {
        let code = self
            .file_cache
            .get_entire_code(uri)
            .map_err(|_| BuildASTError::NoFile)?;
        Parser::parse(code)
            .map(|artifact| artifact.ast)
            .map_err(BuildASTError::ParseError)
    }

    pub(crate) fn change_kind(&self, uri: &NormalizedUrl) -> ChangeKind {
        let deps = self.dependencies_of(uri);
        if deps.is_empty() {
            return ChangeKind::New;
        }
        for dep in deps {
            let Some(old) = self.get_ast(&dep) else {
                return ChangeKind::Invalid;
            };
            if let Ok(new) = self.build_ast(&dep) {
                if !ASTDiff::diff(old, &new).is_nop() {
                    return ChangeKind::Valid;
                }
            } else {
                return ChangeKind::
    
    pub(crate) fn start_workspace_diagnostics(&mut self) {
        let mut _self = self.clone();
        spawn_new_thread(
            move || {
                macro_rules! work_done {
                    ($token: expr) => {{
                        let progress_end = WorkDoneProgressEnd {
                            message: Some(format!("checked 0 files")),
                        };
                        let params = ProgressParams {
                            token: $token.clone(),
                            value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(progress_end)),
                        };
                        _self
                            .send_stdout(&json!({
                                "jsonrpc": "2.0",
                                "method": "$/progress",
                                "params": params,
                            }))
                            .unwrap();
                        _self.flags.workspace_checked.store(true, Ordering::Relaxed);
                        return;
                    }};
                    ($token: expr, $uris: expr) => {{
                        let progress_end = WorkDoneProgressEnd {
                            message: Some(format!("checked {} files", $uris.len())),
                        };
                        let params = ProgressParams {
                            token: $token.clone(),
                            value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(progress_end)),
                        };
                        _self
                            .send_stdout(&json!({
                                "jsonrpc": "2.0",
                                "method": "$/progress",
                                "params": params,
                            }))
                            .unwrap();
                        _self.flags.workspace_checked.store(true, Ordering::Relaxed);
                        return;
                    }};
                }
                while !_self.flags.client_initialized() {
                    safe_yield();
                }
                let token = NumberOrString::String("els/start_workspace_diagnostics".to_string());
                let progress_token = WorkDoneProgressCreateParams {
                    token: token.clone(),
                };
                let _ = _self.send_stdout(&json!({
                    "jsonrpc": "2.0",
                    "id": 1,
                    "method": "window/workDoneProgress/create",
                    "params": progress_token,
                }));
                let Some(project_root) = project_root_dir_of(&current_dir().unwrap()) else {
                    work_done!(token);
                };
                let src_dir = if project_root.join("src").is_dir() {
                    project_root.join("src")
                } else {
                    project_root
                };
                let Some(main_path) = project_entry_file_of(&current_dir().unwrap()) else {
                    work_done!(token);
                };
                let Ok(main_uri) = NormalizedUrl::from_file_path(main_path) else {
                    work_done!(token);
                };
                let uris = Self::project_files(src_dir);
                let progress_begin = WorkDoneProgressBegin {
                    title: "Checking workspace".to_string(),
                    cancellable: Some(false),
                    message: Some(format!("checking {} files ...", uris.len())),
                    percentage: Some(0),
                };
                let params = ProgressParams {
                    token: token.clone(),
                    value: ProgressParamsValue::WorkDone(WorkDoneProgress::Begin(progress_begin)),
                };
                _self
                    .send_stdout(&json!({
                        "jsonrpc": "2.0",
                        "method": "$/progress",
                        "params": params,
                    }))
                    .unwrap();
                let code = _self.file_cache.get_entire_code(&main_uri).unwrap();
                let _ = _self.check_file(main_uri, code);
                work_done!(token, uris);
            },
            fn_name!(),
        );
    }