Skip to content

Commit

Permalink
LSP: Key diagnostics off file path instead of URI
Browse files Browse the repository at this point in the history
URIs need to be normalized to be comparable. For example a language
server could send a URI for a path containing '+' as '%2B' but we might
encode this in something like 'Document::url' as just '+'. We can
normalize the URI straight into a PathBuf though since this is the only
value we compare these diagnostics URIs against. This also covers
edge-cases like windows drive letter capitalization.
  • Loading branch information
the-mikedavis committed Jun 17, 2023
1 parent d5af603 commit f06e53c
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 26 deletions.
2 changes: 1 addition & 1 deletion helix-term/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,7 @@ impl Application {
// Insert the original lsp::Diagnostics here because we may have no open document
// for diagnosic message and so we can't calculate the exact position.
// When using them later in the diagnostics picker, we calculate them on-demand.
match self.editor.diagnostics.entry(params.uri) {
match self.editor.diagnostics.entry(path) {
Entry::Occupied(o) => {
let current_diagnostics = o.into_mut();
// there may entries of other language servers, which is why we can't overwrite the whole entry
Expand Down
41 changes: 17 additions & 24 deletions helix-term/src/commands/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ struct DiagnosticStyles {
}

struct PickerDiagnostic {
url: lsp::Url,
path: PathBuf,
diag: lsp::Diagnostic,
offset_encoding: OffsetEncoding,
}
Expand Down Expand Up @@ -171,8 +171,7 @@ impl ui::menu::Item for PickerDiagnostic {
let path = match format {
DiagnosticsFormat::HideSourcePath => String::new(),
DiagnosticsFormat::ShowSourcePath => {
let file_path = self.url.to_file_path().unwrap();
let path = path::get_truncated_path(file_path);
let path = path::get_truncated_path(&self.path);
format!("{}: ", path.to_string_lossy())
}
};
Expand Down Expand Up @@ -289,21 +288,21 @@ enum DiagnosticsFormat {

fn diag_picker(
cx: &Context,
diagnostics: BTreeMap<lsp::Url, Vec<(lsp::Diagnostic, usize)>>,
current_path: Option<lsp::Url>,
diagnostics: BTreeMap<PathBuf, Vec<(lsp::Diagnostic, usize)>>,
current_path: Option<PathBuf>,
format: DiagnosticsFormat,
) -> FilePicker<PickerDiagnostic> {
// TODO: drop current_path comparison and instead use workspace: bool flag?

// flatten the map to a vec of (url, diag) pairs
let mut flat_diag = Vec::new();
for (url, diags) in diagnostics {
for (path, diags) in diagnostics {
flat_diag.reserve(diags.len());

for (diag, ls) in diags {
if let Some(ls) = cx.editor.language_server_by_id(ls) {
flat_diag.push(PickerDiagnostic {
url: url.clone(),
path: path.clone(),
diag,
offset_encoding: ls.offset_encoding(),
});
Expand All @@ -323,16 +322,15 @@ fn diag_picker(
(styles, format),
move |cx,
PickerDiagnostic {
url,
path,
diag,
offset_encoding,
},
action| {
if current_path.as_ref() == Some(url) {
if current_path.as_ref() == Some(path) {
let (view, doc) = current!(cx.editor);
push_jump(view, doc);
} else {
let path = url.to_file_path().unwrap();
cx.editor.open(&path, action).expect("editor.open failed");
}

Expand All @@ -345,9 +343,9 @@ fn diag_picker(
align_view(doc, view, Align::Center);
}
},
move |_editor, PickerDiagnostic { url, diag, .. }| {
let location = lsp::Location::new(url.clone(), diag.range);
Some(location_to_file_location(&location))
move |_editor, PickerDiagnostic { path, diag, .. }| {
let line = Some((diag.range.start.line as usize, diag.range.end.line as usize));
Some((path.clone().into(), line))
},
)
.truncate_start(false)
Expand Down Expand Up @@ -511,17 +509,12 @@ pub fn workspace_symbol_picker(cx: &mut Context) {

pub fn diagnostics_picker(cx: &mut Context) {
let doc = doc!(cx.editor);
if let Some(current_url) = doc.url() {
let diagnostics = cx
.editor
.diagnostics
.get(&current_url)
.cloned()
.unwrap_or_default();
if let Some(path) = doc.path() {
let diagnostics = cx.editor.diagnostics.get(path).cloned().unwrap_or_default();
let picker = diag_picker(
cx,
[(current_url.clone(), diagnostics)].into(),
Some(current_url),
[(path.clone(), diagnostics)].into(),
Some(path.clone()),
DiagnosticsFormat::HideSourcePath,
);
cx.push_layer(Box::new(overlaid(picker)));
Expand All @@ -530,13 +523,13 @@ pub fn diagnostics_picker(cx: &mut Context) {

pub fn workspace_diagnostics_picker(cx: &mut Context) {
let doc = doc!(cx.editor);
let current_url = doc.url();
let current_path = doc.path();
// TODO not yet filtered by LanguageServerFeature, need to do something similar as Document::shown_diagnostics here for all open documents
let diagnostics = cx.editor.diagnostics.clone();
let picker = diag_picker(
cx,
diagnostics,
current_url,
current_path.cloned(),
DiagnosticsFormat::ShowSourcePath,
);
cx.push_layer(Box::new(overlaid(picker)));
Expand Down
2 changes: 1 addition & 1 deletion helix-view/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ pub struct Editor {
pub macro_recording: Option<(char, Vec<KeyEvent>)>,
pub macro_replaying: Vec<char>,
pub language_servers: helix_lsp::Registry,
pub diagnostics: BTreeMap<lsp::Url, Vec<(lsp::Diagnostic, usize)>>,
pub diagnostics: BTreeMap<PathBuf, Vec<(lsp::Diagnostic, usize)>>,
pub diff_providers: DiffProviderRegistry,

pub debugger: Option<dap::Client>,
Expand Down

0 comments on commit f06e53c

Please sign in to comment.