Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project management #598

Merged
merged 27 commits into from
Jul 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
94b0fda
Strip BOM from first server response
nickspoons Jun 17, 2020
1ca0464
Always suppress 'xxxFadeOut' diagnostics
nickspoons Jun 17, 2020
d3e95ba
Refactor project listening, maintain project count
nickspoons Jun 17, 2020
f605e19
Move python variable into py.vim
nickspoons Jun 18, 2020
549a54d
Detect HTTP server in stdio mode and stop server
nickspoons Jun 18, 2020
8d3713f
Make unsolicited diagnostic listening opt-in
nickspoons Jun 18, 2020
38c1f7b
Stop server correctly and do not restart on :e
nickspoons Jun 20, 2020
3bdb600
Save OmniSharp-roslyn session logs in unique files
nickspoons Jun 20, 2020
0715019
Format log similar to the VSCode OmniSharp log
nickspoons Jun 21, 2020
96fb7ad
Add omnisharplog filetype and syntax highlighting
nickspoons Jun 21, 2020
97403a2
Normalise omnisharplog newlines between OS types
nickspoons Jun 21, 2020
ecca795
Improve log formatting and respect loglevel
nickspoons Jun 21, 2020
be653b3
Simplify OmniSharp#GetHost() and improve caching
nickspoons Jun 22, 2020
86d9cf5
Encapsulate "global" (non-buffer) stdio requests
nickspoons Jun 22, 2020
c41b6c4
Do not try to switch to log buffer when 'nohidden'
nickspoons Jun 26, 2020
4af026d
Use both 'Event' and 'Body' to parse events
nickspoons Jun 27, 2020
e6b30f5
Use /projects endpoint as part of load process
nickspoons Jun 28, 2020
787213f
Initialize buffers instead of full server load
nickspoons Jun 29, 2020
a2b4f95
Remove g:OmniSharp_server_stdio_quickload
nickspoons Jun 29, 2020
b284439
Exclude declaration from FindUsages
nickspoons Jun 29, 2020
aa91d86
Replay highlighting (again) after server is loaded
nickspoons Jul 5, 2020
41e3e3d
Add extra DEBUG loglevel for debug without json
nickspoons Jul 6, 2020
5e8a8f6
Make use of analyzer diagnostic results
nickspoons Jul 6, 2020
10c6405
Re-introduce ReplayOnLoad for selected endpoints
nickspoons Jul 6, 2020
11e44f8
Update documentation of stdio as default server
nickspoons Jul 7, 2020
6cd92c6
Simplify example .vimrc and use <Plug> mappings
nickspoons Jul 7, 2020
c5b41ef
Make g:OmniSharp_highlighting default to 2
nickspoons Jul 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 92 additions & 113 deletions README.md

Large diffs are not rendered by default.

48 changes: 29 additions & 19 deletions autoload/OmniSharp.vim
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,39 @@ set cpoptions&vim
if !g:OmniSharp_server_stdio
" Load python helper functions
call OmniSharp#py#Bootstrap()
let g:OmniSharp_py_err = {}
endif

