Skip to content

Commit

Permalink
When the start parameter is missing, the behabiour is arbitary
Browse files Browse the repository at this point in the history
It seems that the behaviour of the start parameter being missing is
server (or perhaps a specific client) dependent. The specification
clearely says that it should be inserted at the column of the original
request, but the servers clearly expect either for that column to be the
beginning of an identifier or for the client to ignore the spec and
request from that position anyway.

Reading the VSCode code, we see that the 'word' before the cursor is
guessed, and if only if BOTH 'start' AND 'length' are supplied, then
they are used to determine where insertion starts, otherwise the current
'word' is used. Unclear what 'word' means in the specific contexts, but
we're relying on iskeyword.
  • Loading branch information
puremourning committed Sep 3, 2020
1 parent 3aa9494 commit 2710ee2
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 10 deletions.
51 changes: 42 additions & 9 deletions autoload/vimspector.vim
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ let s:save_cpo = &cpoptions
set cpoptions&vim
" }}}

function! s:Debug( ... )
py3 <<EOF
if _vimspector_session is not None:
_vimspector_session._logger.debug( *vim.eval( 'a:000' ) )
EOF
endfunction


let s:enabled = vimspector#internal#state#Reset()

Expand Down Expand Up @@ -271,28 +278,37 @@ function! vimspector#CompleteFuncSync( prompt, find_start, query ) abort

let line = getline( line( '.' ) )[ len( a:prompt ) : ]
let col = col( '.' ) - len( a:prompt )

" It seems that most servers don't implement the 'start' parameter, which is
" clearly necessary, as they all seem to assume a specific behaviour, which
" is undocumented.

let s:latest_completion_request.items =
\ py3eval( '_vimspector_session.GetCompletionsSync( '
\.' vim.eval( "line" ), '
\.' int( vim.eval( "col" ) ) )' )

let s:latest_completion_request.line = line
let s:latest_completion_request.col = col

let prev_non_keyword_char = match( line[ 0 : col - 1 ], '\k*$' ) + 1
let query_len = col - prev_non_keyword_char

let start_pos = col
for item in s:latest_completion_request.items
if !has_key( item, 'start' )
let item.start = col
if !has_key( item, 'start' ) || !has_key( item, 'length' )
" The specification states that if start is not supplied, isertion
" should be at the requested column. But about 0 of the servers actually
" implement that
" (https://github.com/microsoft/debug-adapter-protocol/issues/138)
let item.start = prev_non_keyword_char
let item.length = query_len
else
" For some reason, the returned start value is 0-indexed even though we
" use columnsStartAt1
" TODO need to check this with the other servers that exist
let item.start += 1
endif
" TODO/FIXME. I don't think it's possible to implement the 'length'
" parameter, using vim's completion system
" if !has_key( item, 'length' )
" let item.length = 0
" endif

if !has_key( item, 'text' )
let item.text = item.label
endif
Expand All @@ -305,6 +321,14 @@ function! vimspector#CompleteFuncSync( prompt, find_start, query ) abort
let s:latest_completion_request.start_pos = start_pos
let s:latest_completion_request.prompt = a:prompt

call s:Debug( 'FindStart: %s', {
\ 'line': line,
\ 'col': col,
\ 'prompt': len( a:prompt ),
\ 'start_pos': start_pos,
\ 'returning': ( start_pos + len( a:prompt ) ) - 1,
\ } )

" start_pos is 1-based and the return of findstart is 0-based
return ( start_pos + len( a:prompt ) ) - 1
else
Expand All @@ -316,18 +340,27 @@ function! vimspector#CompleteFuncSync( prompt, find_start, query ) abort
" that would be erased by the fixed-up earlier start position)
"
" both start_pos and item.start are 1-based
let item.text = s:latest_completion_request.text[
let item.text = s:latest_completion_request.line[
\ s:latest_completion_request.start_pos + pfxlen - 1 :
\ item.start + pfxlen - 1 ] . item.text
endif

if item.length > len( a:query )
call s:Debug( 'Rejecting %s, length is greater than %s',
\ item,
\ len( a:query ) )
continue
endif

call add( items, { 'word': item.text,
\ 'abbr': item.label,
\ 'menu': get( item, 'type', '' ),
\ 'icase': 1,
\ } )
endfor
let s:latest_completion_request = {}

call s:Debug( 'Items: %s', items )
return { 'words': items, 'refresh': 'always' }
endif
endfunction
Expand Down
9 changes: 8 additions & 1 deletion support/test/node/simple/simple.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
var msg = 'Hello, world!'

console.log( "OK stuff happened" )
var obj = {
test: 'testing',
toast: function() {
return 'toasty' . this.test;
}
}

console.log( "OK stuff happened " + obj.toast() )

0 comments on commit 2710ee2

Please sign in to comment.