@@ -51,7 +51,23 @@ object Parsers {
51
51
case ElseWhere extends Location (false , false , false )
52
52
53
53
enum ParamOwner :
54
- case Class , Type , TypeParam , Def
54
+ case Class // class or trait or enum
55
+ case CaseClass // case class or enum case
56
+ case Type // type alias or abstract type
57
+ case TypeParam // type parameter
58
+ case Def // method
59
+ case Given // given definition
60
+ case ExtensionPrefix // extension clause, up to and including extension parameter
61
+ case ExtensionFollow // extension clause, following extension parameter
62
+
63
+ def isClass = // owner is a class
64
+ this == Class || this == CaseClass
65
+ def takesOnlyUsingClauses = // only using clauses allowed for this owner
66
+ this == Given || this == ExtensionFollow
67
+ def acceptsVariance =
68
+ this == Class || this == CaseClass || this == Type
69
+
70
+ end ParamOwner
55
71
56
72
enum ParseKind :
57
73
case Expr , Type , Pattern
@@ -3214,33 +3230,29 @@ object Parsers {
3214
3230
* | UsingParamClause
3215
3231
*/
3216
3232
def typeOrTermParamClauses (
3217
- ownerKind : ParamOwner ,
3218
- numLeadParams : Int = 0
3219
- ): List [List [TypeDef ] | List [ValDef ]] =
3233
+ paramOwner : ParamOwner , numLeadParams : Int = 0 ): List [List [TypeDef ] | List [ValDef ]] =
3220
3234
3221
- def recur (firstClause : Boolean , numLeadParams : Int , prevIsTypeClause : Boolean ): List [List [TypeDef ] | List [ValDef ]] =
3235
+ def recur (numLeadParams : Int , firstClause : Boolean , prevIsTypeClause : Boolean ): List [List [TypeDef ] | List [ValDef ]] =
3222
3236
newLineOptWhenFollowedBy(LPAREN )
3223
3237
newLineOptWhenFollowedBy(LBRACKET )
3224
3238
if in.token == LPAREN then
3225
3239
val paramsStart = in.offset
3226
- val params = termParamClause(
3227
- numLeadParams,
3228
- firstClause = firstClause)
3240
+ val params = termParamClause(paramOwner, numLeadParams, firstClause)
3229
3241
val lastClause = params.nonEmpty && params.head.mods.flags.is(Implicit )
3230
3242
params :: (
3231
3243
if lastClause then Nil
3232
- else recur(firstClause = false , numLeadParams + params.length, prevIsTypeClause = false ))
3244
+ else recur(numLeadParams + params.length, firstClause = false , prevIsTypeClause = false ))
3233
3245
else if in.token == LBRACKET then
3234
3246
if prevIsTypeClause then
3235
3247
syntaxError(
3236
3248
em " Type parameter lists must be separated by a term or using parameter list " ,
3237
3249
in.offset
3238
3250
)
3239
- typeParamClause(ownerKind ) :: recur(firstClause, numLeadParams , prevIsTypeClause = true )
3251
+ typeParamClause(paramOwner ) :: recur(numLeadParams, firstClause , prevIsTypeClause = true )
3240
3252
else Nil
3241
3253
end recur
3242
3254
3243
- recur(firstClause = true , numLeadParams = numLeadParams , prevIsTypeClause = false )
3255
+ recur(numLeadParams, firstClause = true , prevIsTypeClause = false )
3244
3256
end typeOrTermParamClauses
3245
3257
3246
3258
@@ -3259,19 +3271,20 @@ object Parsers {
3259
3271
* HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’
3260
3272
* HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (id [HkTypePamClause] | ‘_’) TypeBounds
3261
3273
*/
3262
- def typeParamClause (ownerKind : ParamOwner ): List [TypeDef ] = inBracketsWithCommas {
3274
+ def typeParamClause (paramOwner : ParamOwner ): List [TypeDef ] = inBracketsWithCommas {
3263
3275
3264
3276
def checkVarianceOK (): Boolean =
3265
- val ok = ownerKind != ParamOwner . Def && ownerKind != ParamOwner . TypeParam
3277
+ val ok = paramOwner.acceptsVariance
3266
3278
if ! ok then syntaxError(em " no `+/-` variance annotation allowed here " )
3267
3279
in.nextToken()
3268
3280
ok
3269
3281
3270
3282
def typeParam (): TypeDef = {
3271
- val isAbstractOwner = ownerKind == ParamOwner .Type || ownerKind == ParamOwner .TypeParam
3283
+ val isAbstractOwner = paramOwner == ParamOwner .Type || paramOwner == ParamOwner .TypeParam
3272
3284
val start = in.offset
3273
3285
var mods = annotsAsMods() | Param
3274
- if ownerKind == ParamOwner .Class then mods |= PrivateLocal
3286
+ if paramOwner == ParamOwner .Class || paramOwner == ParamOwner .CaseClass then
3287
+ mods |= PrivateLocal
3275
3288
if isIdent(nme.raw.PLUS ) && checkVarianceOK() then
3276
3289
mods |= Covariant
3277
3290
else if isIdent(nme.raw.MINUS ) && checkVarianceOK() then
@@ -3291,16 +3304,16 @@ object Parsers {
3291
3304
commaSeparated(() => typeParam())
3292
3305
}
3293
3306
3294
- def typeParamClauseOpt (ownerKind : ParamOwner ): List [TypeDef ] =
3295
- if (in.token == LBRACKET ) typeParamClause(ownerKind ) else Nil
3307
+ def typeParamClauseOpt (paramOwner : ParamOwner ): List [TypeDef ] =
3308
+ if (in.token == LBRACKET ) typeParamClause(paramOwner ) else Nil
3296
3309
3297
3310
/** ContextTypes ::= FunArgType {‘,’ FunArgType}
3298
3311
*/
3299
- def contextTypes (ofClass : Boolean , numLeadParams : Int , impliedMods : Modifiers ): List [ValDef ] =
3312
+ def contextTypes (paramOwner : ParamOwner , numLeadParams : Int , impliedMods : Modifiers ): List [ValDef ] =
3300
3313
val tps = commaSeparated(funArgType)
3301
3314
var counter = numLeadParams
3302
3315
def nextIdx = { counter += 1 ; counter }
3303
- val paramFlags = if ofClass then LocalParamAccessor else Param
3316
+ val paramFlags = if paramOwner.isClass then LocalParamAccessor else Param
3304
3317
tps.map(makeSyntheticParameter(nextIdx, _, paramFlags | Synthetic | impliedMods.flags))
3305
3318
3306
3319
/** ClsTermParamClause ::= ‘(’ ClsParams ‘)’ | UsingClsTermParamClause
@@ -3322,11 +3335,8 @@ object Parsers {
3322
3335
* @return the list of parameter definitions
3323
3336
*/
3324
3337
def termParamClause (
3338
+ paramOwner : ParamOwner ,
3325
3339
numLeadParams : Int , // number of parameters preceding this clause
3326
- ofClass : Boolean = false , // owner is a class
3327
- ofCaseClass : Boolean = false , // owner is a case class
3328
- prefix : Boolean = false , // clause precedes name of an extension method
3329
- givenOnly : Boolean = false , // only given parameters allowed
3330
3340
firstClause : Boolean = false // clause is the first in regular list of clauses
3331
3341
): List [ValDef ] = {
3332
3342
var impliedMods : Modifiers = EmptyModifiers
@@ -3345,7 +3355,7 @@ object Parsers {
3345
3355
var mods = impliedMods.withAnnotations(annotations())
3346
3356
if isErasedKw then
3347
3357
mods = addModifier(mods)
3348
- if (ofClass) {
3358
+ if paramOwner.isClass then
3349
3359
mods = addFlag(modifiers(start = mods), ParamAccessor )
3350
3360
mods =
3351
3361
if in.token == VAL then
@@ -3357,9 +3367,8 @@ object Parsers {
3357
3367
else
3358
3368
if (! (mods.flags &~ (ParamAccessor | Inline | Erased | impliedMods.flags)).isEmpty)
3359
3369
syntaxError(em " `val` or `var` expected " )
3360
- if ( firstClause && ofCaseClass) mods
3370
+ if firstClause && paramOwner == ParamOwner . CaseClass then mods
3361
3371
else mods | PrivateLocal
3362
- }
3363
3372
else {
3364
3373
if (isIdent(nme.inline) && in.isSoftModifierInParamModifierPosition)
3365
3374
mods = addModifier(mods)
@@ -3368,7 +3377,7 @@ object Parsers {
3368
3377
atSpan(start, nameStart) {
3369
3378
val name = ident()
3370
3379
acceptColon()
3371
- if (in.token == ARROW && ofClass && ! mods.is(Local ))
3380
+ if (in.token == ARROW && paramOwner.isClass && ! mods.is(Local ))
3372
3381
syntaxError(VarValParametersMayNotBeCallByName (name, mods.is(Mutable )))
3373
3382
// needed?, it's checked later anyway
3374
3383
val tpt = paramType()
@@ -3397,13 +3406,17 @@ object Parsers {
3397
3406
3398
3407
// begin termParamClause
3399
3408
inParensWithCommas {
3400
- if in.token == RPAREN && ! prefix && ! impliedMods.is(Given ) then Nil
3409
+ if in.token == RPAREN && paramOwner != ParamOwner .ExtensionPrefix && ! impliedMods.is(Given )
3410
+ then Nil
3401
3411
else
3402
3412
val clause =
3403
- if prefix && ! isIdent(nme.using) && ! isIdent(nme.erased) then param() :: Nil
3413
+ if paramOwner == ParamOwner .ExtensionPrefix
3414
+ && ! isIdent(nme.using) && ! isIdent(nme.erased)
3415
+ then
3416
+ param() :: Nil
3404
3417
else
3405
3418
paramMods()
3406
- if givenOnly && ! impliedMods.is(Given ) then
3419
+ if paramOwner.takesOnlyUsingClauses && ! impliedMods.is(Given ) then
3407
3420
syntaxError(em " `using` expected " )
3408
3421
val (firstParamMod, isParams) =
3409
3422
var mods = EmptyModifiers
@@ -3417,7 +3430,7 @@ object Parsers {
3417
3430
|| isIdent && (in.name == nme.inline || in.lookahead.isColon)
3418
3431
(mods, isParams)
3419
3432
(if isParams then commaSeparated(() => param())
3420
- else contextTypes(ofClass , numLeadParams, impliedMods)) match {
3433
+ else contextTypes(paramOwner , numLeadParams, impliedMods)) match {
3421
3434
case Nil => Nil
3422
3435
case (h :: t) => h.withAddedFlags(firstParamMod.flags) :: t
3423
3436
}
@@ -3431,31 +3444,21 @@ object Parsers {
3431
3444
*
3432
3445
* @return The parameter definitions
3433
3446
*/
3434
- def termParamClauses (
3435
- ofClass : Boolean = false ,
3436
- ofCaseClass : Boolean = false ,
3437
- givenOnly : Boolean = false ,
3438
- numLeadParams : Int = 0
3439
- ): List [List [ValDef ]] =
3447
+ def termParamClauses (paramOwner : ParamOwner , numLeadParams : Int = 0 ): List [List [ValDef ]] =
3440
3448
3441
- def recur (firstClause : Boolean , numLeadParams : Int ): List [List [ValDef ]] =
3449
+ def recur (numLeadParams : Int , firstClause : Boolean ): List [List [ValDef ]] =
3442
3450
newLineOptWhenFollowedBy(LPAREN )
3443
3451
if in.token == LPAREN then
3444
3452
val paramsStart = in.offset
3445
- val params = termParamClause(
3446
- numLeadParams,
3447
- ofClass = ofClass,
3448
- ofCaseClass = ofCaseClass,
3449
- givenOnly = givenOnly,
3450
- firstClause = firstClause)
3453
+ val params = termParamClause(paramOwner, numLeadParams, firstClause)
3451
3454
val lastClause = params.nonEmpty && params.head.mods.flags.is(Implicit )
3452
3455
params :: (
3453
3456
if lastClause then Nil
3454
- else recur(firstClause = false , numLeadParams + params.length))
3457
+ else recur(numLeadParams + params.length, firstClause = false ))
3455
3458
else Nil
3456
3459
end recur
3457
3460
3458
- recur(firstClause = true , numLeadParams )
3461
+ recur(numLeadParams, firstClause = true )
3459
3462
end termParamClauses
3460
3463
3461
3464
/* -------- DEFS ------------------------------------------- */
@@ -3727,7 +3730,7 @@ object Parsers {
3727
3730
3728
3731
if (in.token == THIS ) {
3729
3732
in.nextToken()
3730
- val vparamss = termParamClauses(numLeadParams = numLeadParams)
3733
+ val vparamss = termParamClauses(ParamOwner . Def , numLeadParams)
3731
3734
if (vparamss.isEmpty || vparamss.head.take(1 ).exists(_.mods.isOneOf(GivenOrImplicit )))
3732
3735
in.token match {
3733
3736
case LBRACKET => syntaxError(em " no type parameters allowed here " )
@@ -3748,10 +3751,10 @@ object Parsers {
3748
3751
val paramss =
3749
3752
if in.featureEnabled(Feature .clauseInterleaving) then
3750
3753
// If you are making interleaving stable manually, please refer to the PR introducing it instead, section "How to make non-experimental"
3751
- typeOrTermParamClauses(ParamOwner .Def , numLeadParams = numLeadParams )
3754
+ typeOrTermParamClauses(ParamOwner .Def , numLeadParams)
3752
3755
else
3753
3756
val tparams = typeParamClauseOpt(ParamOwner .Def )
3754
- val vparamss = termParamClauses(numLeadParams = numLeadParams)
3757
+ val vparamss = termParamClauses(ParamOwner . Def , numLeadParams)
3755
3758
3756
3759
joinParams(tparams, vparamss)
3757
3760
@@ -3892,16 +3895,16 @@ object Parsers {
3892
3895
}
3893
3896
3894
3897
def classDefRest (start : Offset , mods : Modifiers , name : TypeName ): TypeDef =
3895
- val constr = classConstr(isCaseClass = mods.is(Case ))
3898
+ val constr = classConstr(if mods.is(Case ) then ParamOwner . CaseClass else ParamOwner . Class )
3896
3899
val templ = templateOpt(constr)
3897
3900
finalizeDef(TypeDef (name, templ), mods, start)
3898
3901
3899
3902
/** ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsTermParamClauses
3900
3903
*/
3901
- def classConstr (isCaseClass : Boolean = false ): DefDef = atSpan(in.lastOffset) {
3902
- val tparams = typeParamClauseOpt(ParamOwner . Class )
3904
+ def classConstr (paramOwner : ParamOwner ): DefDef = atSpan(in.lastOffset) {
3905
+ val tparams = typeParamClauseOpt(paramOwner )
3903
3906
val cmods = fromWithinClassConstr(constrModsOpt())
3904
- val vparamss = termParamClauses(ofClass = true , ofCaseClass = isCaseClass )
3907
+ val vparamss = termParamClauses(paramOwner )
3905
3908
makeConstructor(tparams, vparamss).withMods(cmods)
3906
3909
}
3907
3910
@@ -3930,7 +3933,7 @@ object Parsers {
3930
3933
val mods1 = checkAccessOnly(mods, " definitions" )
3931
3934
val modulName = ident()
3932
3935
val clsName = modulName.toTypeName
3933
- val constr = classConstr()
3936
+ val constr = classConstr(ParamOwner . Class )
3934
3937
val templ = template(constr, isEnum = true )
3935
3938
finalizeDef(TypeDef (clsName, templ), mods1, start)
3936
3939
}
@@ -3952,7 +3955,7 @@ object Parsers {
3952
3955
val caseDef =
3953
3956
if (in.token == LBRACKET || in.token == LPAREN || in.token == AT || isModifier) {
3954
3957
val clsName = id.name.toTypeName
3955
- val constr = classConstr(isCaseClass = true )
3958
+ val constr = classConstr(ParamOwner . CaseClass )
3956
3959
TypeDef (clsName, caseTemplate(constr))
3957
3960
}
3958
3961
else
@@ -3999,11 +4002,11 @@ object Parsers {
3999
4002
val name = if isIdent && followingIsGivenSig() then ident() else EmptyTermName
4000
4003
4001
4004
val gdef =
4002
- val tparams = typeParamClauseOpt(ParamOwner .Def )
4005
+ val tparams = typeParamClauseOpt(ParamOwner .Given )
4003
4006
newLineOpt()
4004
4007
val vparamss =
4005
4008
if in.token == LPAREN && in.lookahead.isIdent(nme.using)
4006
- then termParamClauses(givenOnly = true )
4009
+ then termParamClauses(ParamOwner . Given )
4007
4010
else Nil
4008
4011
newLinesOpt()
4009
4012
val noParams = tparams.isEmpty && vparamss.isEmpty
@@ -4043,15 +4046,15 @@ object Parsers {
4043
4046
*/
4044
4047
def extension (): ExtMethods =
4045
4048
val start = in.skipToken()
4046
- val tparams = typeParamClauseOpt(ParamOwner .Def )
4049
+ val tparams = typeParamClauseOpt(ParamOwner .ExtensionPrefix )
4047
4050
val leadParamss = ListBuffer [List [ValDef ]]()
4048
4051
def numLeadParams = leadParamss.map(_.length).sum
4049
4052
while
4050
- val extParams = termParamClause(numLeadParams, prefix = true )
4053
+ val extParams = termParamClause(ParamOwner . ExtensionPrefix , numLeadParams )
4051
4054
leadParamss += extParams
4052
4055
isUsingClause(extParams)
4053
4056
do ()
4054
- leadParamss ++= termParamClauses(givenOnly = true , numLeadParams = numLeadParams)
4057
+ leadParamss ++= termParamClauses(ParamOwner . ExtensionFollow , numLeadParams)
4055
4058
if in.isColon then
4056
4059
syntaxError(em " no `:` expected here " )
4057
4060
in.nextToken()
0 commit comments