function! OmniSharp#GetHost(...) abort
let bufnr = a:0 ? a:1 : bufnr('%')
if empty(getbufvar(bufnr, 'OmniSharp_host'))
let sln_or_dir = OmniSharp#FindSolutionOrDir(1, bufnr)
if g:OmniSharp_server_stdio
let host = {
\ 'job': OmniSharp#proc#GetJob(sln_or_dir),
\ 'sln_or_dir': sln_or_dir
\}
else
if g:OmniSharp_server_stdio
" Using the stdio server, b:OmniSharp_host is a dict containing the
" `sln_or_dir` and an `initialized` flag indicating whether this buffer has
" successfully been registered with the server:
" { 'sln_or_dir': '/path/to/solution_or_dir', 'initialized': 1 }
let host = getbufvar(bufnr, 'OmniSharp_host', {})
if get(host, 'sln_or_dir', '') ==# ''
let host.sln_or_dir = OmniSharp#FindSolutionOrDir(1, bufnr)
let host.initialized = 0
call setbufvar(bufnr, 'OmniSharp_host', host)
endif
" The returned dict includes the job, but the job is _not_ part of
" b:OmniSharp_host. It is important to always fetch the job from
" OmniSharp#proc#GetJob, ensuring that the job properties (job.job_id,
" job.loaded, job.pid etc.) are always correct and up-to-date.
return extend(copy(host), { 'job': OmniSharp#proc#GetJob(host.sln_or_dir) })
else
" Using the HTTP server, b:OmniSharp_host is a localhost URL
if empty(getbufvar(bufnr, 'OmniSharp_host'))
let sln_or_dir = OmniSharp#FindSolutionOrDir(1, bufnr)
let port = OmniSharp#py#GetPort(sln_or_dir)
if port == 0
return ''
endif
let host = get(g:, 'OmniSharp_host', 'http://localhost:' . port)
call setbufvar(bufnr, 'OmniSharp_host', host)
endif
call setbufvar(bufnr, 'OmniSharp_host', host)
return getbufvar(bufnr, 'OmniSharp_host')
endif
if g:OmniSharp_server_stdio
let host = getbufvar(bufnr, 'OmniSharp_host')
if !OmniSharp#proc#IsJobRunning(host.job)
let host.job = OmniSharp#proc#GetJob(host.sln_or_dir)
endif
endif
return getbufvar(bufnr, 'OmniSharp_host')
endfunction


Expand Down Expand Up @@ -295,6 +300,12 @@ function! OmniSharp#StartServer(...) abort

" Optionally perform check if server is already running
if check_is_running
let job = OmniSharp#proc#GetJob(sln_or_dir)
if type(job) == type({}) && get(job, 'stopped')
" The job has been manually stopped - do not start it again until
" instructed
return
endif
let running = OmniSharp#proc#IsJobRunning(sln_or_dir)
if !g:OmniSharp_server_stdio
" If the port is hardcoded, we should check if any other vim instances
Expand Down Expand Up @@ -324,10 +335,9 @@ function! s:StartServer(sln_or_dir) abort
return
endif

let job = OmniSharp#proc#Start(command, a:sln_or_dir)
call OmniSharp#proc#Start(command, a:sln_or_dir)
if g:OmniSharp_server_stdio
let b:OmniSharp_host = {
\ 'job': job,
\ 'sln_or_dir': a:sln_or_dir
\}
endif
Expand Down
11 changes: 9 additions & 2 deletions autoload/OmniSharp/actions/buffer.vim
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ set cpoptions&vim
" returned (synchronously or asynchronously)
function! OmniSharp#actions#buffer#Update(...) abort
let opts = a:0 && a:1 isnot 0 ? { 'Callback': a:1 } : {}
if !OmniSharp#IsServerRunning() | return | endif
let initializing = a:0 > 1
if bufname('%') ==# '' || OmniSharp#FugitiveCheck() | return | endif
if b:changedtick != get(b:, 'OmniSharp_UpdateChangeTick', -1)
if initializing || b:changedtick != get(b:, 'OmniSharp_UpdateChangeTick', -1)
let b:OmniSharp_UpdateChangeTick = b:changedtick
if g:OmniSharp_server_stdio
if initializing
let opts.Initializing = 1
endif
call s:StdioUpdate(opts)
else
if !OmniSharp#IsServerRunning() | return | endif
call OmniSharp#py#Eval('updateBuffer()')
call OmniSharp#py#CheckForError()
if has_key(opts, 'Callback')
Expand All @@ -25,6 +29,9 @@ function! s:StdioUpdate(opts) abort
let opts = {
\ 'ResponseHandler': function('s:StdioUpdateRH', [a:opts])
\}
if has_key(a:opts, 'Initializing')
let opts.Initializing = 1
endif
call OmniSharp#stdio#Request('/updatebuffer', opts)
endfunction

Expand Down
34 changes: 19 additions & 15 deletions autoload/OmniSharp/actions/diagnostics.vim
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function! OmniSharp#actions#diagnostics#Check(...) abort
endif
if g:OmniSharp_server_stdio
let Callback = function('s:CBCodeCheck', [opts])
call OmniSharp#actions#diagnostics#StdioCheck({}, Callback)
call OmniSharp#actions#diagnostics#StdioCheck(bufnr('%'), Callback)
else
let codecheck = OmniSharp#py#Eval('codeCheck()')
if OmniSharp#py#CheckForError() | return | endif
Expand All @@ -27,7 +27,12 @@ function! OmniSharp#actions#diagnostics#CheckGlobal(...) abort
if bufname('%') ==# '' || OmniSharp#FugitiveCheck() | return [] | endif
" Place the results in the quickfix window, if possible
if g:OmniSharp_server_stdio
call s:StdioCheckGlobal(function('s:CBGlobalCodeCheck'))
let Callback = function('s:CBGlobalCodeCheck')
let opts = {
\ 'ResponseHandler': function('s:StdioCheckRH', [Callback])
\}
let job = OmniSharp#GetHost().job
call OmniSharp#stdio#RequestGlobal(job, '/codecheck', opts)
else
let quickfixes = OmniSharp#py#Eval('globalCodeCheck()')
if OmniSharp#py#CheckForError() | return | endif
Expand All @@ -38,43 +43,42 @@ endfunction
" Normally this function would be named 's:StdioCheck`, but it is accessed
" directly from autoload/ale/sources/OmniSharp.vim so requires a full autoload
" function name.
function! OmniSharp#actions#diagnostics#StdioCheck(opts, Callback) abort
function! OmniSharp#actions#diagnostics#StdioCheck(bufnr, Callback) abort
let opts = {
\ 'ResponseHandler': function('s:StdioCheckRH', [a:Callback]),
\ 'BufNum': a:bufnr,
\ 'ReplayOnLoad': 1
\}
call extend(opts, a:opts, 'force')
call OmniSharp#stdio#Request('/codecheck', opts)
endfunction

function! s:StdioCheckGlobal(Callback) abort
let opts = {
\ 'ResponseHandler': function('s:StdioCheckRH', [a:Callback])
\}
call OmniSharp#stdio#RequestSend({}, '/codecheck', opts)
endfunction

function! s:StdioCheckRH(Callback, response) abort
if !a:response.Success | return | endif
call a:Callback(OmniSharp#locations#Parse(a:response.Body.QuickFixes,
\ function("s:DiagnosticQuickfixFixup")))
\ function('s:DiagnosticQuickfixFixup')))
endfunction

