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

Elixir: Not all functions are properly identified #249

Open
halfdan opened this issue Aug 16, 2022 · 2 comments
Open

Elixir: Not all functions are properly identified #249

halfdan opened this issue Aug 16, 2022 · 2 comments
Labels
bug Something isn't working

Comments

@halfdan
Copy link

halfdan commented Aug 16, 2022

Describe the bug
In addition to #245, there are two other function declarations that are currently not correctly identified by @function.inner/@function.outer queries. The following are not matched:

def foo(), do: 12
def foo() do
  12
end

def guarded_fn(a, b) when a == b, do: a + b
def guarded_fn(a, b) when a != b do
  a * b
end

To Reproduce
Steps to reproduce the behavior:

  1. Add above code to editor
  2. Try to move to next/prev function.

Expected behavior
Functions with guards and functions without parameters are correctly identified.

Additional context

@halfdan halfdan added the bug Something isn't working label Aug 16, 2022
@skbolton
Copy link
Contributor

skbolton commented Feb 3, 2023

Having to deep dive treesitter to learn all that's needed to fix this. Posting my findings here so that maybe someone can speed me up on fixing this. The problem is in this match.

The match assumes the functions argument list will not be empty

  (arguments (call [
    (arguments (_) @parameter.inner . "," @_delimiter)
    (arguments ((_) @parameter.inner) @_delimiter .) 
  ] (#make-range! "parameter.outer" @parameter.inner @_delimiter))

So the following code doesn't get registered

def foo(), do: 12

What I am struggling with is getting the #make-range to work properly when adding an empty argument clause. If I drop the whole make range logic and just do something like this the function selection works.

(call 
  target: ((identifier) @_identifier (#any-of? @_identifier 
    "def" 
    "defmacro" 
    "defmacrop" 
    "defn" 
    "defnp" 
    "defp"
  ))
  (arguments (call [
    (arguments (_) @parameter.inner . "," @_delimiter)
    (arguments ((_) @parameter.inner) @_delimiter .) 
    (arguments)
  ]))
   (keywords
     (pair
       value: (_) @function.inner))
  )
) @function.outer

I don't know if the proper approach is to define several somewhat duplicated matches that do or do not use the make-range helper or if there is a way to only call that predicate on a part of the match logic.

@skbolton
Copy link
Contributor

skbolton commented Feb 4, 2023

Going to keep playing with this. I think the solution is to stop trying to define a lot of the text objects in one query and instead make separate queries for exact text objects. By pulling the parameters query away from the functions query I think I can get everything lined up

skbolton added a commit to skbolton/nvim-treesitter-textobjects that referenced this issue Feb 8, 2023
Previous queries were mixing the parameter matches and the function
matches into the same query. This would make it so that functions that
didn't have parameters wouldn't match @function.inner or @function.outer
queries.

Separating them makes it easier to handle each case more specifically
and focus on the specifics of fulfilling that query. This should resolve
issue nvim-treesitter#249.
skbolton added a commit to skbolton/nvim-treesitter-textobjects that referenced this issue Feb 8, 2023
Previous queries were mixing the parameter matches and the function
matches into the same query. This would make it so that functions that
didn't have parameters wouldn't match @function.inner or @function.outer
queries.

Separating them makes it easier to focus on the specifics of fulfilling
each query. This should resolve issue nvim-treesitter#249.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants