Skip to content

Commit

Permalink
Fix parenthesized expressions in braceless if conditions
Browse files Browse the repository at this point in the history
Fixes #263 and #342
`_if_condition` extracted from `if_expression` and given a magic dynamic
precedence of 4
  • Loading branch information
susliko committed Sep 18, 2023
1 parent 70afdd5 commit e8579fa
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 24 deletions.
26 changes: 26 additions & 0 deletions corpus/expressions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,11 @@ class C:
else
()

if (a) || b(c) then return true

if (a) && b.c then
()

--------------------------------------------------------------------------------

(compilation_unit
Expand Down Expand Up @@ -445,6 +450,27 @@ class C:
(indented_block
(unit)
(comment))
(indented_block
(unit)))
(if_expression
(infix_expression
(parenthesized_expression
(identifier))
(operator_identifier)
(call_expression
(identifier)
(arguments
(identifier))))
(return_expression
(boolean_literal)))
(if_expression
(infix_expression
(parenthesized_expression
(identifier))
(operator_identifier)
(field_expression
(identifier)
(identifier)))
(indented_block
(unit))))))))

Expand Down
37 changes: 21 additions & 16 deletions grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ module.exports = grammar({
// 'for' operator_identifier ':' _annotated_type • ':' …
[$._type, $.compound_type],
[$.lambda_expression, $.modifiers],
// 'if' parenthesized_expression • '{' …
[$._if_condition, $._simple_expression],
],

word: $ => $._alpha_identifier,
Expand Down Expand Up @@ -1104,22 +1106,25 @@ module.exports = grammar({
),

if_expression: $ =>
prec.right(
PREC.control,
seq(
optional($.inline_modifier),
"if",
field(
"condition",
choice(
$.parenthesized_expression,
seq($._indentable_expression, "then"),
),
),
field("consequence", $._indentable_expression),
optional(seq("else", field("alternative", $._indentable_expression))),
),
),
prec.right(PREC.control, seq(
optional($.inline_modifier),
"if",
field(
"condition",
$._if_condition,
),
field("consequence", $._indentable_expression),
optional(seq("else", field("alternative", $._indentable_expression))),
)),

// NOTE(susliko): _if_condition and its magic dynamic precedence were introduced as a fix to
// https://github.com/tree-sitter/tree-sitter-scala/issues/263 and
// https://github.com/tree-sitter/tree-sitter-scala/issues/342
// Neither do I understand why this works, nor have I found a better solution
_if_condition: $ => prec.dynamic(4, choice(
$.parenthesized_expression,
seq($._indentable_expression, "then"),
)),

/*
* MatchClause ::= 'match' <<< CaseClauses >>>
Expand Down
16 changes: 8 additions & 8 deletions test/highlight/basics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,19 @@ object Hello {
trait Test {
// ^ keyword
// ^ type
def meth(i: Int)(implicit x: Boolean) = ???
def meth(i: Int)(implicit x: Boolean) = ???
// ^keyword.function
// ^keyword
// ^type
// ^method
// ^parameter
// ^parameter

val anonFun: Int => Int = (a: Int) => a
// ^variable
// ^type
// ^operator
// ^type
// ^parameter
val anonFun: Int => Int = (a: Int) => a
// ^variable
// ^type
// ^operator
// ^type
// ^parameter
}

protected abstract class Bla(test: String)
Expand Down

0 comments on commit e8579fa

Please sign in to comment.