Trailing commas

Problem
-------
Trailing commas are not supported.

Solution
--------
This adds support for that.
pull/481/head
Eugene Yokota 2023-01-19 01:38:12 +07:00
parent f6bbf35de4
commit 944196126a
6 changed files with 82 additions and 22 deletions

@ -174,7 +174,9 @@ Imports
import PartialFunction.condOpt import PartialFunction.condOpt
import a.b, c.e import a.b, c.e
import reflect.io.{Directory, File, Path} import reflect.io.{Directory, File, Path}
import a.{
b,
}
--- ---
(compilation_unit (compilation_unit
@ -186,7 +188,9 @@ import reflect.io.{Directory, File, Path}
(identifier) (identifier)) (identifier) (identifier))
(import_declaration (import_declaration
(identifier) (identifier) (identifier) (identifier)
(namespace_selectors (identifier) (identifier) (identifier)))) (namespace_selectors (identifier) (identifier) (identifier)))
(import_declaration (identifier)
(namespace_selectors (identifier))))
================================ ================================
Imports: Wildcard Imports: Wildcard
@ -307,7 +311,10 @@ object O3 extends A {
Class definitions Class definitions
======================================= =======================================
class C[T, U] { class C[
T,
U,
] {
} }
--- ---
@ -397,7 +404,10 @@ end A
Class definitions with parameters Class definitions with parameters
======================================= =======================================
class Point(val x: Int, val y: Int)(implicit coord: Coord) class Point(
val x: Int,
val y: Int,
)(implicit coord: Coord)
// TODO: The last argument should become class_parameters // TODO: The last argument should become class_parameters
class A @Inject()(x: Int, y: Int) class A @Inject()(x: Int, y: Int)
@ -734,7 +744,10 @@ Function definitions
======================================= =======================================
class A { class A {
def b(c: D, e: F) = 1 def b(
c: D,
e: F,
) = 1
def g[H](i) { def g[H](i) {
j j
} }

@ -5,7 +5,10 @@ Call expressions
class C { class C {
def main() { def main() {
a() a()
a(123) a(
123,
234,
)
::(123) ::(123)
a(b, c) a(b, c)
a.map(x => x + 1) a.map(x => x + 1)
@ -27,7 +30,7 @@ class C {
(parameters) (parameters)
(block (block
(call_expression (identifier) (arguments)) (call_expression (identifier) (arguments))
(call_expression (identifier) (arguments (integer_literal))) (call_expression (identifier) (arguments (integer_literal) (integer_literal)))
(call_expression (operator_identifier) (arguments (integer_literal))) (call_expression (operator_identifier) (arguments (integer_literal)))
(call_expression (identifier) (arguments (identifier) (identifier))) (call_expression (identifier) (arguments (identifier) (identifier)))
(call_expression (field_expression (identifier) (identifier)) (arguments (call_expression (field_expression (identifier) (identifier)) (arguments
@ -122,7 +125,10 @@ Generic functions
class C { class C {
def main() { def main() {
a[T]() a[
A1,
A2,
]()
List[Traversable[ClassPath]]() List[Traversable[ClassPath]]()
} }
} }
@ -140,7 +146,7 @@ class C {
(call_expression (call_expression
(generic_function (generic_function
(identifier) (identifier)
(type_arguments (type_identifier))) (type_arguments (type_identifier) (type_identifier)))
(arguments)) (arguments))
(call_expression (call_expression
(generic_function (generic_function

@ -159,3 +159,19 @@ lazy val nullObject: String = null
--- ---
(compilation_unit (val_definition (modifiers) (identifier) (type_identifier) (null_literal))) (compilation_unit (val_definition (modifiers) (identifier) (type_identifier) (null_literal)))
==========================
Tuple literals
==========================
val x = (
1,
2,
3,
)
---
(compilation_unit
(val_definition (identifier)
(tuple_expression (integer_literal) (integer_literal) (integer_literal))))

@ -27,7 +27,10 @@ Generic types
=================================== ===================================
object Main { object Main {
type A = B[C, D] type A = B[
C,
D,
]
type E = F.G[H] type E = F.G[H]
} }
@ -52,12 +55,21 @@ Tuple types
object Main { object Main {
type A = (B, C) type A = (B, C)
type A = (
B,
C,
)
} }
--- ---
(compilation_unit (compilation_unit
(object_definition (identifier) (template_body (object_definition (identifier) (template_body
(type_definition
(type_identifier)
(tuple_type
(type_identifier)
(type_identifier)))
(type_definition (type_definition
(type_identifier) (type_identifier)
(tuple_type (tuple_type

@ -210,7 +210,7 @@ module.exports = grammar({
namespace_selectors: $ => seq( namespace_selectors: $ => seq(
'{', '{',
commaSep1(choice( trailingCommaSep1(choice(
$._namespace_given_by_type, $._namespace_given_by_type,
$.namespace_wildcard, $.namespace_wildcard,
$.identifier, $.identifier,
@ -279,7 +279,7 @@ module.exports = grammar({
// make that distinction. // make that distinction.
type_parameters: $ => seq( type_parameters: $ => seq(
'[', '[',
commaSep1($._variant_type_parameter), trailingCommaSep1($._variant_type_parameter),
']' ']'
), ),
@ -599,14 +599,14 @@ module.exports = grammar({
class_parameters: $ => prec(1, seq( class_parameters: $ => prec(1, seq(
'(', '(',
optional(choice('implicit', 'using')), optional(choice('implicit', 'using')),
commaSep($.class_parameter), trailingCommaSep($.class_parameter),
')' ')'
)), )),
parameters: $ => seq( parameters: $ => seq(
'(', '(',
optional(choice('implicit', 'using')), optional(choice('implicit', 'using')),
commaSep($.parameter), trailingCommaSep($.parameter),
')' ')'
), ),
@ -704,7 +704,7 @@ module.exports = grammar({
tuple_type: $ => seq( tuple_type: $ => seq(
'(', '(',
commaSep1($._type), trailingCommaSep1($._type),
')', ')',
), ),
@ -747,7 +747,7 @@ module.exports = grammar({
parameter_types: $ => prec(-1, choice( parameter_types: $ => prec(-1, choice(
$._annotated_type, $._annotated_type,
// Prioritize a parenthesized param list over a single tuple_type. // Prioritize a parenthesized param list over a single tuple_type.
prec.dynamic(1, seq('(', commaSep($._param_type), ')' )), prec.dynamic(1, seq('(', trailingCommaSep($._param_type), ')' )),
$.compound_type, $.compound_type,
$.infix_type, $.infix_type,
)), )),
@ -790,7 +790,7 @@ module.exports = grammar({
case_class_pattern: $ => seq( case_class_pattern: $ => seq(
field('type', choice($._type_identifier, $.stable_type_identifier)), field('type', choice($._type_identifier, $.stable_type_identifier)),
'(', '(',
field('pattern', commaSep($._pattern)), field('pattern', trailingCommaSep($._pattern)),
')' ')'
), ),
@ -939,7 +939,7 @@ module.exports = grammar({
bindings: $ => seq( bindings: $ => seq(
'(', '(',
commaSep($.binding), trailingCommaSep($.binding),
')', ')',
), ),
@ -1098,6 +1098,7 @@ module.exports = grammar({
'(', '(',
$.expression, $.expression,
repeat1(seq(',', $.expression)), repeat1(seq(',', $.expression)),
optional(','),
')' ')'
), ),
@ -1109,13 +1110,13 @@ module.exports = grammar({
type_arguments: $ => seq( type_arguments: $ => seq(
'[', '[',
commaSep1($._type), trailingCommaSep1($._type),
']' ']'
), ),
arguments: $ => seq( arguments: $ => seq(
'(', '(',
commaSep($.expression), trailingCommaSep($.expression),
')' ')'
), ),
@ -1428,6 +1429,18 @@ function commaSep1(rule) {
return sep1(',', rule) return sep1(',', rule)
} }
function trailingCommaSep(rule) {
return optional(trailingCommaSep1(rule))
}
function trailingCommaSep1(rule) {
return trailingSep1(',', rule)
}
function trailingSep1(delimiter, rule) {
return seq(sep1(delimiter, rule), optional(delimiter))
}
function sep1(delimiter, rule) { function sep1(delimiter, rule) {
return seq(rule, repeat(seq(delimiter, rule))) return seq(rule, repeat(seq(delimiter, rule)))
} }

@ -3,8 +3,8 @@
# This is an integration test to generally check the quality of parsing. # This is an integration test to generally check the quality of parsing.
SCALA_SCALA_LIBRARY_EXPECTED=100 SCALA_SCALA_LIBRARY_EXPECTED=100
SCALA_SCALA_COMPILER_EXPECTED=67 SCALA_SCALA_COMPILER_EXPECTED=66
DOTTY_COMPILER_EXPECTED=66 DOTTY_COMPILER_EXPECTED=65
if [ ! -d "$SCALA_SCALA_DIR" ]; then if [ ! -d "$SCALA_SCALA_DIR" ]; then
echo "\$SCALA_SCALA_DIR must be set" echo "\$SCALA_SCALA_DIR must be set"