1
1
mirror of https://github.com/oxalica/nil.git synced 2024-11-27 10:11:04 +03:00

Recalculate all diagnostics after config change

This commit is contained in:
oxalica 2022-09-26 00:23:46 +08:00
parent a370df35c9
commit 5f53c3c83e
2 changed files with 59 additions and 28 deletions

View File

@ -1,13 +1,24 @@
use crate::{convert, Result, StateSnapshot};
use ide::FileRange;
use lsp_types::{
CompletionParams, CompletionResponse, GotoDefinitionParams, GotoDefinitionResponse, Hover,
HoverParams, Location, PrepareRenameResponse, ReferenceParams, RenameParams, SelectionRange,
SelectionRangeParams, SemanticTokens, SemanticTokensParams, SemanticTokensRangeParams,
SemanticTokensRangeResult, SemanticTokensResult, TextDocumentPositionParams, WorkspaceEdit,
CompletionParams, CompletionResponse, Diagnostic, GotoDefinitionParams, GotoDefinitionResponse,
Hover, HoverParams, Location, PrepareRenameResponse, ReferenceParams, RenameParams,
SelectionRange, SelectionRangeParams, SemanticTokens, SemanticTokensParams,
SemanticTokensRangeParams, SemanticTokensRangeResult, SemanticTokensResult,
TextDocumentPositionParams, Url, WorkspaceEdit,
};
use text_size::TextRange;
const MAX_DIAGNOSTICS_CNT: usize = 128;
pub(crate) fn diagnostics(snap: StateSnapshot, uri: &Url) -> Result<Vec<Diagnostic>> {
let file = snap.vfs().file_for_uri(uri)?;
let mut diags = snap.analysis.diagnostics(file)?;
diags.retain(|diag| !snap.config.diagnostics_ignored.contains(diag.code()));
diags.truncate(MAX_DIAGNOSTICS_CNT);
Ok(convert::to_diagnostics(&snap.vfs(), file, &diags))
}
pub(crate) fn goto_definition(
snap: StateSnapshot,
params: GotoDefinitionParams,

View File

@ -15,13 +15,12 @@ use std::path::PathBuf;
use std::sync::{Arc, Once, RwLock};
use std::{fs, panic};
const MAX_DIAGNOSTICS_CNT: usize = 128;
const FILTER_FILE_EXTENTION: &str = "nix";
const CONFIG_KEY: &str = "nil";
#[derive(Debug, Default, Deserialize)]
#[derive(Debug, Clone, Default, Deserialize)]
pub struct Config {
diagnostics_ignored: HashSet<String>,
pub(crate) diagnostics_ignored: HashSet<String>,
}
type ReqHandler = fn(&mut State, Response);
@ -34,7 +33,7 @@ pub struct State {
req_queue: ReqQueue<(), ReqHandler>,
sender: Sender<Message>,
is_shutdown: bool,
config: Config,
config: Arc<Config>,
}
impl State {
@ -50,7 +49,7 @@ impl State {
req_queue: ReqQueue::default(),
sender: responder,
is_shutdown: false,
config: Config::default(),
config: Arc::new(Config::default()),
}
}
@ -220,9 +219,14 @@ impl State {
}
fn update_config(&mut self, mut v: serde_json::Value) {
let mut updated_diagnostics = false;
let mut config = Config::clone(&self.config);
if let Some(v) = v.pointer_mut("/diagnostics/ignored") {
match serde_json::from_value(v.take()) {
Ok(v) => self.config.diagnostics_ignored = v,
Ok(v) => {
config.diagnostics_ignored = v;
updated_diagnostics = true;
}
Err(e) => {
self.show_message(
MessageType::ERROR,
@ -231,13 +235,31 @@ impl State {
}
}
}
self.config = Arc::new(config);
tracing::debug!("Updated config: {:?}", self.config);
// Refresh all diagnostics since the filter may be changed.
if updated_diagnostics {
for uri in &*self.opened_files.read().unwrap() {
tracing::debug!("Recalculate diagnostics of {uri}");
let snap = self.snapshot();
// TODO: Error is ignored.
let diagnostics = handler::diagnostics(snap, uri).unwrap_or_default();
self.send_notification::<notif::PublishDiagnostics>(PublishDiagnosticsParams {
uri: uri.clone(),
diagnostics,
version: None,
});
}
}
}
fn snapshot(&self) -> StateSnapshot {
StateSnapshot {
analysis: self.host.snapshot(),
vfs: Arc::clone(&self.vfs),
config: Arc::clone(&self.config),
}
}
@ -248,34 +270,31 @@ impl State {
}
fn apply_vfs_change(&mut self) {
let mut vfs = self.vfs.write().unwrap();
let change = vfs.take_change();
let file_changes = change
.file_changes
.iter()
.map(|(file, text)| (*file, !text.is_empty()))
.collect::<Vec<_>>();
tracing::debug!("Change: {:?}", change);
self.host.apply_change(change);
let file_changes = {
let mut vfs = self.vfs.write().unwrap();
let change = vfs.take_change();
let file_changes = change
.file_changes
.iter()
.map(|(file, text)| (vfs.uri_for_file(*file), !text.is_empty()))
.collect::<Vec<_>>();
tracing::debug!("Change: {:?}", change);
self.host.apply_change(change);
file_changes
};
let snap = self.host.snapshot();
let opened_files = self.opened_files.read().unwrap();
for (file, has_text) in file_changes {
let uri = vfs.uri_for_file(file);
for (uri, has_text) in file_changes {
if !opened_files.contains(&uri) {
continue;
}
// TODO: Error is ignored.
let diagnostics = has_text
.then(|| {
let mut diags = snap.diagnostics(file).ok()?;
diags.retain(|diag| !self.config.diagnostics_ignored.contains(diag.code()));
diags.truncate(MAX_DIAGNOSTICS_CNT);
Some(convert::to_diagnostics(&vfs, file, &diags))
})
.then(|| handler::diagnostics(self.snapshot(), &uri).ok())
.flatten()
.unwrap_or_default();
self.send_notification::<notif::PublishDiagnostics>(PublishDiagnosticsParams {
uri,
diagnostics,
@ -422,6 +441,7 @@ fn result_to_response(id: RequestId, ret: Result<impl Serialize>) -> Result<Resp
pub struct StateSnapshot {
pub(crate) analysis: Analysis,
vfs: Arc<RwLock<Vfs>>,
pub(crate) config: Arc<Config>,
}
impl StateSnapshot {