Skip to content

Commit 0f0ad73

Browse files
authored
Show all diagnostics on point on explain error at point buffer (#1204)
1 parent 70456d4 commit 0f0ad73

File tree

3 files changed

+71
-52
lines changed

3 files changed

+71
-52
lines changed

src/language_server_protocol.rs

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3219,64 +3219,64 @@ impl LanguageClient {
32193219
let silent_mode: bool = try_get("silent", params)?.unwrap_or_default();
32203220
let filename = self.vim()?.get_filename(params)?;
32213221
let position = self.vim()?.get_position(params)?;
3222-
let diag = self.get_state(|state| {
3223-
state
3222+
let diagnostics: Result<Vec<Diagnostic>> = self.get_state(|state| {
3223+
Ok(state
32243224
.diagnostics
32253225
.get(&filename)
32263226
.ok_or_else(|| anyhow!("No diagnostics found: filename: {}", filename,))?
32273227
.iter()
3228-
.find(|dn| position >= dn.range.start && position < dn.range.end)
3228+
.filter(|dn| position >= dn.range.start && position <= dn.range.end)
32293229
.cloned()
3230-
.ok_or_else(|| {
3231-
anyhow!(
3232-
"No diagnostics found: filename: {}, line: {}, character: {}",
3233-
filename,
3234-
position.line,
3235-
position.character
3236-
)
3237-
})
3230+
.collect::<Vec<Diagnostic>>())
32383231
})?;
32393232

3240-
if silent_mode && diag.is_err() {
3233+
if silent_mode && diagnostics.is_err() {
32413234
return Ok(Value::Null);
32423235
}
3243-
let diag = diag?;
3236+
let diagnostics = diagnostics?;
32443237

32453238
let language_id = self.vim()?.get_language_id(&filename, params)?;
32463239
let root =
32473240
self.get_state(|state| state.roots.get(&language_id).cloned().unwrap_or_default())?;
32483241
let root_uri = root.to_url()?;
32493242

3250-
let mut explanation = diag.message;
3251-
if let Some(source) = diag.source {
3252-
explanation = format!("{}: {}\n", source, explanation);
3253-
}
3254-
if let Some(related_information) = diag.related_information {
3255-
explanation = format!("{}\n", explanation);
3256-
for ri in related_information {
3257-
let prefix = format!("{}/", root_uri);
3258-
let uri = if ri.location.uri.as_str().starts_with(prefix.as_str()) {
3259-
// Heuristic: if start of stringified URI matches rootUri, abbreviate it away
3260-
&ri.location.uri.as_str()[root_uri.as_str().len() + 1..]
3261-
} else {
3262-
ri.location.uri.as_str()
3263-
};
3264-
if ri.location.uri.scheme() == "file" {
3265-
explanation = format!(
3266-
"{}\n{}:{}: {}",
3267-
explanation,
3268-
uri,
3269-
&ri.location.range.start.line + 1,
3270-
&ri.message
3271-
);
3272-
} else {
3273-
// Heuristic: if scheme is not file, don't show line numbers
3274-
explanation = format!("{}\n{}: {}", explanation, uri, &ri.message);
3243+
let mut explanation = vec![];
3244+
for (idx, diagnostic) in diagnostics.iter().enumerate() {
3245+
let mut message = diagnostic.message.clone();
3246+
if let Some(source) = &diagnostic.source {
3247+
message = format!("{}: {}", source, message);
3248+
}
3249+
message = format!("{}. {}", idx + 1, message);
3250+
3251+
if let Some(related_information) = &diagnostic.related_information {
3252+
for ri in related_information {
3253+
let prefix = format!("{}/", root_uri);
3254+
let uri = if ri.location.uri.as_str().starts_with(prefix.as_str()) {
3255+
// Heuristic: if start of stringified URI matches rootUri, abbreviate it away
3256+
&ri.location.uri.as_str()[root_uri.as_str().len() + 1..]
3257+
} else {
3258+
ri.location.uri.as_str()
3259+
};
3260+
if ri.location.uri.scheme() == "file" {
3261+
message = format!(
3262+
"{}\n{}:{}:{}: {}",
3263+
message,
3264+
uri,
3265+
&ri.location.range.start.line + 1,
3266+
&ri.location.range.start.character + 1,
3267+
&ri.message
3268+
);
3269+
} else {
3270+
// Heuristic: if scheme is not file, don't show line numbers
3271+
message = format!("{}\n{}: {}", message, uri, &ri.message);
3272+
}
32753273
}
32763274
}
3275+
3276+
explanation.push(message);
32773277
}
32783278

3279-
self.preview(explanation.as_str(), "__LCNExplainError__")?;
3279+
self.preview(explanation.join("\n").as_str(), "__LCNExplainError__")?;
32803280
Ok(Value::Null)
32813281
}
32823282

tests/LanguageClient_test.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010

1111
NVIM_LISTEN_ADDRESS = "/tmp/nvim-LanguageClient-IntegrationTest"
12+
EXPLAIN_ERROR_BUFFER = "__LCNExplainError__"
13+
HOVER_BUFFER = "__LCNHover__"
1214

1315

1416
project_root = os.path.dirname(os.path.abspath(__file__))
@@ -36,8 +38,8 @@ def assertRetry(predicate, retry_max=100):
3638
assert predicate()
3739

3840

39-
def getLanguageClientBuffers(nvim):
40-
return [b for b in nvim.buffers if b.name.endswith("__LCNHover__")]
41+
def getBufferByName(nvim, name: str):
42+
return [b for b in nvim.buffers if b.name.endswith(name)]
4143

4244

4345
@pytest.fixture(scope="module")
@@ -52,6 +54,18 @@ def setup(nvim):
5254
nvim.command("%bdelete!")
5355

5456

57+
def test_explainErrorAtPoint(nvim):
58+
nvim.command("edit! {}".format(PATH_MAIN_GO))
59+
time.sleep(1)
60+
nvim.funcs.cursor(26, 2)
61+
nvim.funcs.LanguageClient_explainErrorAtPoint()
62+
time.sleep(1)
63+
buf = getBufferByName(nvim, EXPLAIN_ERROR_BUFFER)[0]
64+
expect = "1. assign: self-assignment of x to x"
65+
66+
assert expect in "\n".join(buf)
67+
68+
5569
def test_textDocument_definition(nvim):
5670
nvim.command("edit! {}".format(PATH_MAIN_GO))
5771
time.sleep(2)
@@ -68,7 +82,7 @@ def test_textDocument_hover(nvim):
6882
nvim.funcs.cursor(10, 16)
6983
nvim.funcs.LanguageClient_textDocument_hover()
7084
time.sleep(1)
71-
buf = getLanguageClientBuffers(nvim)[0]
85+
buf = getBufferByName(nvim, HOVER_BUFFER)[0]
7286
expect = "func greet() int32"
7387

7488
assert expect in "\n".join(buf)
@@ -136,22 +150,22 @@ def test_workspace_symbol(nvim):
136150
nvim.command("edit! {}".format(PATH_MAIN_GO))
137151
time.sleep(1)
138152
nvim.funcs.cursor(1, 1)
139-
nvim.funcs.LanguageClient_workspace_symbol()
153+
nvim.funcs.LanguageClient_workspace_symbol('yo')
140154
time.sleep(1)
141155

142156
assert nvim.funcs.getloclist(0)
143157

144-
nvim.command("3lnext")
158+
nvim.command("lnext")
145159

146-
assert nvim.current.window.cursor == [17, 0]
160+
assert nvim.current.window.cursor == [24, 5]
147161

148162

149163
def test_textDocument_references(nvim):
150164
nvim.command("edit! {}".format(PATH_MAIN_GO))
151165
time.sleep(1)
152166
nvim.funcs.cursor(13, 6)
153167
nvim.funcs.LanguageClient_textDocument_references()
154-
time.sleep(2)
168+
time.sleep(3)
155169
expect = ["func greet() int32 {", "log.Println(greet())",
156170
"log.Println(greet())"]
157171

@@ -239,7 +253,7 @@ def test_textDocument_hover_float_window_closed_on_cursor_moved(nvim):
239253

240254
pos = _open_float_window(nvim)
241255

242-
float_buf = getLanguageClientBuffers(nvim)[0]
256+
float_buf = getBufferByName(nvim, HOVER_BUFFER)[0]
243257

244258
# Check if float window is open
245259
float_winnr = nvim.funcs.bufwinnr(float_buf.number)
@@ -253,7 +267,7 @@ def test_textDocument_hover_float_window_closed_on_cursor_moved(nvim):
253267
nvim.funcs.cursor(10, 14)
254268

255269
# Check float window buffer was closed by CursorMoved
256-
assert len(getLanguageClientBuffers(nvim)) == 0
270+
assert len(getBufferByName(nvim, HOVER_BUFFER)) == 0
257271

258272

259273
def test_textDocument_hover_float_window_closed_on_entering_window(nvim):
@@ -276,7 +290,7 @@ def test_textDocument_hover_float_window_closed_on_entering_window(nvim):
276290
assert win_id == nvim.funcs.win_getid()
277291

278292
# Check float window buffer was closed by BufEnter
279-
assert len(getLanguageClientBuffers(nvim)) == 0
293+
assert len(getBufferByName(nvim, HOVER_BUFFER)) == 0
280294
finally:
281295
nvim.command("close!")
282296

@@ -298,7 +312,7 @@ def test_textDocument_hover_float_window_closed_on_switching_to_buffer(nvim):
298312

299313
_open_float_window(nvim)
300314

301-
float_buf = getLanguageClientBuffers(nvim)[0]
315+
float_buf = getBufferByName(nvim, HOVER_BUFFER)[0]
302316
float_winnr = nvim.funcs.bufwinnr(float_buf.number)
303317
assert float_winnr > 0
304318

@@ -309,7 +323,7 @@ def test_textDocument_hover_float_window_closed_on_switching_to_buffer(nvim):
309323
assert nvim.current.buffer.number == another_bufnr
310324

311325
# Check float window buffer was closed by BufEnter
312-
assert len(getLanguageClientBuffers(nvim)) == 0
326+
assert len(getBufferByName(nvim, HOVER_BUFFER)) == 0
313327
finally:
314328
nvim.command("bdelete! {}".format(another_bufnr))
315329

@@ -334,4 +348,4 @@ def test_textDocument_hover_float_window_move_cursor_into_window(nvim):
334348
assert nvim.current.buffer.number == prev_bufnr
335349

336350
# Check float window buffer was closed by :close in the window
337-
assert len(getLanguageClientBuffers(nvim)) == 0
351+
assert len(getBufferByName(nvim, HOVER_BUFFER)) == 0

tests/data/sample-go/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,8 @@ func yo() {
2020
log.Println(b)
2121
log.Println(otherYo())
2222
}
23+
24+
func yoWithDiagnostic() {
25+
x := 0
26+
x = x
27+
}

0 commit comments

Comments
 (0)