function! s:DiagnosticQuickfixFixup(quickfix) abort
let exclude_paths = get(g:, 'OmniSharp_diagnostic_exclude_paths', [])
if len(exclude_paths) && has_key(a:quickfix, 'FileName')
for exclude_path in exclude_paths
if match(a:quickfix.FileName, exclude_path) > 0
return
return {}
endif
endfor
endif

let overrides = get(g:, 'OmniSharp_diagnostic_overrides', {})
let diag_id = get(a:quickfix, 'Id', '-')
if index(keys(overrides), diag_id) >= 0
if diag_id =~# '.FadeOut$'
" Some analyzers such as roslynator provide 2 diagnostics: one to mark
" the start of the issue location and another to mark the end, e.g.
" `RCS1124FadeOut`. We never make use of these FadeOut diagnostics, as
" we can extract start and end locations from the main diagnostic.
return {}
elseif index(keys(overrides), diag_id) >= 0
if overrides[diag_id].type ==? 'None'
return
return {}
endif
call extend(a:quickfix, overrides[diag_id])
endif
Expand Down
9 changes: 5 additions & 4 deletions autoload/OmniSharp/actions/highlight.vim
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
let s:save_cpo = &cpoptions
set cpoptions&vim

function! OmniSharp#actions#highlight#Buffer() abort
if bufname('%') ==# '' || OmniSharp#FugitiveCheck() | return | endif
let opts = { 'BufNum': bufnr('%') }
function! OmniSharp#actions#highlight#Buffer(...) abort
let bufnr = a:0 ? a:1 : bufnr('%')
if bufname(bufnr) ==# '' || OmniSharp#FugitiveCheck() | return | endif
if g:OmniSharp_server_stdio &&
\ (has('textprop') || exists('*nvim_create_namespace'))
call s:StdioHighlight(opts.BufNum)
call s:StdioHighlight(bufnr)
else
" Full semantic highlighting not supported - highlight types instead
call OmniSharp#actions#highlight_types#Buffer()
Expand All @@ -17,6 +17,7 @@ function! s:StdioHighlight(bufnr) abort
let buftick = getbufvar(a:bufnr, 'changedtick')
let opts = {
\ 'ResponseHandler': function('s:HighlightRH', [a:bufnr, buftick]),
\ 'BufNum': a:bufnr,
\ 'ReplayOnLoad': 1
\}
call OmniSharp#stdio#Request('/v2/highlight', opts)
Expand Down
18 changes: 11 additions & 7 deletions autoload/OmniSharp/actions/highlight_types.vim
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,23 @@ set cpoptions&vim
function! OmniSharp#actions#highlight_types#Buffer() abort
if bufname('%') ==# '' || OmniSharp#FugitiveCheck() | return | endif
call OmniSharp#actions#highlight_types#Initialise()
let opts = { 'BufNum': bufnr('%') }
let bufnr = bufnr('%')
if g:OmniSharp_server_stdio
let Callback = function('s:CBHighlightBuffer', [opts])
call s:StdioFindHighlightTypes(Callback)
let Callback = function('s:CBHighlightBuffer', [bufnr])
call s:StdioFindHighlightTypes(bufnr, Callback)
else
if !OmniSharp#IsServerRunning() | return | endif
let hltypes = OmniSharp#py#Eval('findHighlightTypes()')
if OmniSharp#py#CheckForError() | return | endif
call s:CBHighlightBuffer(opts, hltypes)
call s:CBHighlightBuffer(bufnr, hltypes)
endif
endfunction

