@@ -1831,8 +1831,10 @@ object Parsers {
1831
1831
* DefParams ::= DefParam {`,' DefParam}
1832
1832
* DefParam ::= {Annotation} [`inline'] Param
1833
1833
* Param ::= id `:' ParamType [`=' Expr]
1834
+ * ImplicitParamClause ::= [nl] ‘(’ ImplicitMods ClsParams ‘)’)
1835
+ * ImplicitMods ::= `implicit` [`unused`] | `unused` `implicit`
1834
1836
*/
1835
- def paramClauses (owner : Name , ofCaseClass : Boolean = false ): List [List [ValDef ]] = {
1837
+ def paramClauses (owner : Name , ofCaseClass : Boolean = false , ofAugmentation : Boolean = false ): List [List [ValDef ]] = {
1836
1838
var imods : Modifiers = EmptyModifiers
1837
1839
var implicitOffset = - 1 // use once
1838
1840
var firstClauseOfCaseClass = ofCaseClass
@@ -1878,7 +1880,7 @@ object Parsers {
1878
1880
}
1879
1881
}
1880
1882
def paramClause (): List [ValDef ] = inParens {
1881
- if (in.token == RPAREN ) Nil
1883
+ if (! ofAugmentation && in.token == RPAREN ) Nil
1882
1884
else {
1883
1885
def funArgMods (): Unit = {
1884
1886
if (in.token == IMPLICIT ) {
@@ -1891,7 +1893,8 @@ object Parsers {
1891
1893
}
1892
1894
}
1893
1895
funArgMods()
1894
-
1896
+ if (ofAugmentation && ! imods.is(Implicit ))
1897
+ syntaxError(i " parameters of augment clause must be implicit " )
1895
1898
commaSeparated(() => param())
1896
1899
}
1897
1900
}
@@ -1901,7 +1904,7 @@ object Parsers {
1901
1904
imods = EmptyModifiers
1902
1905
paramClause() :: {
1903
1906
firstClauseOfCaseClass = false
1904
- if (imods is Implicit ) Nil else clauses()
1907
+ if (imods.is( Implicit ) || ofAugmentation ) Nil else clauses()
1905
1908
}
1906
1909
} else Nil
1907
1910
}
@@ -2180,15 +2183,15 @@ object Parsers {
2180
2183
}
2181
2184
}
2182
2185
2183
- /** ClassDef ::= id ClassConstr TemplateOpt
2186
+ /** ClassDef ::= id ClassConstr [TemplateClause]
2184
2187
*/
2185
2188
def classDef (start : Offset , mods : Modifiers ): TypeDef = atPos(start, nameStart) {
2186
2189
classDefRest(start, mods, ident().toTypeName)
2187
2190
}
2188
2191
2189
2192
def classDefRest (start : Offset , mods : Modifiers , name : TypeName ): TypeDef = {
2190
2193
val constr = classConstr(name, isCaseClass = mods is Case )
2191
- val templ = templateOpt (constr)
2194
+ val templ = templateClauseOpt (constr)
2192
2195
TypeDef (name, templ).withMods(mods).setComment(in.getDocComment(start))
2193
2196
}
2194
2197
@@ -2197,7 +2200,7 @@ object Parsers {
2197
2200
def classConstr (owner : Name , isCaseClass : Boolean = false ): DefDef = atPos(in.lastOffset) {
2198
2201
val tparams = typeParamClauseOpt(ParamOwner .Class )
2199
2202
val cmods = fromWithinClassConstr(constrModsOpt(owner))
2200
- val vparamss = paramClauses(owner, isCaseClass)
2203
+ val vparamss = paramClauses(owner, ofCaseClass = isCaseClass)
2201
2204
makeConstructor(tparams, vparamss).withMods(cmods)
2202
2205
}
2203
2206
@@ -2206,14 +2209,14 @@ object Parsers {
2206
2209
def constrModsOpt (owner : Name ): Modifiers =
2207
2210
modifiers(accessModifierTokens, annotsAsMods())
2208
2211
2209
- /** ObjectDef ::= id TemplateOpt
2212
+ /** ObjectDef ::= id [TemplateClause]
2210
2213
*/
2211
2214
def objectDef (start : Offset , mods : Modifiers ): ModuleDef = atPos(start, nameStart) {
2212
2215
objectDefRest(start, mods, ident())
2213
2216
}
2214
2217
2215
2218
def objectDefRest (start : Offset , mods : Modifiers , name : TermName ): ModuleDef = {
2216
- val template = templateOpt (emptyConstructor)
2219
+ val template = templateClauseOpt (emptyConstructor)
2217
2220
ModuleDef (name, template).withMods(mods).setComment(in.getDocComment(start))
2218
2221
}
2219
2222
@@ -2223,7 +2226,7 @@ object Parsers {
2223
2226
val modName = ident()
2224
2227
val clsName = modName.toTypeName
2225
2228
val constr = classConstr(clsName)
2226
- val impl = templateOpt (constr, isEnum = true )
2229
+ val impl = templateClauseOpt (constr, isEnum = true , bodyRequired = true )
2227
2230
TypeDef (clsName, impl).withMods(addMod(mods, enumMod)).setComment(in.getDocComment(start))
2228
2231
}
2229
2232
@@ -2269,6 +2272,19 @@ object Parsers {
2269
2272
Template (constr, parents, EmptyValDef , Nil )
2270
2273
}
2271
2274
2275
+ /** Augmentation ::= ‘augment’ (id | [id] ClassTypeParamClause)
2276
+ * [[nl] ImplicitParamClause] TemplateClause
2277
+ */
2278
+ def augmentation (): Augment = atPos(in.skipToken(), nameStart) {
2279
+ val (name, tparams) =
2280
+ if (isIdent) (ident().toTypeName, typeParamClauseOpt(ParamOwner .Class ))
2281
+ else (tpnme.EMPTY , typeParamClause(ParamOwner .Class ))
2282
+ val vparamss = paramClauses(name, ofAugmentation = true )
2283
+ val constr = makeConstructor(tparams, vparamss)
2284
+ val templ = templateClauseOpt(constr, bodyRequired = true )
2285
+ Augment (name, templ)
2286
+ }
2287
+
2272
2288
/* -------- TEMPLATES ------------------------------------------- */
2273
2289
2274
2290
/** ConstrApp ::= SimpleType {ParArgumentExprs}
@@ -2285,26 +2301,27 @@ object Parsers {
2285
2301
* @return a pair consisting of the template, and a boolean which indicates
2286
2302
* whether the template misses a body (i.e. no {...} part).
2287
2303
*/
2288
- def template (constr : DefDef , isEnum : Boolean = false ): (Template , Boolean ) = {
2304
+ def template (constr : DefDef , isEnum : Boolean = false , bodyRequired : Boolean = false ): (Template , Boolean ) = {
2289
2305
newLineOptWhenFollowedBy(LBRACE )
2290
2306
if (in.token == LBRACE ) (templateBodyOpt(constr, Nil , isEnum), false )
2291
2307
else {
2292
2308
val parents = tokenSeparated(WITH , constrApp)
2293
2309
newLineOptWhenFollowedBy(LBRACE )
2294
- if (isEnum && in.token != LBRACE )
2310
+ if (bodyRequired && in.token != LBRACE )
2295
2311
syntaxErrorOrIncomplete(ExpectedTokenButFound (LBRACE , in.token))
2296
2312
val missingBody = in.token != LBRACE
2297
2313
(templateBodyOpt(constr, parents, isEnum), missingBody)
2298
2314
}
2299
2315
}
2300
2316
2301
- /** TemplateOpt = [`extends' Template | TemplateBody]
2317
+ /** TemplateClause = `extends' Template | TemplateBody
2318
+ * TemplateClauseOpt = [TemplateClause]
2302
2319
*/
2303
- def templateOpt (constr : DefDef , isEnum : Boolean = false ): Template =
2304
- if (in.token == EXTENDS ) { in.nextToken(); template(constr, isEnum)._1 }
2320
+ def templateClauseOpt (constr : DefDef , isEnum : Boolean = false , bodyRequired : Boolean = false ): Template =
2321
+ if (in.token == EXTENDS ) { in.nextToken(); template(constr, isEnum, bodyRequired )._1 }
2305
2322
else {
2306
2323
newLineOptWhenFollowedBy(LBRACE )
2307
- if (in.token == LBRACE ) template(constr, isEnum)._1
2324
+ if (in.token == LBRACE || bodyRequired ) template(constr, isEnum, bodyRequired )._1
2308
2325
else Template (constr, Nil , EmptyValDef , Nil )
2309
2326
}
2310
2327
@@ -2380,6 +2397,7 @@ object Parsers {
2380
2397
* TemplateStat ::= Import
2381
2398
* | Annotations Modifiers Def
2382
2399
* | Annotations Modifiers Dcl
2400
+ * | Augmentation
2383
2401
* | Expr1
2384
2402
* |
2385
2403
* EnumStat ::= TemplateStat
@@ -2410,6 +2428,8 @@ object Parsers {
2410
2428
setLastStatOffset()
2411
2429
if (in.token == IMPORT )
2412
2430
stats ++= importClause()
2431
+ else if (in.token == AUGMENT )
2432
+ stats += augmentation()
2413
2433
else if (isExprIntro)
2414
2434
stats += expr1()
2415
2435
else if (isDefIntro(modifierTokensOrCase))
@@ -2454,6 +2474,7 @@ object Parsers {
2454
2474
* BlockStat ::= Import
2455
2475
* | Annotations [implicit] [lazy] Def
2456
2476
* | Annotations LocalModifiers TmplDef
2477
+ * | Augmentation
2457
2478
* | Expr1
2458
2479
* |
2459
2480
*/
@@ -2464,6 +2485,8 @@ object Parsers {
2464
2485
setLastStatOffset()
2465
2486
if (in.token == IMPORT )
2466
2487
stats ++= importClause()
2488
+ else if (in.token == AUGMENT )
2489
+ stats += augmentation()
2467
2490
else if (isExprIntro)
2468
2491
stats += expr(Location .InBlock )
2469
2492
else if (isDefIntro(localModifierTokens))
0 commit comments