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

Feature Request: supports Workspace commands (workspace/executeCommand) #1461

Closed
zbinlin opened this issue Apr 10, 2023 · 2 comments
Closed

Comments

@zbinlin
Copy link
Contributor

zbinlin commented Apr 10, 2023

The Typescript LSP(typescript-language-server) supports Go to Source Definition via workspace/executeCommand

I found lsp#ui#vim#execute_command#_execute function can send an workspace/executeCommand command, but it doesn't handle the callback.

Is consideration given to support this feature?

@prabirshrestha
Copy link
Owner

This are generic and can't be supported directly in vim-lsp. You can register your own commands. If you are using vim-lsp-settings it is better to support it there so everyone can benefit. You can refer to mattn/vim-lsp-settings#362. You can use lsp#register_command.

@zbinlin
Copy link
Contributor Author

zbinlin commented Apr 11, 2023

I try to use lsp#register_command, but I found it unable to implement this requirement, finally I used raw lsp#send_request to implement it.

function! s:lsp_ui_workspace_execute_command(server_name, command_name, command_args, callback, ...) abort
    let l:params = { 'command': a:command_name }
    if a:command_args isnot v:null
        let l:params['arguments'] = a:command_args
    endif

    let l:ctx = {
    \    'server_name': a:server_name,
    \    'command_name': a:command_name,
    \    'command_args': a:command_args,
    \    }
    if a:0
        call extend(l:ctx, a:1)
    endif

    call lsp#send_request(a:server_name, {
    \    'method': 'workspace/executeCommand',
    \    'params': l:params,
    \    'on_notification': function(a:callback, [l:ctx]),
    \    })
endfunction

function! s:lsp_go_to_source_definition() abort
    let l:method = 'executeCommand'
    let l:operation = substitute(l:method, '\u', ' \l\0', 'g')

    let l:command_name = '_typescript.goToSourceDefinition'

    let l:capabilities_func = printf('lsp#capabilities#has_%s_provider(v:val)', substitute(l:operation, ' ', '_', 'g'))
    "let l:servers = filter(lsp#get_allowed_servers(), l:capabilities_func)
    let l:servers = lsp#get_allowed_servers()
    let l:command_id = lsp#_new_command()


    let l:ctx = { 'counter': len(l:servers), 'list':[], 'last_command_id': l:command_id, 'jump_if_one': 1, 'mods': '', 'in_preview': 0 }
    "if len(l:servers) == 0
    "    call s:not_supported('Retrieving ' . l:operation)
    "    return
    "endif

    let l:command_args = [
    \        lsp#get_text_document_identifier()['uri'],
    \        lsp#get_position(),
    \    ]

    for l:server in l:servers
        call s:lsp_ui_workspace_execute_command(l:server, l:command_name, l:command_args, function('s:handle_callback'), l:ctx)
    endfor

    echo printf('Retrieving %s ...', l:operation)
endfunction

function! s:handle_callback(ctx, data) abort
    if a:ctx['last_command_id'] != lsp#_last_command()
        return
    endif
    echom a:data

    let l:server = a:ctx['server_name']
    let l:type = 'workspace/executeCommand(' . a:ctx['command_name'] . ')'

    let a:ctx['counter'] = a:ctx['counter'] - 1

    if lsp#client#is_error(a:data['response']) || !has_key(a:data['response'], 'result')
        call lsp#utils#error('Failed to retrieve '. l:type . ' for ' . l:server . ': ' . lsp#client#error_message(a:data['response']))
    else
        let a:ctx['list'] = a:ctx['list'] + lsp#utils#location#_lsp_to_vim_list(a:data['response']['result'])
    endif

    if a:ctx['counter'] == 0
        if empty(a:ctx['list'])
            call lsp#utils#error('No ' . l:type . ' found')
        else
            call lsp#utils#tagstack#_update()

            let l:loc = a:ctx['list'][0]

            if len(a:ctx['list']) == 1 && a:ctx['jump_if_one'] && !a:ctx['in_preview']
                call lsp#utils#location#_open_vim_list_item(l:loc, a:ctx['mods'])
                echo 'Retrieved ' . l:type
                redraw
            elseif !a:ctx['in_preview']
                call setqflist([])
                call setqflist(a:ctx['list'])
                echo 'Retrieved ' . l:type
                botright copen
            else
                let l:lines = readfile(l:loc['filename'])
                if has_key(l:loc,'viewstart') " showing a locationLink
                    let l:view = l:lines[l:loc['viewstart'] : l:loc['viewend']]
                    call lsp#ui#vim#output#preview(l:server, l:view, {
                        \   'statusline': ' LSP Peek ' . l:type,
                        \   'filetype': &filetype
                        \ })
                else " showing a location
                    call lsp#ui#vim#output#preview(l:server, l:lines, {
                        \   'statusline': ' LSP Peek ' . l:type,
                        \   'cursor': { 'line': l:loc['lnum'], 'col': l:loc['col'], 'align': g:lsp_peek_alignment },
                        \   'filetype': &filetype
                        \ })
                endif
            endif
        endif
    endif
endfunction

nmap <expr> <A-]> <SID>lsp_go_to_source_definition()

thehowl added a commit to gnolang/gno that referenced this issue Oct 27, 2023
Relates to #1274 

What works with this setup:
- code completion after `.` but only for stdlibs packages
- code hover tooltip with `:LspHover` command (again limited to stdlibs)
- format on save (only gofmt for now)
- code Lens with `:LspCodeLens` command (only when the buffer is
`_test.gno` file) which display a list of possible `gno test` executions
with different scopes (package, files or function).
Note that test executions are using the LSP `workspace/executeCommand`
and actually `vim-lsp` doesn't handle well the output of that. That
means, tests are running, but you don't get the ouput. I'm still unsure
about how to setup that properly (see
prabirshrestha/vim-lsp#1461).

The good thing is the limitations can be removed by contributing to
[gnols](https://github.com/gno-playground/gnols), for instance :
- Expand code completion to all imported types
- Expand code hover to all imported types
- Add the *go-to-definition* feature
- Add the *rename* feature
- ...

---------

Co-authored-by: Morgan <git@howl.moe>
gfanton pushed a commit to gfanton/gno that referenced this issue Nov 9, 2023
Relates to gnolang#1274 

What works with this setup:
- code completion after `.` but only for stdlibs packages
- code hover tooltip with `:LspHover` command (again limited to stdlibs)
- format on save (only gofmt for now)
- code Lens with `:LspCodeLens` command (only when the buffer is
`_test.gno` file) which display a list of possible `gno test` executions
with different scopes (package, files or function).
Note that test executions are using the LSP `workspace/executeCommand`
and actually `vim-lsp` doesn't handle well the output of that. That
means, tests are running, but you don't get the ouput. I'm still unsure
about how to setup that properly (see
prabirshrestha/vim-lsp#1461).

The good thing is the limitations can be removed by contributing to
[gnols](https://github.com/gno-playground/gnols), for instance :
- Expand code completion to all imported types
- Expand code hover to all imported types
- Add the *go-to-definition* feature
- Add the *rename* feature
- ...

---------

Co-authored-by: Morgan <git@howl.moe>
moul pushed a commit to moul/gno that referenced this issue Nov 14, 2023
Relates to gnolang#1274 

What works with this setup:
- code completion after `.` but only for stdlibs packages
- code hover tooltip with `:LspHover` command (again limited to stdlibs)
- format on save (only gofmt for now)
- code Lens with `:LspCodeLens` command (only when the buffer is
`_test.gno` file) which display a list of possible `gno test` executions
with different scopes (package, files or function).
Note that test executions are using the LSP `workspace/executeCommand`
and actually `vim-lsp` doesn't handle well the output of that. That
means, tests are running, but you don't get the ouput. I'm still unsure
about how to setup that properly (see
prabirshrestha/vim-lsp#1461).

The good thing is the limitations can be removed by contributing to
[gnols](https://github.com/gno-playground/gnols), for instance :
- Expand code completion to all imported types
- Expand code hover to all imported types
- Add the *go-to-definition* feature
- Add the *rename* feature
- ...

---------

Co-authored-by: Morgan <git@howl.moe>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants