Skip to content

Commit 4f2e069

Browse files
committed
Initialize buffers instead of full server load
The OmniSharp-roslyn loading issues appear to stem from situations where multiple buffer-requests are sent before the project is fully initialized. This results in duplicate "miscellaneous" files, which are not correctly promoted to "project" files. Instead, this commit introduces a buffer "initialization" concept, where an `/updatebuffer` request is always sent as the first request for a buffer, and no further requests are sent for that buffer until a response is received (indicating that the server has registered the file, and there will be no duplicates created).
1 parent de51104 commit 4f2e069

File tree

6 files changed

+69
-41
lines changed

6 files changed

+69
-41
lines changed

autoload/OmniSharp.vim

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,20 @@ function! OmniSharp#GetHost(...) abort
1212
let bufnr = a:0 ? a:1 : bufnr('%')
1313
if g:OmniSharp_server_stdio
1414
" Using the stdio server, b:OmniSharp_host is a dict containing the
15-
" sln_or_dir:
16-
" { 'sln_or_dir': '/path/to/solution_or_dir' }
15+
" `sln_or_dir` and an `initialized` flag indicating whether this buffer has
16+
" successfully been registered with the server:
17+
" { 'sln_or_dir': '/path/to/solution_or_dir', 'initialized': 1 }
1718
let host = getbufvar(bufnr, 'OmniSharp_host', {})
1819
if get(host, 'sln_or_dir', '') ==# ''
1920
let host.sln_or_dir = OmniSharp#FindSolutionOrDir(1, bufnr)
21+
let host.initialized = 0
2022
call setbufvar(bufnr, 'OmniSharp_host', host)
2123
endif
2224
" The returned dict includes the job, but the job is _not_ part of
2325
" b:OmniSharp_host. It is important to always fetch the job from
2426
" OmniSharp#proc#GetJob, ensuring that the job properties (job.job_id,
2527
" job.loaded, job.pid etc.) are always correct and up-to-date.
26-
return {
27-
\ 'sln_or_dir': host.sln_or_dir,
28-
\ 'job': OmniSharp#proc#GetJob(host.sln_or_dir)
29-
\}
28+
return extend(copy(host), { 'job': OmniSharp#proc#GetJob(host.sln_or_dir) })
3029
else
3130
" Using the HTTP server, b:OmniSharp_host is a localhost URL
3231
if empty(getbufvar(bufnr, 'OmniSharp_host'))

autoload/OmniSharp/actions/buffer.vim

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ set cpoptions&vim
55
" returned (synchronously or asynchronously)
66
function! OmniSharp#actions#buffer#Update(...) abort
77
let opts = a:0 && a:1 isnot 0 ? { 'Callback': a:1 } : {}
8-
if !OmniSharp#IsServerRunning() | return | endif
8+
let initializing = a:0 > 1
99
if bufname('%') ==# '' || OmniSharp#FugitiveCheck() | return | endif
10-
if b:changedtick != get(b:, 'OmniSharp_UpdateChangeTick', -1)
10+
if initializing || b:changedtick != get(b:, 'OmniSharp_UpdateChangeTick', -1)
1111
let b:OmniSharp_UpdateChangeTick = b:changedtick
1212
if g:OmniSharp_server_stdio
13+
if initializing
14+
let opts.Initializing = 1
15+
endif
1316
call s:StdioUpdate(opts)
1417
else
18+
if !OmniSharp#IsServerRunning() | return | endif
1519
call OmniSharp#py#Eval('updateBuffer()')
1620
call OmniSharp#py#CheckForError()
1721
if has_key(opts, 'Callback')
@@ -25,6 +29,9 @@ function! s:StdioUpdate(opts) abort
2529
let opts = {
2630
\ 'ResponseHandler': function('s:StdioUpdateRH', [a:opts])
2731
\}
32+
if has_key(a:opts, 'Initializing')
33+
let opts.Initializing = 1
34+
endif
2835
call OmniSharp#stdio#Request('/updatebuffer', opts)
2936
endfunction
3037

autoload/OmniSharp/actions/workspace.vim

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ let s:attempts = 0
55

66
function! OmniSharp#actions#workspace#Get(job) abort
77
let opts = {
8-
\ 'ResponseHandler': function('s:ProjectsRH', [a:job]),
9-
\ 'AllowUnloaded': 1
8+
\ 'ResponseHandler': function('s:ProjectsRH', [a:job])
109
\}
1110
let s:attempts += 1
1211
call OmniSharp#stdio#RequestGlobal(a:job, '/projects', opts)

autoload/OmniSharp/buffer.vim

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
let s:save_cpo = &cpoptions
22
set cpoptions&vim
33

4+
function! OmniSharp#buffer#Initialize(job, bufnr, command, opts) abort
5+
let a:job.pending_requests = get(a:job, 'pending_requests', {})
6+
let host = getbufvar(a:bufnr, 'OmniSharp_host')
7+
if get(host, 'initialized') | return | endif
8+
let a:job.pending_requests[a:bufnr] = get(a:job.pending_requests, a:bufnr, {})
9+
" More recent requests to the same command replace older pending requests
10+
let a:job.pending_requests[a:bufnr][a:command] = a:opts
11+
if has_key(OmniSharp#GetHost(a:bufnr), 'initializing') | return | endif
12+
let host.initializing = 1
13+
let Callback = function('s:CBInitialize', [a:job, a:bufnr, host])
14+
call OmniSharp#actions#buffer#Update(Callback, 1)
15+
endfunction
16+
17+
function! s:CBInitialize(job, bufnr, host) abort
18+
let a:host.initialized = 1
19+
unlet a:host.initializing
20+
call OmniSharp#log#Log(a:job, 'Replaying requests for buffer ' . a:bufnr)
21+
for key in keys(a:job.pending_requests[a:bufnr])
22+
call OmniSharp#stdio#Request(key, a:job.pending_requests[a:bufnr][key])
23+
unlet a:job.pending_requests[a:bufnr][key]
24+
if empty(a:job.pending_requests[a:bufnr])
25+
unlet a:job.pending_requests[a:bufnr]
26+
endif
27+
endfor
28+
endfunction
29+
430
function! OmniSharp#buffer#PerformChanges(opts, response) abort
531
if !a:response.Success | return | endif
632
let changes = get(a:response.Body, 'Changes', [])

autoload/OmniSharp/project.vim

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ let s:save_cpo = &cpoptions
22
set cpoptions&vim
33

44
function! OmniSharp#project#CountLoaded() abort
5-
" TODO: stdio guard?
5+
if !g:OmniSharp_server_stdio | return 0 | endif
66
let host = OmniSharp#GetHost()
77
return get(OmniSharp#proc#GetJob(host.sln_or_dir), 'projects_loaded', 0)
88
endfunction
99

1010
function! OmniSharp#project#CountTotal() abort
11-
" TODO: stdio guard?
11+
if !g:OmniSharp_server_stdio | return 0 | endif
1212
let host = OmniSharp#GetHost()
1313
return get(OmniSharp#proc#GetJob(host.sln_or_dir), 'projects_total', 0)
1414
endfunction
@@ -22,12 +22,6 @@ function! OmniSharp#project#RegisterLoaded(job) abort
2222
endif
2323
let a:job.loaded = 1
2424
silent doautocmd <nomodeline> User OmniSharpReady
25-
26-
" TODO: Remove this delay once we have better information about
27-
" when the server is completely initialised:
28-
" https://github.com/OmniSharp/omnisharp-roslyn/issues/1521
29-
call timer_start(1000, function('OmniSharp#stdio#ReplayRequests', [a:job]))
30-
" call OmniSharp#stdio#ReplayRequests(a:job)
3125
endfunction
3226

3327
" Listen for stdio server-loaded events

autoload/OmniSharp/stdio.vim

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ set cpoptions&vim
33

44
let s:nextseq = get(s:, 'nextseq', 1001)
55
let s:requests = get(s:, 'requests', {})
6-
let s:pendingRequests = get(s:, 'pendingRequests', {})
76

87
function! OmniSharp#stdio#HandleResponse(job, message) abort
98
try
@@ -100,17 +99,37 @@ function! OmniSharp#stdio#Request(command, opts) abort
10099
let [bufnr, lnum, cnum] = s:lastPosition
101100
elseif has_key(a:opts, 'BufNum') && a:opts.BufNum != bufnr('%')
102101
let bufnr = a:opts.BufNum
103-
let lnum = 1
104-
let cnum = 1
102+
let lnum = get(a:opts, 'LineNum', 1)
103+
let cnum = get(a:opts, 'ColNum', 1)
105104
else
106105
let bufnr = bufnr('%')
107-
let lnum = line('.')
108-
let cnum = col('.')
106+
let lnum = get(a:opts, 'LineNum', line('.'))
107+
let cnum = get(a:opts, 'ColNum', col('.'))
109108
endif
110-
let job = OmniSharp#GetHost(bufnr).job
109+
let host = OmniSharp#GetHost(bufnr)
110+
let job = host.job
111111
if !OmniSharp#proc#IsJobRunning(job)
112112
return
113113
endif
114+
115+
if has_key(a:opts, 'Initializing')
116+
" The buffer is being initialized - this request will always be sent
117+
else
118+
if !get(host, 'initialized')
119+
" Replay the request when the buffer has been initialized with the server
120+
let opts = extend(a:opts, {
121+
\ 'BufNum': bufnr,
122+
\ 'LineNum': lnum,
123+
\ 'ColNum': cnum
124+
\})
125+
if has_key(opts, 'UsePreviousPosition')
126+
unlet opts.UsePreviousPosition
127+
endif
128+
call OmniSharp#buffer#Initialize(job, bufnr, a:command, opts)
129+
return 0
130+
endif
131+
endif
132+
114133
if has_key(a:opts, 'SavePosition')
115134
let s:lastPosition = [bufnr, lnum, cnum]
116135
endif
@@ -156,15 +175,6 @@ function! OmniSharp#stdio#RequestGlobal(job, command, opts) abort
156175
endfunction
157176

158177
function! s:Request(job, body, command, opts, ...) abort
159-
let sep = a:0 ? a:1 : ''
160-
if !has_key(a:opts, 'AllowUnloaded') &&
161-
\ (!has_key(a:job, 'job_id') || !a:job.loaded)
162-
if has_key(a:opts, 'ReplayOnLoad') && !has_key(s:pendingRequests, a:command)
163-
" This request should be replayed when the server is fully loaded
164-
let s:pendingRequests[a:command] = a:opts
165-
endif
166-
return 0
167-
endif
168178
call OmniSharp#log#Log(a:job, 'Request: ' . a:command, 1)
169179

170180
let a:body['Command'] = a:command
@@ -173,6 +183,7 @@ function! s:Request(job, body, command, opts, ...) abort
173183
if has_key(a:opts, 'Parameters')
174184
call extend(a:body.Arguments, a:opts.Parameters, 'force')
175185
endif
186+
let sep = a:0 ? a:1 : ''
176187
if sep !=# ''
177188
let encodedBody = substitute(json_encode(a:body), sep, '\\r\\n', 'g')
178189
else
@@ -196,14 +207,6 @@ function! s:Request(job, body, command, opts, ...) abort
196207
return 1
197208
endfunction
198209

199-
function! OmniSharp#stdio#ReplayRequests(job, ...) abort
200-
call OmniSharp#log#Log(a:job, 'Replaying requests')
201-
for key in keys(s:pendingRequests)
202-
call OmniSharp#stdio#Request(key, s:pendingRequests[key])
203-
unlet s:pendingRequests[key]
204-
endfor
205-
endfunction
206-
207210
let &cpoptions = s:save_cpo
208211
unlet s:save_cpo
209212

0 commit comments

Comments
 (0)