Skip to content

Commit

Permalink
Initialize diagnostics when opening a document
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp-M committed Dec 18, 2023
1 parent f27fdb2 commit e01567e
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 112 deletions.
109 changes: 11 additions & 98 deletions helix-term/src/application.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
use arc_swap::{access::Map, ArcSwap};
use futures_util::Stream;
use helix_core::{
diagnostic::{DiagnosticTag, NumberOrString},
path::get_relative_path,
pos_at_coords, syntax, Selection,
};
use helix_core::{path::get_relative_path, pos_at_coords, syntax, Selection};
use helix_lsp::{
lsp::{self, notification::Notification},
util::lsp_pos_to_pos,
LspProgressMap,
};
use helix_view::{
Expand Down Expand Up @@ -743,99 +738,15 @@ impl Application {
});

if let Some(doc) = doc {
let lang_conf = doc.language_config();
let text = doc.text();

let diagnostics = params
.diagnostics
.iter()
.filter_map(|diagnostic| {
use helix_core::diagnostic::{Diagnostic, Range, Severity::*};
use lsp::DiagnosticSeverity;

// TODO: convert inside server
let start = if let Some(start) = lsp_pos_to_pos(
text,
diagnostic.range.start,
doc.lsp_diagnostic_to_diagnostic(
diagnostic,
server_id,
offset_encoding,
) {
start
} else {
log::warn!("lsp position out of bounds - {:?}", diagnostic);
return None;
};

let end = if let Some(end) =
lsp_pos_to_pos(text, diagnostic.range.end, offset_encoding)
{
end
} else {
log::warn!("lsp position out of bounds - {:?}", diagnostic);
return None;
};

let severity =
diagnostic.severity.map(|severity| match severity {
DiagnosticSeverity::ERROR => Error,
DiagnosticSeverity::WARNING => Warning,
DiagnosticSeverity::INFORMATION => Info,
DiagnosticSeverity::HINT => Hint,
severity => unreachable!(
"unrecognized diagnostic severity: {:?}",
severity
),
});

if let Some(lang_conf) = lang_conf {
if let Some(severity) = severity {
if severity < lang_conf.diagnostic_severity {
return None;
}
}
};

let code = match diagnostic.code.clone() {
Some(x) => match x {
lsp::NumberOrString::Number(x) => {
Some(NumberOrString::Number(x))
}
lsp::NumberOrString::String(x) => {
Some(NumberOrString::String(x))
}
},
None => None,
};

let tags = if let Some(tags) = &diagnostic.tags {
let new_tags = tags
.iter()
.filter_map(|tag| match *tag {
lsp::DiagnosticTag::DEPRECATED => {
Some(DiagnosticTag::Deprecated)
}
lsp::DiagnosticTag::UNNECESSARY => {
Some(DiagnosticTag::Unnecessary)
}
_ => None,
})
.collect();

new_tags
} else {
Vec::new()
};

Some(Diagnostic {
range: Range { start, end },
line: diagnostic.range.start.line as usize,
message: diagnostic.message.clone(),
severity,
code,
tags,
source: diagnostic.source.clone(),
data: diagnostic.data.clone(),
language_server_id: server_id,
})
)
})
.collect();

Expand All @@ -859,12 +770,14 @@ impl Application {
current_diagnostics.append(&mut diagnostics);
// Sort diagnostics first by severity and then by line numbers.
// Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order
current_diagnostics
.sort_unstable_by_key(|(d, _)| (d.severity, d.range.start));
current_diagnostics.sort_by_key(|(d, lsp_id)| {
(d.severity, d.range.start, *lsp_id)
});
}
Entry::Vacant(v) => {
diagnostics
.sort_unstable_by_key(|(d, _)| (d.severity, d.range.start));
diagnostics.sort_by_key(|(d, lsp_id)| {
(d.severity, d.range.start, *lsp_id)
});
v.insert(diagnostics);
}
};
Expand Down
5 changes: 2 additions & 3 deletions helix-term/src/ui/picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ impl<T: Item + 'static> Picker<T> {
(size, _) if size > MAX_FILE_SIZE_FOR_PREVIEW => {
CachedPreview::LargeFile
}
_ => Document::open(path, None, None, editor.config.clone())
_ => Document::open(path, None, None, editor)
.map(|doc| CachedPreview::Document(Box::new(doc)))
.unwrap_or(CachedPreview::NotFound),
},
Expand Down Expand Up @@ -480,8 +480,7 @@ impl<T: Item + 'static> Picker<T> {
.find::<Overlay<DynamicPicker<T>>>()
.map(|overlay| &mut overlay.content.file_picker),
};
let Some(picker) = picker
else {
let Some(picker) = picker else {
log::info!("picker closed before syntax highlighting finished");
return;
};
Expand Down
111 changes: 106 additions & 5 deletions helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use helix_core::doc_formatter::TextFormat;
use helix_core::encoding::Encoding;
use helix_core::syntax::{Highlight, LanguageServerFeature};
use helix_core::text_annotations::{InlineAnnotation, TextAnnotations};
use helix_lsp::util::lsp_pos_to_pos;
use helix_vcs::{DiffHandle, DiffProviderRegistry};

use ::parking_lot::Mutex;
Expand Down Expand Up @@ -692,20 +693,20 @@ impl Document {
path: &Path,
encoding: Option<&'static Encoding>,
config_loader: Option<Arc<syntax::Loader>>,
config: Arc<dyn DynAccess<Config>>,
editor: &Editor,
) -> Result<Self, Error> {
// Open the file if it exists, otherwise assume it is a new file (and thus empty).
let (rope, encoding, has_bom) = if path.exists() {
let mut file =
std::fs::File::open(path).context(format!("unable to open {:?}", path))?;
from_reader(&mut file, encoding)?
} else {
let line_ending: LineEnding = config.load().default_line_ending.into();
let line_ending: LineEnding = editor.config.load().default_line_ending.into();
let encoding = encoding.unwrap_or(encoding::UTF_8);
(Rope::from(line_ending.as_str()), encoding, false)
};

let mut doc = Self::from(rope, Some((encoding, has_bom)), config);
let mut doc = Self::from(rope, Some((encoding, has_bom)), editor.config.clone());

// set the path and try detecting the language
doc.set_path(Some(path));
Expand All @@ -715,6 +716,24 @@ impl Document {

doc.detect_indent_and_line_ending();

let diagnostics = Url::from_file_path(path) // TODO log error?
.ok()
.and_then(|uri| editor.diagnostics.get(&uri))
.map(|diags| {
diags
.iter()
.filter_map(|(diagnostic, lsp_id)| {
let offset_encoding =
editor.language_server_by_id(*lsp_id)?.offset_encoding();
doc.lsp_diagnostic_to_diagnostic(diagnostic, *lsp_id, offset_encoding)
})
.collect::<Vec<_>>()
});

if let Some(diagnostics) = diagnostics {
doc.diagnostics = diagnostics;
}

Ok(doc)
}

Expand Down Expand Up @@ -1692,15 +1711,97 @@ impl Document {
)
}

pub fn lsp_diagnostic_to_diagnostic(
&self,
diagnostic: &helix_lsp::lsp::Diagnostic,
language_server_id: usize,
offset_encoding: helix_lsp::OffsetEncoding,
) -> Option<Diagnostic> {
use helix_core::diagnostic::{Range, Severity::*};

let lang_conf = self.language_config();
let text = self.text();

// TODO: convert inside server
let start =
if let Some(start) = lsp_pos_to_pos(text, diagnostic.range.start, offset_encoding) {
start
} else {
log::warn!("lsp position out of bounds - {:?}", diagnostic);
return None;
};

let end = if let Some(end) = lsp_pos_to_pos(text, diagnostic.range.end, offset_encoding) {
end
} else {
log::warn!("lsp position out of bounds - {:?}", diagnostic);
return None;
};

let severity = diagnostic.severity.map(|severity| match severity {
lsp::DiagnosticSeverity::ERROR => Error,
lsp::DiagnosticSeverity::WARNING => Warning,
lsp::DiagnosticSeverity::INFORMATION => Info,
lsp::DiagnosticSeverity::HINT => Hint,
severity => unreachable!("unrecognized diagnostic severity: {:?}", severity),
});

if let Some(lang_conf) = lang_conf {
if let Some(severity) = severity {
if severity < lang_conf.diagnostic_severity {
return None;
}
}
};
use helix_core::diagnostic::{DiagnosticTag, NumberOrString};

let code = match diagnostic.code.clone() {
Some(x) => match x {
lsp::NumberOrString::Number(x) => Some(NumberOrString::Number(x)),
lsp::NumberOrString::String(x) => Some(NumberOrString::String(x)),
},
None => None,
};

let tags = if let Some(tags) = &diagnostic.tags {
let new_tags = tags
.iter()
.filter_map(|tag| match *tag {
lsp::DiagnosticTag::DEPRECATED => Some(DiagnosticTag::Deprecated),
lsp::DiagnosticTag::UNNECESSARY => Some(DiagnosticTag::Unnecessary),
_ => None,
})
.collect();

new_tags
} else {
Vec::new()
};

Some(Diagnostic {
range: Range { start, end },
line: diagnostic.range.start.line as usize,
message: diagnostic.message.clone(),
severity,
code,
tags,
source: diagnostic.source.clone(),
data: diagnostic.data.clone(),
language_server_id,
})
}

#[inline]
pub fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}

pub fn shown_diagnostics(&self) -> impl Iterator<Item = &Diagnostic> + DoubleEndedIterator {
self.diagnostics.iter().filter(|d| {
self.language_servers_with_feature(LanguageServerFeature::Diagnostics)
.any(|ls| ls.id() == d.language_server_id)
self.language_servers.len() == 0
|| self
.language_servers_with_feature(LanguageServerFeature::Diagnostics)
.any(|ls| ls.id() == d.language_server_id)
})
}

Expand Down
7 changes: 1 addition & 6 deletions helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1449,12 +1449,7 @@ impl Editor {
let id = if let Some(id) = id {
id
} else {
let mut doc = Document::open(
&path,
None,
Some(self.syn_loader.clone()),
self.config.clone(),
)?;
let mut doc = Document::open(&path, None, Some(self.syn_loader.clone()), self)?;

if let Some(diff_base) = self.diff_providers.get_diff_base(&path) {
doc.set_diff_base(diff_base);
Expand Down

0 comments on commit e01567e

Please sign in to comment.