mirror of
https://github.com/prabirshrestha/vim-lsp.git
synced 2025-12-14 20:35:59 +01:00
Add initial support for workspace folders (#1265)
* add g:lsp_experimental_workspace_folders * send client capabilities for workspaceFolders if g:lsp_experimental_workspace_folders is enabled * fix g:lsp_experimental_workspace_folders missing s * send workspaceFolders if workspaceFolder capability is defined via client * add local copy add opened workspace folders * Add support for workspace folders * document Workspace folders * add indent * fix doc indent
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
let s:enabled = 0
|
let s:enabled = 0
|
||||||
let s:already_setup = 0
|
let s:already_setup = 0
|
||||||
let s:Stream = lsp#callbag#makeSubject()
|
let s:Stream = lsp#callbag#makeSubject()
|
||||||
let s:servers = {} " { lsp_id, server_info, init_callbacks, init_result, buffers: { path: { changed_tick } }
|
" workspace_folders = { 'uri': { uri, name } }
|
||||||
|
let s:servers = {} " { lsp_id, server_info, workspace_folders, init_callbacks, init_result, buffers: { path: { changed_tick } }
|
||||||
let s:last_command_id = 0
|
let s:last_command_id = 0
|
||||||
let s:notification_callbacks = [] " { name, callback }
|
let s:notification_callbacks = [] " { name, callback }
|
||||||
|
|
||||||
@@ -167,10 +168,12 @@ function! lsp#register_server(server_info) abort
|
|||||||
if has_key(s:servers, l:server_name)
|
if has_key(s:servers, l:server_name)
|
||||||
call lsp#log('lsp#register_server', 'server already registered', l:server_name)
|
call lsp#log('lsp#register_server', 'server already registered', l:server_name)
|
||||||
endif
|
endif
|
||||||
|
" NOTE: workspace_folders is dict for faster lookup instead of array
|
||||||
let s:servers[l:server_name] = {
|
let s:servers[l:server_name] = {
|
||||||
\ 'server_info': a:server_info,
|
\ 'server_info': a:server_info,
|
||||||
\ 'lsp_id': 0,
|
\ 'lsp_id': 0,
|
||||||
\ 'buffers': {},
|
\ 'buffers': {},
|
||||||
|
\ 'workspace_folders': {},
|
||||||
\ }
|
\ }
|
||||||
call lsp#log('lsp#register_server', 'server registered', l:server_name)
|
call lsp#log('lsp#register_server', 'server registered', l:server_name)
|
||||||
doautocmd <nomodeline> User lsp_register_server
|
doautocmd <nomodeline> User lsp_register_server
|
||||||
@@ -565,7 +568,8 @@ function! lsp#default_get_supported_capabilities(server_info) abort
|
|||||||
\ },
|
\ },
|
||||||
\ 'workspace': {
|
\ 'workspace': {
|
||||||
\ 'applyEdit': v:true,
|
\ 'applyEdit': v:true,
|
||||||
\ 'configuration': v:true
|
\ 'configuration': v:true,
|
||||||
|
\ 'workspaceFolders': g:lsp_experimental_workspace_folders ? v:true : v:false,
|
||||||
\ },
|
\ },
|
||||||
\ }
|
\ }
|
||||||
endfunction
|
endfunction
|
||||||
@@ -598,6 +602,7 @@ function! s:ensure_init(buf, server_name, cb) abort
|
|||||||
let l:root_uri = lsp#utils#get_default_root_uri()
|
let l:root_uri = lsp#utils#get_default_root_uri()
|
||||||
endif
|
endif
|
||||||
let l:server['server_info']['_root_uri_resolved'] = l:root_uri
|
let l:server['server_info']['_root_uri_resolved'] = l:root_uri
|
||||||
|
let l:server['workspace_folders'][l:root_uri] = { 'name': l:root_uri, 'uri': l:root_uri }
|
||||||
|
|
||||||
if has_key(l:server_info, 'capabilities')
|
if has_key(l:server_info, 'capabilities')
|
||||||
let l:capabilities = l:server_info['capabilities']
|
let l:capabilities = l:server_info['capabilities']
|
||||||
@@ -616,6 +621,15 @@ function! s:ensure_init(buf, server_name, cb) abort
|
|||||||
\ 'trace': 'off',
|
\ 'trace': 'off',
|
||||||
\ },
|
\ },
|
||||||
\ }
|
\ }
|
||||||
|
|
||||||
|
let l:workspace_capabilities = get(l:capabilities, 'workspace', {})
|
||||||
|
if get(l:workspace_capabilities, 'workspaceFolders', v:false)
|
||||||
|
" TODO: extract folder name for l:root_uri
|
||||||
|
let l:server_info['workspaceFolders'] = [
|
||||||
|
\ { 'uri': l:root_uri, 'name': l:root_uri }
|
||||||
|
\ ]
|
||||||
|
let l:request['params']['workspaceFolders'] = l:server_info['workspaceFolders']
|
||||||
|
endif
|
||||||
|
|
||||||
if has_key(l:server_info, 'initialization_options')
|
if has_key(l:server_info, 'initialization_options')
|
||||||
let l:request.params['initializationOptions'] = l:server_info['initialization_options']
|
let l:request.params['initializationOptions'] = l:server_info['initialization_options']
|
||||||
@@ -645,7 +659,6 @@ endfunction
|
|||||||
|
|
||||||
function! s:text_changes(buf, server_name) abort
|
function! s:text_changes(buf, server_name) abort
|
||||||
let l:sync_kind = lsp#capabilities#get_text_document_change_sync_kind(a:server_name)
|
let l:sync_kind = lsp#capabilities#get_text_document_change_sync_kind(a:server_name)
|
||||||
|
|
||||||
" When syncKind is None, return null for contentChanges.
|
" When syncKind is None, return null for contentChanges.
|
||||||
if l:sync_kind == 0
|
if l:sync_kind == 0
|
||||||
return v:null
|
return v:null
|
||||||
@@ -729,6 +742,10 @@ function! s:ensure_open(buf, server_name, cb) abort
|
|||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if lsp#capabilities#has_workspace_folders_change_notifications(a:server_name)
|
||||||
|
call s:workspace_add_folder(a:server_name)
|
||||||
|
endif
|
||||||
|
|
||||||
call s:update_file_content(a:buf, a:server_name, lsp#utils#buffer#_get_lines(a:buf))
|
call s:update_file_content(a:buf, a:server_name, lsp#utils#buffer#_get_lines(a:buf))
|
||||||
|
|
||||||
let l:buffer_info = { 'changed_tick': getbufvar(a:buf, 'changedtick'), 'version': 1, 'uri': l:path }
|
let l:buffer_info = { 'changed_tick': getbufvar(a:buf, 'changedtick'), 'version': 1, 'uri': l:path }
|
||||||
@@ -748,6 +765,24 @@ function! s:ensure_open(buf, server_name, cb) abort
|
|||||||
call a:cb(l:msg)
|
call a:cb(l:msg)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! s:workspace_add_folder(server_name) abort
|
||||||
|
if !g:lsp_experimental_workspace_folders | return | endif
|
||||||
|
let l:server = s:servers[a:server_name]
|
||||||
|
let l:server_info = l:server['server_info']
|
||||||
|
let l:root_uri = has_key(l:server_info, 'root_uri') ? l:server_info['root_uri'](l:server_info) : lsp#utils#get_default_root_uri()
|
||||||
|
if !has_key(l:server['workspace_folders'], l:root_uri)
|
||||||
|
let l:workspace_folder = { 'name': l:root_uri, 'uri': l:root_uri }
|
||||||
|
call lsp#log('adding workspace folder', a:server_name, l:workspace_folder)
|
||||||
|
call s:send_notification(a:server_name, {
|
||||||
|
\ 'method': 'workspace/didChangeWorkspaceFolders',
|
||||||
|
\ 'params': {
|
||||||
|
\ 'added': [l:workspace_folder],
|
||||||
|
\ }
|
||||||
|
\ })
|
||||||
|
let l:server['workspace_folders'][l:root_uri] = l:workspace_folder
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! s:send_request(server_name, data) abort
|
function! s:send_request(server_name, data) abort
|
||||||
let l:lsp_id = s:servers[a:server_name]['lsp_id']
|
let l:lsp_id = s:servers[a:server_name]['lsp_id']
|
||||||
let l:data = copy(a:data)
|
let l:data = copy(a:data)
|
||||||
@@ -789,6 +824,7 @@ function! s:on_exit(server_name, id, data, event) abort
|
|||||||
if has_key(l:server, 'init_result')
|
if has_key(l:server, 'init_result')
|
||||||
unlet l:server['init_result']
|
unlet l:server['init_result']
|
||||||
endif
|
endif
|
||||||
|
let l:server['workspace_folders'] = {}
|
||||||
call lsp#stream(1, { 'server': '$vimlsp',
|
call lsp#stream(1, { 'server': '$vimlsp',
|
||||||
\ 'response': { 'method': '$/vimlsp/lsp_server_exit', 'params': { 'server': a:server_name } } })
|
\ 'response': { 'method': '$/vimlsp/lsp_server_exit', 'params': { 'server': a:server_name } } })
|
||||||
doautocmd <nomodeline> User lsp_server_exit
|
doautocmd <nomodeline> User lsp_server_exit
|
||||||
|
|||||||
@@ -33,6 +33,22 @@ function! lsp#capabilities#has_rename_prepare_provider(server_name) abort
|
|||||||
return s:has_provider(a:server_name, 'renameProvider', 'prepareProvider')
|
return s:has_provider(a:server_name, 'renameProvider', 'prepareProvider')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! lsp#capabilities#has_workspace_folders_change_notifications(server_name) abort
|
||||||
|
let l:capabilities = lsp#get_server_capabilities(a:server_name)
|
||||||
|
if type(l:capabilities) == type({}) && !empty(l:capabilities)
|
||||||
|
let l:workspace = get(l:capabilities, 'workspace', {})
|
||||||
|
if type(l:workspace) == type({}) && !empty(l:workspace)
|
||||||
|
let l:workspace_folders = get(l:workspace, 'workspaceFolders', {})
|
||||||
|
if type(l:workspace_folders) == type({}) && !empty(l:workspace_folders)
|
||||||
|
if get(l:workspace_folders, 'supported', v:false) && get(l:workspace_folders, 'changeNotifications', '') ==# 'workspace/didChangeWorkspaceFolders'
|
||||||
|
return v:true
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
return v:false
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! lsp#capabilities#has_document_formatting_provider(server_name) abort
|
function! lsp#capabilities#has_document_formatting_provider(server_name) abort
|
||||||
return s:has_provider(a:server_name, 'documentFormattingProvider')
|
return s:has_provider(a:server_name, 'documentFormattingProvider')
|
||||||
endfunction
|
endfunction
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ CONTENTS *vim-lsp-contents*
|
|||||||
Folding |vim-lsp-folding|
|
Folding |vim-lsp-folding|
|
||||||
Semantic highlighting |vim-lsp-semantic|
|
Semantic highlighting |vim-lsp-semantic|
|
||||||
Popup Formatting |vim-lsp-popup-format|
|
Popup Formatting |vim-lsp-popup-format|
|
||||||
|
Workspace Folders |vim-lsp-workspace-folders|
|
||||||
License |vim-lsp-license|
|
License |vim-lsp-license|
|
||||||
Maintainers |vim-lsp-maintainers|
|
Maintainers |vim-lsp-maintainers|
|
||||||
|
|
||||||
@@ -2023,6 +2024,18 @@ For customization, see
|
|||||||
|formatprg|.
|
|formatprg|.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
Workspace Folders *vim-lsp-workspace-folders*
|
||||||
|
|
||||||
|
Workspace folders is an experimental feature of vim-lsp. To enable workspace
|
||||||
|
folders set `let g:lsp_experimental_workspace_folders = 1`. In the future this
|
||||||
|
flag will be removed and workspace folders will be enabled by default.
|
||||||
|
|
||||||
|
When a new buffer is opened, if the server supports workspace folder, it will
|
||||||
|
call `root_uri` function to detect the workspace folder. If the folder is not
|
||||||
|
part of workspace folder, it will automatically notify the server to add the
|
||||||
|
workspace folder.
|
||||||
|
|
||||||
|
=============================================================================
|
||||||
License *vim-lsp-license*
|
License *vim-lsp-license*
|
||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ let g:lsp_untitled_buffer_enabled = get(g:, 'lsp_untitled_buffer_enabled', 1)
|
|||||||
|
|
||||||
let g:lsp_get_supported_capabilities = get(g:, 'lsp_get_supported_capabilities', [function('lsp#default_get_supported_capabilities')])
|
let g:lsp_get_supported_capabilities = get(g:, 'lsp_get_supported_capabilities', [function('lsp#default_get_supported_capabilities')])
|
||||||
|
|
||||||
|
let g:lsp_experimental_workspace_folders = get(g:, 'lsp_experimental_workspace_folders', 0)
|
||||||
|
|
||||||
if g:lsp_auto_enable
|
if g:lsp_auto_enable
|
||||||
augroup lsp_auto_enable
|
augroup lsp_auto_enable
|
||||||
autocmd!
|
autocmd!
|
||||||
|
|||||||
Reference in New Issue
Block a user