function! s:StdioFindHighlightTypes(Callback) abort
function! s:StdioFindHighlightTypes(bufnr, Callback) abort
let bufferLines = getline(1, '$')
let opts = {
\ 'ResponseHandler': function('s:FindHighlightTypesRH', [a:Callback, bufferLines]),
\ 'BufNum': a:bufnr,
\ 'ReplayOnLoad': 1
\}
call OmniSharp#stdio#Request('/highlight', opts)
Expand Down Expand Up @@ -68,12 +69,15 @@ function! s:FindHighlightTypesRH(Callback, bufferLines, response) abort
call a:Callback(hltypes)
endfunction

function! s:CBHighlightBuffer(opts, hltypes) abort
function! s:CBHighlightBuffer(bufnr, hltypes) abort
if has_key(a:hltypes, 'error')
echohl WarningMsg | echom a:hltypes.error | echohl None
return
endif
if bufnr('%') != a:opts.BufNum | return | endif
" matchadd() only works in the current window/buffer, so if the user has
" navigated away from the buffer where the request was made, this response can
" not be applied
if bufnr('%') != a:bufnr | return | endif

let b:OmniSharp_hl_matches = get(b:, 'OmniSharp_hl_matches', [])

Expand Down
2 changes: 1 addition & 1 deletion autoload/OmniSharp/actions/signature.vim
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function! OmniSharp#actions#signature#SignatureHelp(...) abort
else
let response = OmniSharp#py#Eval('signatureHelp()')
if OmniSharp#py#CheckForError() | return | endif
call s:CBSignatureHelp(response)
call s:CBSignatureHelp(opts, response)
endif
endfunction

Expand Down
5 changes: 4 additions & 1 deletion autoload/OmniSharp/actions/usages.vim
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ endfunction

