mirror of
https://github.com/prabirshrestha/vim-lsp.git
synced 2025-12-14 20:35:59 +01:00
Add support for range diagnostics under cursor (#1586)
This commit is contained in:
@@ -29,20 +29,29 @@ function! lsp#internal#diagnostics#under_cursor#get_diagnostic(...) abort
|
||||
let l:line = line('.')
|
||||
let l:col = col('.')
|
||||
|
||||
return lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, l:line, l:col)
|
||||
endfunction
|
||||
|
||||
" Returns a diagnostic object, or empty dictionary if no diagnostics are
|
||||
" available.
|
||||
function! lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(diagnostics, line, col) abort
|
||||
let l:closest_diagnostic = {}
|
||||
let l:closest_distance = -1
|
||||
let l:closest_end_col = -1
|
||||
|
||||
for l:diagnostic in l:diagnostics
|
||||
for l:diagnostic in a:diagnostics
|
||||
let [l:start_line, l:start_col] = lsp#utils#position#lsp_to_vim('%', l:diagnostic['range']['start'])
|
||||
let [l:end_line, l:end_col] = lsp#utils#position#lsp_to_vim('%', l:diagnostic['range']['end'])
|
||||
|
||||
if l:line == l:start_line
|
||||
let l:distance = abs(l:start_col - l:col)
|
||||
if (a:line > l:start_line || (a:line == l:start_line && a:col >= l:start_col)) &&
|
||||
\ (a:line < l:end_line || (a:line == l:end_line && a:col < l:end_col))
|
||||
let l:distance = abs(l:start_col - a:col)
|
||||
if l:closest_distance < 0 || l:distance < l:closest_distance
|
||||
let l:closest_end_col = l:end_col
|
||||
let l:closest_diagnostic = l:diagnostic
|
||||
let l:closest_distance = l:distance
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
|
||||
return l:closest_diagnostic
|
||||
endfunction
|
||||
|
||||
88
test/lsp/internal/diagnostics/under_cursor.vimspec
Normal file
88
test/lsp/internal/diagnostics/under_cursor.vimspec
Normal file
@@ -0,0 +1,88 @@
|
||||
Describe lsp#internal#diagnostics#under_cursor
|
||||
" refer to lsp#test#projectdir('go') . '/documentdiagnostics.go'
|
||||
|
||||
It should not trigger diagnostics when cursor is outside diagnostic range
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
\ ]
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 1, 1), {})
|
||||
End
|
||||
|
||||
It should trigger diagnostic when cursor is exactly at start position
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
\ ]
|
||||
let l:expected = { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 7, 13), l:expected)
|
||||
End
|
||||
|
||||
It should not trigger diagnostic when cursor is at line before start position
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
\ ]
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 6, 13), {})
|
||||
End
|
||||
|
||||
It should not trigger diagnostic when cursor is one character before start position
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
\ ]
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 7, 12), {})
|
||||
End
|
||||
|
||||
It should trigger diagnostic when cursor is at start column on an intermediate line within range
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
\ ]
|
||||
let l:expected = { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 8, 1), l:expected)
|
||||
End
|
||||
|
||||
It should trigger diagnostic when cursor is at end column on an intermediate line within range
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
\ ]
|
||||
let l:expected = { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 8, 15), l:expected)
|
||||
End
|
||||
|
||||
It should trigger diagnostic when cursor is exactly at end position
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
\ ]
|
||||
let l:expected = { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 9, 5), l:expected)
|
||||
End
|
||||
|
||||
It should not trigger diagnostic when cursor is at line after end position
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
\ ]
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 10, 5), {})
|
||||
End
|
||||
|
||||
It should not return diagnostic when cursor is one character after end position
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
\ ]
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 9, 6), {})
|
||||
End
|
||||
|
||||
It should return the closest diagnostic when multiple diagnostics exist across different ranges
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 10, 'line': 4}, 'end': {'character': 7, 'line': 10}} },
|
||||
\ { 'range': {'start': {'character': 12, 'line': 6}, 'end': {'character': 5, 'line': 8}} }
|
||||
\ ]
|
||||
let l:expected = { 'range': {'start': {'character': 10, 'line': 4}, 'end': {'character': 7, 'line': 10}} }
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 7, 3), l:expected)
|
||||
End
|
||||
|
||||
It should return the most specific diagnostic when multiple diagnostics overlap at cursor position
|
||||
let l:diagnostics = [
|
||||
\ { 'range': {'start': {'character': 10, 'line': 4}, 'end': {'character': 15, 'line': 4}} },
|
||||
\ { 'range': {'start': {'character': 12, 'line': 4}, 'end': {'character': 14, 'line': 4}} }
|
||||
\ ]
|
||||
let l:expected = { 'range': {'start': {'character': 12, 'line': 4}, 'end': {'character': 14, 'line': 4}} }
|
||||
Assert Equals(lsp#internal#diagnostics#under_cursor#_get_closest_diagnostic(l:diagnostics, 5, 13), l:expected)
|
||||
End
|
||||
End
|
||||
11
test/testproject-go/documentdiagnositcs.go
Normal file
11
test/testproject-go/documentdiagnositcs.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func documentdiagnostics() {
|
||||
msg := "msg"
|
||||
fmt.Printf(msg +
|
||||
msg +
|
||||
msg,
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user