Skip to content

Commit

Permalink
Merge pull request #2126 from bhcleek/signs-are-breakpoints
Browse files Browse the repository at this point in the history
Use signs to keep track of breakpoints
  • Loading branch information
bhcleek authored Jan 14, 2019
2 parents 53fb586 + 3ffc8e1 commit dadf61d
Showing 1 changed file with 69 additions and 71 deletions.
140 changes: 69 additions & 71 deletions autoload/go/debug.vim
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ if !exists('s:state')
let s:state = {
\ 'rpcid': 1,
\ 'running': 0,
\ 'breakpoint': {},
\ 'currentThread': {},
\ 'localVars': {},
\ 'functionArgs': {},
Expand Down Expand Up @@ -257,16 +256,6 @@ function! s:stop() abort
endfunction

function! go#debug#Stop() abort
" TODO(bc): don't remove breakpoints that were set before debugging started
" (see out_cb).
" Remove signs.
for k in keys(s:state['breakpoint'])
let bt = s:state['breakpoint'][k]
if bt.id >= 0
silent exe 'sign unplace ' . bt.id
endif
endfor

" Remove all commands and add back the default commands.
for k in map(split(execute('command GoDebug'), "\n")[1:], 'matchstr(v:val, "^\\s*\\zs\\S\\+")')
exe 'delcommand' k
Expand Down Expand Up @@ -420,18 +409,8 @@ function! s:expand_var() abort
endif
endfunction

function! s:start_cb(res) abort
if empty(a:res) || !has_key(a:res, 'result')
return
endif
for bt in a:res.result.Breakpoints
if bt.id >= 0
let s:state['breakpoint'][bt.id] = bt
exe 'sign place '. bt.id .' line=' . bt.line . ' name=godebugbreakpoint file=' . bt.file
endif
endfor

let oldbuf = bufnr('%')
function! s:start_cb() abort
let l:winid = win_getid()
silent! only!

let winnum = bufwinnr(bufnr('__GODEBUG_STACKTRACE__'))
Expand Down Expand Up @@ -491,7 +470,7 @@ function! s:start_cb(res) abort
set ballooneval
endif

exe bufwinnr(oldbuf) 'wincmd w'
call win_gotoid(l:winid)

augroup vim-go-debug
autocmd! * <buffer>
Expand Down Expand Up @@ -567,15 +546,14 @@ function! s:out_cb(ch, msg) abort
" future messages.
let s:state['ready'] = 1

" Tell dlv about the breakpoints that the user added before delve started.
let l:breaks = copy(s:state.breakpoint)
let s:state['breakpoint'] = {}
for l:bt in values(l:breaks)
call go#debug#Breakpoint(bt.line)
" replace all the breakpoints set before delve started so that the ids won't overlap.
let l:breakpoints = s:list_breakpoints()
for l:bt in s:list_breakpoints()
exe 'sign unplace '. l:bt.id
call go#debug#Breakpoint(l:bt.line, l:bt.file)
endfor

let res = s:call_jsonrpc('RPCServer.ListBreakpoints')
call s:start_cb(res)
call s:start_cb()
endif
endfunction

Expand Down Expand Up @@ -760,13 +738,12 @@ endfunction

function! s:eval(arg) abort
try
let res = s:call_jsonrpc('RPCServer.State')
let goroutineID = res.result.State.currentThread.goroutineID
let res = s:call_jsonrpc('RPCServer.Eval', {
let l:res = s:call_jsonrpc('RPCServer.State')
let l:res = s:call_jsonrpc('RPCServer.Eval', {
\ 'expr': a:arg,
\ 'scope': {'GoroutineID': goroutineID}
\ 'scope': {'GoroutineID': l:res.result.State.currentThread.goroutineID}
\ })
return s:eval_tree(res.result.Variable, 0)
return s:eval_tree(l:res.result.Variable, 0)
catch
call go#util#EchoError(v:exception)
return ''
Expand Down Expand Up @@ -816,12 +793,11 @@ endfunction

function! go#debug#Set(symbol, value) abort
try
let res = s:call_jsonrpc('RPCServer.State')
let goroutineID = res.result.State.currentThread.goroutineID
let l:res = s:call_jsonrpc('RPCServer.State')
call s:call_jsonrpc('RPCServer.Set', {
\ 'symbol': a:symbol,
\ 'value': a:value,
\ 'scope': {'GoroutineID': goroutineID}
\ 'scope': {'GoroutineID': l:res.result.State.currentThread.goroutineID}
\ })
catch
call go#util#EchoError(v:exception)
Expand All @@ -832,8 +808,8 @@ endfunction

function! s:update_stacktrace() abort
try
let res = s:call_jsonrpc('RPCServer.Stacktrace', {'id': s:groutineID(), 'depth': 5})
call s:show_stacktrace(res)
let l:res = s:call_jsonrpc('RPCServer.Stacktrace', {'id': s:groutineID(), 'depth': 5})
call s:show_stacktrace(l:res)
catch
call go#util#EchoError(v:exception)
endtry
Expand Down Expand Up @@ -863,7 +839,7 @@ function! go#debug#Stack(name) abort
endif

" Add a breakpoint to the main.Main if the user didn't define any.
if len(s:state['breakpoint']) is 0
if len(s:list_breakpoints()) is 0
if go#debug#Breakpoint() isnot 0
let s:state.running = 0
return
Expand Down Expand Up @@ -895,23 +871,15 @@ function! go#debug#Restart() abort
try
call s:stop()

let l:breaks = s:state['breakpoint']
let s:state = {
\ 'rpcid': 1,
\ 'running': 0,
\ 'breakpoint': {},
\ 'currentThread': {},
\ 'localVars': {},
\ 'functionArgs': {},
\ 'message': [],
\}

" Preserve breakpoints.
for bt in values(l:breaks)
" TODO: should use correct filename
exe 'sign unplace '. bt.id .' file=' . bt.file
call go#debug#Breakpoint(bt.line)
endfor
call call('go#debug#Start', s:start_args)
catch
call go#util#EchoError(v:exception)
Expand All @@ -926,47 +894,45 @@ endfunction
" Toggle breakpoint. Returns 0 on success and 1 on failure.
function! go#debug#Breakpoint(...) abort
let l:filename = fnamemodify(expand('%'), ':p:gs!\\!/!')
let l:linenr = line('.')

" Get line number from argument.
if len(a:000) > 0
let linenr = str2nr(a:1)
if linenr is 0
let l:linenr = str2nr(a:1)
if l:linenr is 0
call go#util#EchoError('not a number: ' . a:1)
return 0
endif
else
let linenr = line('.')
if len(a:000) > 1
let l:filename = a:2
endif
endif

try
" Check if we already have a breakpoint for this line.
let found = {}
for k in keys(s:state.breakpoint)
let bt = s:state.breakpoint[k]
if bt.file == l:filename && bt.line == linenr
let found = bt
let l:found = {}
for l:bt in s:list_breakpoints()
if l:bt.file is# l:filename && l:bt.line is# l:linenr
let l:found = l:bt
break
endif
endfor

" Remove breakpoint.
if type(found) == v:t_dict && !empty(found)
call remove(s:state['breakpoint'], bt.id)
exe 'sign unplace '. found.id .' file=' . found.file
if type(l:found) == v:t_dict && !empty(l:found)
exe 'sign unplace '. l:found.id .' file=' . l:found.file
if s:isActive()
let res = s:call_jsonrpc('RPCServer.ClearBreakpoint', {'id': found.id})
let res = s:call_jsonrpc('RPCServer.ClearBreakpoint', {'id': l:found.id})
endif
" Add breakpoint.
else
if s:isActive()
let res = s:call_jsonrpc('RPCServer.CreateBreakpoint', {'Breakpoint': {'file': l:filename, 'line': linenr}})
let bt = res.result.Breakpoint
exe 'sign place '. bt.id .' line=' . bt.line . ' name=godebugbreakpoint file=' . bt.file
let s:state['breakpoint'][bt.id] = bt
let l:res = s:call_jsonrpc('RPCServer.CreateBreakpoint', {'Breakpoint': {'file': l:filename, 'line': l:linenr}})
let l:bt = res.result.Breakpoint
exe 'sign place '. l:bt.id .' line=' . l:bt.line . ' name=godebugbreakpoint file=' . l:bt.file
else
let id = len(s:state['breakpoint']) + 1
let s:state['breakpoint'][id] = {'id': id, 'file': l:filename, 'line': linenr}
exe 'sign place '. id .' line=' . linenr . ' name=godebugbreakpoint file=' . l:filename
let l:id = len(s:list_breakpoints()) + 1
exe 'sign place ' . l:id . ' line=' . l:linenr . ' name=godebugbreakpoint file=' . l:filename
endif
endif
catch
Expand All @@ -977,8 +943,40 @@ function! go#debug#Breakpoint(...) abort
return 0
endfunction

function! s:list_breakpoints()
" :sign place
" --- Signs ---
" Signs for a.go:
" line=15 id=2 name=godebugbreakpoint
" line=16 id=1 name=godebugbreakpoint
" Signs for a_test.go:
" line=6 id=3 name=godebugbreakpoint

let l:signs = []
let l:file = ''
for l:line in split(execute('sign place'), '\n')[1:]
if l:line =~# '^Signs for '
let l:file = l:line[10:-2]
continue
endif

if l:line !~# 'name=godebugbreakpoint'
continue
endif

let l:sign = matchlist(l:line, '\vline\=(\d+) +id\=(\d+)')
call add(l:signs, {
\ 'id': l:sign[2],
\ 'file': fnamemodify(l:file, ':p'),
\ 'line': str2nr(l:sign[1]),
\ })
endfor

return l:signs
endfunction

sign define godebugbreakpoint text=> texthl=GoDebugBreakpoint
sign define godebugcurline text== linehl=GoDebugCurrent texthl=GoDebugCurrent
sign define godebugcurline text== texthl=GoDebugCurrent linehl=GoDebugCurrent

" restore Vi compatibility settings
let &cpo = s:cpo_save
Expand Down

0 comments on commit dadf61d

Please sign in to comment.