@@ -931,7 +931,11 @@ object Parsers {
931
931
lookahead.nextToken()
932
932
if lookahead.isIdent && ! lookahead.isIdent(nme.on) then
933
933
lookahead.nextToken()
934
+ if lookahead.isNewLine then
935
+ lookahead.nextToken()
934
936
lookahead.isIdent(nme.on)
937
+ || lookahead.token == LBRACE
938
+ || lookahead.token == COLON
935
939
936
940
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
937
941
@@ -3471,6 +3475,23 @@ object Parsers {
3471
3475
Template (constr, parents, Nil , EmptyValDef , Nil )
3472
3476
}
3473
3477
3478
+ def checkExtensionMethod (tparams : List [Tree ],
3479
+ vparamss : List [List [Tree ]], stat : Tree ): Unit = stat match {
3480
+ case stat : DefDef =>
3481
+ if stat.mods.is(Extension ) && vparamss.nonEmpty then
3482
+ syntaxError(i " no extension method allowed here since leading parameter was already given " , stat.span)
3483
+ else if ! stat.mods.is(Extension ) && vparamss.isEmpty then
3484
+ syntaxError(i " an extension method is required here " , stat.span)
3485
+ else if tparams.nonEmpty && stat.tparams.nonEmpty then
3486
+ syntaxError(i " extension method cannot have type parameters since some were already given previously " ,
3487
+ stat.tparams.head.span)
3488
+ else if stat.rhs.isEmpty then
3489
+ syntaxError(i " extension method cannot be abstract " , stat.span)
3490
+ case EmptyTree =>
3491
+ case stat =>
3492
+ syntaxError(i " extension clause can only define methods " , stat.span)
3493
+ }
3494
+
3474
3495
/** GivenDef ::= [GivenSig] [‘_’ ‘<:’] Type ‘=’ Expr
3475
3496
* | [GivenSig] ConstrApps [TemplateBody]
3476
3497
* GivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘as’
@@ -3517,22 +3538,27 @@ object Parsers {
3517
3538
finalizeDef(gdef, mods1, start)
3518
3539
}
3519
3540
3520
- /** ExtensionDef ::= [id] ‘on’ ExtParamClause {UsingParamClause} ExtMethods
3541
+ /** ExtensionDef ::= [id] [ ‘on’ ExtParamClause {UsingParamClause}] TemplateBody
3521
3542
*/
3522
3543
def extensionDef (start : Offset , mods : Modifiers ): ModuleDef =
3523
3544
in.nextToken()
3524
3545
val name = if isIdent && ! isIdent(nme.on) then ident() else EmptyTermName
3525
3546
in.endMarkerScope(if name.isEmpty then nme.extension else name) {
3526
- if ! isIdent(nme.on) then syntaxErrorOrIncomplete(" `on` expected" )
3527
- if isIdent(nme.on) then in.nextToken()
3528
- val tparams = typeParamClauseOpt(ParamOwner .Def )
3529
- val extParams = paramClause(0 , prefix = true )
3530
- val givenParamss = paramClauses(givenOnly = true )
3547
+ val (tparams, vparamss, extensionFlag) =
3548
+ if isIdent(nme.on) then
3549
+ in.nextToken()
3550
+ val tparams = typeParamClauseOpt(ParamOwner .Def )
3551
+ val extParams = paramClause(0 , prefix = true )
3552
+ val givenParamss = paramClauses(givenOnly = true )
3553
+ (tparams, extParams :: givenParamss, Extension )
3554
+ else
3555
+ (Nil , Nil , EmptyFlags )
3531
3556
possibleTemplateStart()
3532
3557
if ! in.isNestedStart then syntaxError(" Extension without extension methods" )
3533
- val templ = templateBodyOpt(makeConstructor(tparams, extParams :: givenParamss), Nil , Nil )
3558
+ val templ = templateBodyOpt(makeConstructor(tparams, vparamss), Nil , Nil )
3559
+ templ.body.foreach(checkExtensionMethod(tparams, vparamss, _))
3534
3560
val edef = ModuleDef (name, templ)
3535
- finalizeDef(edef, addFlag(mods, Given ), start)
3561
+ finalizeDef(edef, addFlag(mods, Given | extensionFlag ), start)
3536
3562
}
3537
3563
3538
3564
/* -------- TEMPLATES ------------------------------------------- */
0 commit comments