function! s:StdioFind(Callback) abort
let opts = {
\ 'ResponseHandler': function('s:StdioFindRH', [a:Callback])
\ 'ResponseHandler': function('s:StdioFindRH', [a:Callback]),
\ 'Parameters': {
\ 'ExcludeDefinition': 1
\ }
\}
call OmniSharp#stdio#Request('/findusages', opts)
endfunction
Expand Down
38 changes: 38 additions & 0 deletions autoload/OmniSharp/actions/workspace.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
let s:save_cpo = &cpoptions
set cpoptions&vim

let s:attempts = 0

function! OmniSharp#actions#workspace#Get(job) abort
let opts = {
\ 'ResponseHandler': function('s:ProjectsRH', [a:job])
\}
let s:attempts += 1
call OmniSharp#stdio#RequestGlobal(a:job, '/projects', opts)
endfunction

function! s:ProjectsRH(job, response) abort
" If this request fails, retry up to 5 times
if !a:response.Success
if s:attempts < 5
call OmniSharp#actions#workspace#Get(a:job)
endif
return
endif
" If no projects have been loaded by the time this callback is reached, there
" are no projects and the job can be marked as ready
let projects = get(get(a:response.Body, 'MsBuild', {}), 'Projects', {})
let a:job.projects = map(projects,
\ {_,project -> {"name": project.AssemblyName, "path": project.Path}})
if get(a:job, 'projects_total', 0) > 0
call OmniSharp#log#Log(a:job, 'Workspace complete: ' . a:job.projects_total . ' project(s)')
else
call OmniSharp#log#Log(a:job, 'Workspace complete: no projects')
call OmniSharp#project#RegisterLoaded(a:job)
endif
endfunction

let &cpoptions = s:save_cpo
unlet s:save_cpo

" vim:et:sw=2:sts=2
26 changes: 26 additions & 0 deletions autoload/OmniSharp/buffer.vim
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
let s:save_cpo = &cpoptions
set cpoptions&vim

function! OmniSharp#buffer#Initialize(job, bufnr, command, opts) abort
let a:job.pending_requests = get(a:job, 'pending_requests', {})
let host = getbufvar(a:bufnr, 'OmniSharp_host')
if get(host, 'initialized') | return | endif
let a:job.pending_requests[a:bufnr] = get(a:job.pending_requests, a:bufnr, {})
" More recent requests to the same command replace older pending requests
let a:job.pending_requests[a:bufnr][a:command] = a:opts
if has_key(OmniSharp#GetHost(a:bufnr), 'initializing') | return | endif
let host.initializing = 1
let Callback = function('s:CBInitialize', [a:job, a:bufnr, host])
call OmniSharp#actions#buffer#Update(Callback, 1)
endfunction

function! s:CBInitialize(job, bufnr, host) abort
let a:host.initialized = 1
unlet a:host.initializing
call OmniSharp#log#Log(a:job, 'Replaying requests for buffer ' . a:bufnr)
for key in keys(a:job.pending_requests[a:bufnr])
call OmniSharp#stdio#Request(key, a:job.pending_requests[a:bufnr][key])
unlet a:job.pending_requests[a:bufnr][key]
if empty(a:job.pending_requests[a:bufnr])
unlet a:job.pending_requests[a:bufnr]
endif
endfor
endfunction

function! OmniSharp#buffer#PerformChanges(opts, response) abort
if !a:response.Success | return | endif
let changes = get(a:response.Body, 'Changes', [])
Expand Down
3 changes: 1 addition & 2 deletions autoload/OmniSharp/locations.vim
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function! OmniSharp#locations#Parse(quickfixes, ...) abort
let locations = []
for quickfix in a:quickfixes
let quickfix = a:0 ? a:1(quickfix) : quickfix
if type(quickfix) == 0
if empty(quickfix)
continue
endif

Expand All @@ -50,7 +50,6 @@ function! OmniSharp#locations#Parse(quickfixes, ...) abort
let location.end_col = quickfix.EndColumn - 1
endif


if has_key(quickfix, 'type')
let location.type = get(quickfix, 'type')
if has_key(quickfix, 'subtype')
Expand Down
Loading