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

merlin-locate-type editor support #1359

Merged
merged 4 commits into from
Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ git version
- vim: add a simple interface to the new `construct` command:
`MerlinConstruct`. When several results are suggested, `<c-i>` and `<c-u>`
to show more or less deep results. (#1318)
- vim: add support for the `merlin-locate-type` command:
`MerlinLocateType` (#1359)
- emacs: add a simple interface to the new `construct` command:
`merlin-construct`. (#1352)
- emacs: add support for the `merlin-locate-type` command. (#1359)
+ test suite
- cover the new `construct` command (#1318)

Expand Down
11 changes: 11 additions & 0 deletions emacs/merlin.el
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,17 @@ loading"
(interactive)
(merlin--locate-result (merlin-call-locate)))

(defun merlin-locate-type ()
"Locate the type of the expression under point."
(interactive)
(let ((result (merlin/call "locate-type"
"-position" (merlin/unmake-point (point)))))
(unless result
(error "Not found. (Check *Messages* for potential errors)"))
(unless (listp result)
(error "%S" result))
(merlin--goto-file-and-point result)))

(defun merlin-pop-stack ()
"Go back to the last position where the user did a locate."
(interactive)
Expand Down
4 changes: 4 additions & 0 deletions tests/test-dirs/locate-type.t/a.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ end
module Y = struct
let y = T.X 1
end

let z = Y.y

let z2 = B.x
2 changes: 2 additions & 0 deletions tests/test-dirs/locate-type.t/b.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
type foo = string option
let x : foo = None
27 changes: 27 additions & 0 deletions tests/test-dirs/locate-type.t/run.t
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
$ $OCAMLC b.ml -bin-annot -c

$ $MERLIN single locate-type -position 6:6 -filename ./a.ml < ./a.ml
{
Expand All @@ -11,3 +12,29 @@
},
"notifications": []
}

$ $MERLIN single locate-type -workdir . -position 9:11 -filename a.ml < ./a.ml
{
"class": "return",
"value": {
"file": "$TESTCASE_ROOT/a.ml",
"pos": {
"line": 2,
"col": 2
}
},
"notifications": []
}

$ $MERLIN single locate-type -position 11:12 -filename ./a.ml < ./a.ml
{
"class": "return",
"value": {
"file": "$TESTCASE_ROOT/b.ml",
"pos": {
"line": 1,
"col": 0
}
},
"notifications": []
}
75 changes: 45 additions & 30 deletions vim/merlin/autoload/merlin.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,38 @@ def differs_from_current_file(path):
def vim_fnameescape(s):
return vim.eval("fnameescape('%s')" % s.replace("'","''"))

def goto_file_and_point(pos_or_err):
if not isinstance(pos_or_err, dict):
print(pos_or_err)
else:
l = pos_or_err['pos']['line']
c = pos_or_err['pos']['col']
split_method = vim.eval('g:merlin_split_method')
# save the current position in the jump list
vim.command("normal! m'")
if "file" in pos_or_err and differs_from_current_file(pos_or_err['file']):
fname = vim_fnameescape(pos_or_err['file'])
if split_method == "never":
vim.command(":keepjumps e %s" % fname)
elif "tab" in split_method:
if "always" in split_method:
vim.command(":keepjumps tab split %s" % fname)
else:
vim.command(":keepjumps tab drop %s" % fname)
elif "vertical" in split_method:
vim.command(":keepjumps vsplit %s" % fname)
else:
vim.command(":keepjumps split %s" % fname)
elif "always" in split_method:
if "tab" in split_method:
vim.command(":tab split")
elif "vertical" in split_method:
vim.command(":vsplit")
else:
vim.command(":split")
# TODO: move the cursor using vimscript, so we can :keepjumps?
vim.current.window.cursor = (l, c)

def command_locate(path, pos):
try:
choice = vim.eval('g:merlin_locate_preference')
Expand All @@ -260,36 +292,16 @@ def command_locate(path, pos):
pos_or_err = command("locate", "-look-for", choice, "-position", fmtpos(pos))
else:
pos_or_err = command("locate", "-prefix", path, "-look-for", choice, "-position", fmtpos(pos))
if not isinstance(pos_or_err, dict):
print(pos_or_err)
else:
l = pos_or_err['pos']['line']
c = pos_or_err['pos']['col']
split_method = vim.eval('g:merlin_split_method')
# save the current position in the jump list
vim.command("normal! m'")
if "file" in pos_or_err and differs_from_current_file(pos_or_err['file']):
fname = vim_fnameescape(pos_or_err['file'])
if split_method == "never":
vim.command(":keepjumps e %s" % fname)
elif "tab" in split_method:
if "always" in split_method:
vim.command(":keepjumps tab split %s" % fname)
else:
vim.command(":keepjumps tab drop %s" % fname)
elif "vertical" in split_method:
vim.command(":keepjumps vsplit %s" % fname)
else:
vim.command(":keepjumps split %s" % fname)
elif "always" in split_method:
if "tab" in split_method:
vim.command(":tab split")
elif "vertical" in split_method:
vim.command(":vsplit")
else:
vim.command(":split")
# TODO: move the cursor using vimscript, so we can :keepjumps?
vim.current.window.cursor = (l, c)
goto_file_and_point(pos_or_err)
except MerlinExc as e:
try_print_error(e)


def command_locate_type(pos):
try:
pos_or_err = command("locate-type", "-position", fmtpos(pos))
goto_file_and_point(pos_or_err)

except MerlinExc as e:
try_print_error(e)

Expand Down Expand Up @@ -444,6 +456,9 @@ def vim_locate_at_cursor(path):
def vim_locate_under_cursor():
vim_locate_at_cursor(None)

def vim_locate_type_at_cursor():
command_locate_type(vim.current.window.cursor)

# Jump and Phrase motion
def vim_jump_to(target):
command_motion("jump", target, vim.current.window.cursor)
Expand Down
6 changes: 5 additions & 1 deletion vim/merlin/autoload/merlin.vim
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,10 @@ function! merlin#Locate(...)
endif
endfunction

function! merlin#LocateType()
MerlinPy merlin.vim_locate_type_at_cursor()
endfunction

function! merlin#LocateImpl(...)
let l:pref = g:merlin_locate_preference
let g:merlin_locate_preference = 'implementation'
Expand Down Expand Up @@ -711,7 +715,7 @@ function! merlin#Register()
command! -buffer -complete=customlist,merlin#ExpandPrefix -nargs=? MerlinLocateImpl call merlin#LocateImpl(<q-args>)
command! -buffer -complete=customlist,merlin#ExpandPrefix -nargs=? MerlinLocateIntf call merlin#LocateIntf(<q-args>)
command! -buffer -nargs=0 MerlinILocate call merlin#InteractiveLocate()

command! -buffer -nargs=0 MerlinLocateType call merlin#LocateType()

if !exists('g:merlin_disable_default_keybindings') || !g:merlin_disable_default_keybindings
nmap <silent><buffer> gd :MerlinLocate<return>
Expand Down