@@ -968,6 +968,10 @@ object Parsers {
968
968
val next = in.lookahead.token
969
969
next == LBRACKET || next == LPAREN
970
970
971
+ def followingIsParam (): Boolean =
972
+ startParamTokens.contains(in.token)
973
+ || isIdent && (in.name == nme.inline || in.lookahead.token == COLON )
974
+
971
975
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
972
976
973
977
var opStack : List [OpInfo ] = Nil
@@ -1441,7 +1445,8 @@ object Parsers {
1441
1445
1442
1446
val t =
1443
1447
if in.token == LPAREN then
1444
- afterArguments(x => infixTypeRest(refinedTypeRest(withTypeRest(x))), functionRest)
1448
+ def normalTypeRest (t : Tree ) = infixTypeRest(refinedTypeRest(withTypeRest(t)))
1449
+ maybeParams(typedFunParams, normalTypeRest, functionRest)
1445
1450
else if (in.token == LBRACKET ) {
1446
1451
val tparams = typeParamClause(ParamOwner .TypeParam )
1447
1452
if (in.token == TLARROW )
@@ -1474,14 +1479,18 @@ object Parsers {
1474
1479
}
1475
1480
}
1476
1481
1477
- def funArgTypesRest (first : Tree , following : () => Tree ): List [Tree ] =
1478
- val buf = new ListBuffer [Tree ] += first
1479
- while in.token == COMMA do
1480
- in.nextToken()
1481
- buf += following()
1482
- buf.toList
1483
-
1484
- def afterArguments [T ](parseSimple : Tree => T , parseFn : (List [Tree ], Modifiers ) => T ): T =
1482
+ /** Either a parameter list, which then needs to be followed by `=>` or
1483
+ * a type or constructor application.
1484
+ *
1485
+ * @param parseParams The parsing method for the parameters inside `(...)`
1486
+ * @param parseSimple The parsing continuation if the prefix is not a parameter list
1487
+ * or the prefix is not followed by `=>` or `?=>`
1488
+ * @param parseFn The parsing continuation to follow otherwise.
1489
+ */
1490
+ def maybeParams [T ](
1491
+ parseParams : Modifiers => List [ValDef ],
1492
+ parseSimple : Tree => T ,
1493
+ parseFn : (List [Tree ], Modifiers ) => T ): T =
1485
1494
val start = in.offset
1486
1495
in.nextToken()
1487
1496
var imods = Modifiers ()
@@ -1493,17 +1502,11 @@ object Parsers {
1493
1502
openParens.change(LPAREN , 1 )
1494
1503
imods = modifiers(funTypeArgMods)
1495
1504
val paramStart = in.offset
1496
- val ts = funArgType() match
1497
- case Ident (name) if name != tpnme.WILDCARD && in.token == COLON =>
1498
- isValParamList = true
1499
- funArgTypesRest(
1500
- typedFunParam(paramStart, name.toTermName, imods),
1501
- () => typedFunParam(in.offset, ident(), imods))
1502
- case t =>
1503
- funArgTypesRest(t, funArgType)
1505
+ val isParams = followingIsParam()
1506
+ val ts = if isParams then parseParams(imods) else funArgTypes()
1504
1507
openParens.change(LPAREN , - 1 )
1505
1508
accept(RPAREN )
1506
- if isValParamList || in.token == ARROW || in.token == CTXARROW then
1509
+ if isParams || in.token == ARROW || in.token == CTXARROW then
1507
1510
parseFn(ts, imods)
1508
1511
else
1509
1512
val ts1 =
@@ -1516,7 +1519,7 @@ object Parsers {
1516
1519
t
1517
1520
val tuple = atSpan(start) { makeTupleOrParens(ts1) }
1518
1521
parseSimple(annotTypeRest(simpleTypeRest(tuple)))
1519
- end afterArguments
1522
+ end maybeParams
1520
1523
1521
1524
private def makeKindProjectorTypeDef (name : TypeName ): TypeDef =
1522
1525
TypeDef (name, WildcardTypeBoundsTree ()).withFlags(Param )
@@ -1548,10 +1551,12 @@ object Parsers {
1548
1551
makeParameter(name, typ(), mods)
1549
1552
}
1550
1553
1554
+ def typedFunParams (mods : Modifiers = EmptyModifiers ): List [ValDef ] =
1555
+ commaSeparated(() => typedFunParam(in.offset, ident(), mods))
1556
+
1551
1557
/** FunParamClause ::= ‘(’ TypedFunParam {‘,’ TypedFunParam } ‘)’
1552
1558
*/
1553
- def funParamClause (): List [ValDef ] =
1554
- inParens(commaSeparated(() => typedFunParam(in.offset, ident())))
1559
+ def funParamClause (): List [ValDef ] = inParens(typedFunParams())
1555
1560
1556
1561
def funParamClauses (): List [List [ValDef ]] =
1557
1562
if in.token == LPAREN then funParamClause() :: funParamClauses() else Nil
@@ -1796,6 +1801,10 @@ object Parsers {
1796
1801
if (in.token == ARROW ) atSpan(in.skipToken()) { ByNameTypeTree (typ()) }
1797
1802
else typ()
1798
1803
1804
+ /** FunArgTypes ::= FunArgType { `,` FunArgType}
1805
+ */
1806
+ def funArgTypes (): List [Tree ] = commaSeparated(funArgType)
1807
+
1799
1808
/** ParamType ::= [`=>'] ParamValueType
1800
1809
*/
1801
1810
def paramType (): Tree =
@@ -2965,28 +2974,23 @@ object Parsers {
2965
2974
*
2966
2975
* Param ::= id `:' ParamType [`=' Expr]
2967
2976
*
2977
+ * The method here does not parse the outer `(...)` or any "head" modifiers
2978
+ * in `erased`, `using`, `given`; this has to be done in the caller.
2968
2979
* @return the list of parameter definitions
2969
2980
*/
2970
- def paramClause (nparams : Int , // number of parameters preceding this clause
2981
+ def paramClause (hmods : Modifiers , // parsed modifiers at start of clause
2982
+ nparams : Int = 0 , // number of parameters preceding this clause
2971
2983
ofClass : Boolean = false , // owner is a class
2972
2984
ofCaseClass : Boolean = false , // owner is a case class
2973
2985
prefix : Boolean = false , // clause precedes name of an extension method
2974
2986
givenOnly : Boolean = false , // only given parameters allowed
2975
2987
firstClause : Boolean = false // clause is the first in regular list of clauses
2976
- ): List [ValDef ] = {
2977
- var impliedMods : Modifiers = EmptyModifiers
2978
-
2979
- def addParamMod (mod : () => Mod ) = impliedMods = addMod(impliedMods, atSpan(in.skipToken()) { mod() })
2980
-
2981
- def paramMods () =
2982
- if in.token == IMPLICIT then addParamMod(() => Mod .Implicit ())
2983
- else
2984
- if isIdent(nme.using) then addParamMod(() => Mod .Given ())
2985
- if in.token == ERASED then addParamMod(() => Mod .Erased ())
2988
+ ): List [ValDef ] =
2989
+ var headMods : Modifiers = hmods
2986
2990
2987
2991
def param (): ValDef = {
2988
2992
val start = in.offset
2989
- var mods = impliedMods .withAnnotations(annotations())
2993
+ var mods = headMods .withAnnotations(annotations())
2990
2994
if (ofClass) {
2991
2995
mods = addFlag(modifiers(start = mods), ParamAccessor )
2992
2996
mods =
@@ -2997,7 +3001,7 @@ object Parsers {
2997
3001
val mod = atSpan(in.skipToken()) { Mod .Var () }
2998
3002
addMod(mods, mod)
2999
3003
else
3000
- if (! (mods.flags &~ (ParamAccessor | Inline | impliedMods .flags)).isEmpty)
3004
+ if (! (mods.flags &~ (ParamAccessor | Inline | headMods .flags)).isEmpty)
3001
3005
syntaxError(" `val` or `var` expected" )
3002
3006
if (firstClause && ofCaseClass) mods
3003
3007
else mods | PrivateLocal
@@ -3016,8 +3020,8 @@ object Parsers {
3016
3020
val default =
3017
3021
if (in.token == EQUALS ) { in.nextToken(); subExpr() }
3018
3022
else EmptyTree
3019
- if (impliedMods .mods.nonEmpty)
3020
- impliedMods = impliedMods .withMods(Nil ) // keep only flags, so that parameter positions don't overlap
3023
+ if (headMods .mods.nonEmpty)
3024
+ headMods = headMods .withMods(Nil ) // keep only flags, so that parameter positions don't overlap
3021
3025
ValDef (name, tpt, default).withMods(mods)
3022
3026
}
3023
3027
}
@@ -3034,26 +3038,21 @@ object Parsers {
3034
3038
checkVarArgsRules(rest)
3035
3039
}
3036
3040
3037
- // begin paramClause
3038
- inParens {
3039
- if in.token == RPAREN && ! prefix && ! impliedMods.is(Given ) then Nil
3040
- else
3041
- val clause =
3042
- if prefix then param() :: Nil
3041
+ if in.token == RPAREN && ! prefix && headMods.flags.isEmpty then
3042
+ Nil
3043
+ else
3044
+ val clause =
3045
+ if prefix then param() :: Nil
3046
+ else
3047
+ if givenOnly && ! headMods.is(Given ) then
3048
+ syntaxError(" `using` expected" )
3049
+ if ! headMods.is(Given ) || followingIsParam() then
3050
+ commaSeparated(param)
3043
3051
else
3044
- paramMods()
3045
- if givenOnly && ! impliedMods.is(Given ) then
3046
- syntaxError(" `using` expected" )
3047
- val isParams =
3048
- ! impliedMods.is(Given )
3049
- || startParamTokens.contains(in.token)
3050
- || isIdent && (in.name == nme.inline || in.lookahead.token == COLON )
3051
- if isParams then commaSeparated(() => param())
3052
- else contextTypes(ofClass, nparams)
3053
- checkVarArgsRules(clause)
3054
- clause
3055
- }
3056
- }
3052
+ contextTypes(ofClass, nparams)
3053
+ checkVarArgsRules(clause)
3054
+ clause
3055
+ end paramClause
3057
3056
3058
3057
/** ClsParamClauses ::= {ClsParamClause} [[nl] ‘(’ [‘implicit’] ClsParams ‘)’]
3059
3058
* DefParamClauses ::= {DefParamClause} [[nl] ‘(’ [‘implicit’] DefParams ‘)’]
@@ -3067,13 +3066,22 @@ object Parsers {
3067
3066
def recur (firstClause : Boolean , nparams : Int ): List [List [ValDef ]] =
3068
3067
newLineOptWhenFollowedBy(LPAREN )
3069
3068
if in.token == LPAREN then
3070
- val paramsStart = in.offset
3071
- val params = paramClause(
3072
- nparams,
3073
- ofClass = ofClass,
3074
- ofCaseClass = ofCaseClass,
3075
- givenOnly = givenOnly,
3076
- firstClause = firstClause)
3069
+ val params = inParens {
3070
+ var headMods : Modifiers = EmptyModifiers
3071
+ def addParamMod (mod : () => Mod ) =
3072
+ headMods = addMod(headMods, atSpan(in.skipToken()) { mod() })
3073
+ if in.token == IMPLICIT then addParamMod(() => Mod .Implicit ())
3074
+ else
3075
+ if isIdent(nme.using) then addParamMod(() => Mod .Given ())
3076
+ if in.token == ERASED then addParamMod(() => Mod .Erased ())
3077
+ paramClause(
3078
+ headMods,
3079
+ nparams,
3080
+ ofClass = ofClass,
3081
+ ofCaseClass = ofCaseClass,
3082
+ givenOnly = givenOnly,
3083
+ firstClause = firstClause)
3084
+ }
3077
3085
val lastClause = params.nonEmpty && params.head.mods.flags.is(Implicit )
3078
3086
params :: (
3079
3087
if lastClause then Nil
@@ -3596,12 +3604,13 @@ object Parsers {
3596
3604
(Nil , constrAppsRest(constrAppRest(t), commaOK = true ))
3597
3605
def givenHead (): (List [List [ValDef ]], List [Tree ]) =
3598
3606
if in.token == LPAREN then
3599
- afterArguments( givenHeadFinish, givenHeadRest)
3607
+ maybeParams(paramClause(_), givenHeadFinish, givenHeadRest)
3600
3608
else
3601
3609
val constr = constrOrSimpleType()
3602
3610
if in.token == ARROW then givenHeadRest(constr :: Nil , EmptyModifiers )
3603
3611
else givenHeadFinish(constr)
3604
3612
val (vparamss, parents) = givenHead()
3613
+ newLinesOptWhenFollowedBy(nme.as)
3605
3614
val name =
3606
3615
if in.isIdent(nme.as) then
3607
3616
in.nextToken()
@@ -3637,7 +3646,7 @@ object Parsers {
3637
3646
def extension (): ExtMethods =
3638
3647
val start = in.skipToken()
3639
3648
val tparams = typeParamClauseOpt(ParamOwner .Def )
3640
- val extParams = paramClause(0 , prefix = true )
3649
+ val extParams = inParens( paramClause(EmptyModifiers , prefix = true ) )
3641
3650
val givenParamss = paramClauses(givenOnly = true )
3642
3651
in.observeColonEOL()
3643
3652
if (in.token == COLONEOL ) in.nextToken()
0 commit comments