tree-sitter / tree-sitter-scala

Scala grammar for tree-sitter
MIT License
157 stars 55 forks source link

Unhandled block expression as parameter #21

Closed ckipp01 closed 2 years ago

ckipp01 commented 3 years ago

In Scala when you have a method that expects a single parameter the parens may be replaced with curly braces. We currently don't account for this.

For example:

object Main {
  def x(a: Int) = a

  x { 3 }
  x(3)
}

While a bit contrived, both of these are valid. However, currently the above will return:

(compilation_unit [0, 0] - [6, 0]
  (object_definition [0, 0] - [5, 1]
    name: (identifier [0, 7] - [0, 11])
    body: (template_body [0, 12] - [5, 1]
      (function_definition [1, 2] - [1, 19]
        name: (identifier [1, 6] - [1, 7])
        parameters: (parameters [1, 7] - [1, 15]
          (parameter [1, 8] - [1, 14]
            name: (identifier [1, 8] - [1, 9])
            type: (type_identifier [1, 11] - [1, 14])))
        body: (identifier [1, 18] - [1, 19]))
      (ERROR [3, 2] - [3, 3]
        (identifier [3, 2] - [3, 3]))
      (block [3, 4] - [3, 9]
        (number [3, 6] - [3, 7]))
      (call_expression [4, 2] - [4, 6]
        function: (identifier [4, 2] - [4, 3])
        arguments: (arguments [4, 3] - [4, 6]
          (number [4, 4] - [4, 5]))))))

The ERROR here should still be a call_expression. ~I'm a little unsure what to call the { 3 } since arguments is valid, but also a bit wrong since there can only be one. So I'm trying to think if this should be like single_block_argument or something like that signifying that it is a block, but an argument as well. I also can't really find reference to this in the spec to see exactly how this should be called.~ So I was a bit wrong on this, it's just a multiline block expression, but on a single line.

stumash commented 3 years ago

ya, I often write code like this:

List(1,2,3).map { x =>
  f(x) // maybe do slightly more complicated things than f(x)
}

I think the gramar should be able to parse this as (rougly)

(call_expression
  function: (identifier)
  arguments: (anonymous_function_expression))

I'm working on a PR, but I'm getting a gnarly amount of conflicts from adding anonymous_function_expression. (x, y) => e looks like a tuple until the =>. I'm really putting the G in GLR parser 😢

stumash commented 3 years ago

are there performance tests, or a performance test skeleton that we can add that's standard for tree-sitter-* repos?

stevanmilic commented 3 years ago

@stumash you got any progress on this one? I can try to resolve it if you want?

stumash commented 3 years ago

@stumash you got any progress on this one? I can try to resolve it if you want?

I got it done. I had to leave anonymous_function_expression for another time.

https://github.com/tree-sitter/tree-sitter-scala/pull/35

stevanmilic commented 3 years ago

Nice @stumash! I did something similar in https://github.com/tree-sitter/tree-sitter-scala/pull/34, although I didn't abstract the change into $.arguments – that I should have. I guess we can merge yours, and then mine since I've implemented the anonymous_function_expression i.e. lambda_expression. I also have some additional fixes.

stumash commented 2 years ago

so didn't #34 solve this? can we close this issue?