Skip to content

Commit

Permalink
Support call hierarchy
Browse files Browse the repository at this point in the history
  • Loading branch information
maralla committed Aug 29, 2024
1 parent c25ff7d commit c64da05
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 3 deletions.
11 changes: 11 additions & 0 deletions autoload/completor/action.vim
Original file line number Diff line number Diff line change
Expand Up @@ -324,11 +324,13 @@ function! completor#action#trigger(items)
let items = a:items
let action = s:action
let ft = 'markdown'
let do_method = ''

if type(a:items) == v:t_dict
let items = a:items.data
let action = get(a:items, 'action', action)
let ft = get(a:items, 'ft', ft)
let do_method = get(a:items, 'method', '')
endif

if action ==# 'complete'
Expand Down Expand Up @@ -361,6 +363,15 @@ function! completor#action#trigger(items)
echo "popup window not supported"
endif
endif
elseif action ==# 'do'
if empty(do_method)
return
endif
let arg = ''
if !empty(items)
let arg = items[0]
endif
call completor#do(do_method, arg)
elseif action ==# 'hover'
if !empty(items)
if completor#support_popup()
Expand Down
14 changes: 14 additions & 0 deletions autoload/completor/popup.vim
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,19 @@ func s:select_filter(id, key)
endfunc


func s:select_preview_filter(id, key)
if a:key == "j"
call win_execute(a:id, "normal! \<C-d>")
return 1
elseif a:key == "k"
call win_execute(a:id, "normal! \<C-u>")
return 1
endif

return 0
endfunc


let s:is_selector_content_shown = v:false
let s:selector_content = -1
func s:select_preview(id, type, item)
Expand All @@ -473,6 +486,7 @@ func s:select_preview(id, type, item)
\ mapping: 0,
\ scrollbar: 0,
\ line: 1,
\ filter: function('s:select_preview_filter'),
\ maxheight: height,
\ minheight: height,
\ minwidth: &columns - 10,
Expand Down
89 changes: 86 additions & 3 deletions pythonx/completers/lsp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
import os
import json
import io
from completor import Completor, vim, get
from completor import Completor, vim
from completor.compat import to_unicode

from . import ext
from .models import Initialize, DidOpen, Completion, DidChange, DidSave, \
Definition, Format, Rename, Hover, Initialized, Implementation, \
References, DidChangeConfiguration, Symbol, Signature, DocumentSymbol, \
CodeAction, CodeResolve
CodeAction, CodeResolve, PrepareCallHierarchy, IncomingCalls, \
OutgoingCalls
from .action import gen_jump_list, get_completion_word, gen_hover_doc, \
filter_items, parse_symbols, rename
from .utils import gen_uri
from .utils import gen_uri, to_filename

logger = logging.getLogger('completor')

Expand All @@ -30,6 +31,7 @@ def __init__(self, *args, **kwargs):
self.server_cmd = None
self.initialized = False
self.current_id = None
self.current_request_args = None
self.current_options = None
self.is_ext = False
self.open_file_map = {}
Expand Down Expand Up @@ -134,6 +136,25 @@ def code_action(self, action):
self.current_id = req_id
return req

def prepare_call_hierarchy(self, args):
if not args:
return ''
req = self.position_request(PrepareCallHierarchy)
self.current_request_args = args
return req

def call_hierarchy(self, data, call):
try:
item = json.loads(data)
except Exception as e:
logger.exception(e)
return ''

c = call(item)
req_id, req = c.to_request()
self.current_id = req_id
return req

def code_action_callback(self, data):
if not data:
return ''
Expand Down Expand Up @@ -220,6 +241,19 @@ def _gen_action_args(self, action, args):
if action == b'hover':
return self.position_request(Hover)

if action == b'prepare_call_hierarchy':
return self.prepare_call_hierarchy(args)

if action == b'incoming_calls':
if not args:
return ''
return self.call_hierarchy(args[0], IncomingCalls)

if action == b'outgoing_calls':
if not args:
return ''
return self.call_hierarchy(args[0], OutgoingCalls)

handler = ext.get_action_handler(action, self.ft_orig)
if handler:
self.is_ext = True
Expand All @@ -229,6 +263,7 @@ def _gen_action_args(self, action, args):
return ''

def gen_request(self, action, args):
self.current_request_args = None
self.current_options = {}
if args:
last = args[-1]
Expand Down Expand Up @@ -453,6 +488,54 @@ def on_hover(self, data):

return [gen_hover_doc(self.ft_orig, '\n\n'.join(values))]

def on_prepare_call_hierarchy(self, data):
logger.info("prepare_call_hierarchy -> %r", data)
if not data:
return []

if not self.current_request_args:
return []

method = self.current_request_args[0]

items = data[0]
if not items:
return []

item = items[0]

try:
data = json.dumps(item)
except Exception as e:
logger.exception(e)
return []

return vim.Dictionary(data=[data], action='do', method=method)

def on_incoming_calls(self, data, direction='from'):
logger.info("incoming_calls -> %r", data)
if not data:
return []

res = []
for item in data[0]:
data = item[direction]
if direction == 'from':
start = item['fromRanges'][0]['start']
else:
start = data['selectionRange']['start']
res.append({
'filename': to_filename(data['uri']),
'lnum': start['line'] + 1,
'col': start['character'] + 1,
'name': data['name'],
})

return vim.Dictionary(data=res, action='references')

def on_outgoing_calls(self, data):
return self.on_incoming_calls(data, direction='to')

def on_lsp_ext(self, data):
if not data or len(data) < 3:
return []
Expand Down
20 changes: 20 additions & 0 deletions pythonx/completers/lsp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,23 @@ def to_dict(self):
return {
"query": self.query,
}


class PrepareCallHierarchy(Completion):
method = "textDocument/prepareCallHierarchy"


class IncomingCalls(Base):
method = "callHierarchy/incomingCalls"

def __init__(self, item):
self.item = item

def to_dict(self):
return {
"item": self.item
}


class OutgoingCalls(IncomingCalls):
method = "callHierarchy/outgoingCalls"
9 changes: 9 additions & 0 deletions pythonx/completers/lsp/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# -*- coding: utf-8 -*-

try:
from urlparse import unquote
except ImportError:
from urllib.parse import unquote


def gen_uri(path):
return 'file://' + path
Expand All @@ -9,3 +14,7 @@ def parse_uri(uri):
if uri.startswith('file://'):
return uri[7:]
return uri


def to_filename(uri):
return unquote(parse_uri(uri))

0 comments on commit c64da05

Please sign in to comment.