@@ -931,7 +931,11 @@ object Parsers {
931931 lookahead.nextToken()
932932 if lookahead.isIdent && ! lookahead.isIdent(nme.on) then
933933 lookahead.nextToken()
934+ if lookahead.isNewLine then
935+ lookahead.nextToken()
934936 lookahead.isIdent(nme.on)
937+ || lookahead.token == LBRACE
938+ || lookahead.token == COLON
935939
936940/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
937941
@@ -3471,6 +3475,23 @@ object Parsers {
34713475 Template (constr, parents, Nil , EmptyValDef , Nil )
34723476 }
34733477
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+
34743495 /** GivenDef ::= [GivenSig] [‘_’ ‘<:’] Type ‘=’ Expr
34753496 * | [GivenSig] ConstrApps [TemplateBody]
34763497 * GivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘as’
@@ -3517,22 +3538,27 @@ object Parsers {
35173538 finalizeDef(gdef, mods1, start)
35183539 }
35193540
3520- /** ExtensionDef ::= [id] ‘on’ ExtParamClause {UsingParamClause} ExtMethods
3541+ /** ExtensionDef ::= [id] [ ‘on’ ExtParamClause {UsingParamClause}] TemplateBody
35213542 */
35223543 def extensionDef (start : Offset , mods : Modifiers ): ModuleDef =
35233544 in.nextToken()
35243545 val name = if isIdent && ! isIdent(nme.on) then ident() else EmptyTermName
35253546 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 )
35313556 possibleTemplateStart()
35323557 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, _))
35343560 val edef = ModuleDef (name, templ)
3535- finalizeDef(edef, addFlag(mods, Given ), start)
3561+ finalizeDef(edef, addFlag(mods, Given | extensionFlag ), start)
35363562 }
35373563
35383564/* -------- TEMPLATES ------------------------------------------- */
0 commit comments