@@ -1058,7 +1058,7 @@ object Parsers {
1058
1058
* | PostfixExpr `match' `{' CaseClauses `}'
1059
1059
* Bindings ::= `(' [Binding {`,' Binding}] `)'
1060
1060
* Binding ::= (id | `_') [`:' Type]
1061
- * Ascription ::= `:' CompoundType
1061
+ * Ascription ::= `:' InfixType
1062
1062
* | `:' Annotation {Annotation}
1063
1063
* | `:' `_' `*'
1064
1064
*/
@@ -1178,6 +1178,13 @@ object Parsers {
1178
1178
t
1179
1179
}
1180
1180
1181
+ /** Ascription ::= `:' InfixType
1182
+ * | `:' Annotation {Annotation}
1183
+ * | `:' `_' `*'
1184
+ * PatternAscription ::= `:' TypePattern
1185
+ * | `:' `_' `*'
1186
+ * TypePattern ::= RefinedType
1187
+ */
1181
1188
def ascription (t : Tree , location : Location .Value ) = atPos(startOffset(t)) {
1182
1189
in.skipToken()
1183
1190
in.token match {
@@ -1539,7 +1546,7 @@ object Parsers {
1539
1546
if (isIdent(nme.raw.BAR )) { in.nextToken(); pattern1() :: patternAlts() }
1540
1547
else Nil
1541
1548
1542
- /** Pattern1 ::= PatVar Ascription
1549
+ /** Pattern1 ::= PatVar PatternAscription
1543
1550
* | Pattern2
1544
1551
*/
1545
1552
def pattern1 (): Tree = {
@@ -1831,8 +1838,10 @@ object Parsers {
1831
1838
* DefParams ::= DefParam {`,' DefParam}
1832
1839
* DefParam ::= {Annotation} [`inline'] Param
1833
1840
* Param ::= id `:' ParamType [`=' Expr]
1841
+ * ImplicitParamClause ::= [nl] ‘(’ ImplicitMods ClsParams ‘)’)
1842
+ * ImplicitMods ::= `implicit` [`unused`] | `unused` `implicit`
1834
1843
*/
1835
- def paramClauses (owner : Name , ofCaseClass : Boolean = false ): List [List [ValDef ]] = {
1844
+ def paramClauses (owner : Name , ofCaseClass : Boolean = false , ofExtension : Boolean = false ): List [List [ValDef ]] = {
1836
1845
var imods : Modifiers = EmptyModifiers
1837
1846
var implicitOffset = - 1 // use once
1838
1847
var firstClauseOfCaseClass = ofCaseClass
@@ -1878,7 +1887,7 @@ object Parsers {
1878
1887
}
1879
1888
}
1880
1889
def paramClause (): List [ValDef ] = inParens {
1881
- if (in.token == RPAREN ) Nil
1890
+ if (! ofExtension && in.token == RPAREN ) Nil
1882
1891
else {
1883
1892
def funArgMods (): Unit = {
1884
1893
if (in.token == IMPLICIT ) {
@@ -1891,7 +1900,8 @@ object Parsers {
1891
1900
}
1892
1901
}
1893
1902
funArgMods()
1894
-
1903
+ if (ofExtension && ! imods.is(Implicit ))
1904
+ syntaxError(i " parameters of extension must be implicit " )
1895
1905
commaSeparated(() => param())
1896
1906
}
1897
1907
}
@@ -1901,7 +1911,7 @@ object Parsers {
1901
1911
imods = EmptyModifiers
1902
1912
paramClause() :: {
1903
1913
firstClauseOfCaseClass = false
1904
- if (imods is Implicit ) Nil else clauses()
1914
+ if (imods.is( Implicit ) || ofExtension ) Nil else clauses()
1905
1915
}
1906
1916
} else Nil
1907
1917
}
@@ -2159,6 +2169,7 @@ object Parsers {
2159
2169
/** TmplDef ::= ([`case'] ‘class’ | trait’) ClassDef
2160
2170
* | [`case'] `object' ObjectDef
2161
2171
* | `enum' EnumDef
2172
+ * | `extension' ExtensionDef
2162
2173
*/
2163
2174
def tmplDef (start : Int , mods : Modifiers ): Tree = {
2164
2175
in.token match {
@@ -2174,21 +2185,23 @@ object Parsers {
2174
2185
objectDef(start, posMods(start, mods | Case | Module ))
2175
2186
case ENUM =>
2176
2187
enumDef(start, mods, atPos(in.skipToken()) { Mod .Enum () })
2188
+ case EXTENSION =>
2189
+ extensionDef(start, posMods(start, mods))
2177
2190
case _ =>
2178
2191
syntaxErrorOrIncomplete(ExpectedStartOfTopLevelDefinition ())
2179
2192
EmptyTree
2180
2193
}
2181
2194
}
2182
2195
2183
- /** ClassDef ::= id ClassConstr TemplateOpt
2196
+ /** ClassDef ::= id ClassConstr [TemplateClause]
2184
2197
*/
2185
2198
def classDef (start : Offset , mods : Modifiers ): TypeDef = atPos(start, nameStart) {
2186
2199
classDefRest(start, mods, ident().toTypeName)
2187
2200
}
2188
2201
2189
2202
def classDefRest (start : Offset , mods : Modifiers , name : TypeName ): TypeDef = {
2190
2203
val constr = classConstr(name, isCaseClass = mods is Case )
2191
- val templ = templateOpt (constr)
2204
+ val templ = templateClauseOpt (constr)
2192
2205
TypeDef (name, templ).withMods(mods).setComment(in.getDocComment(start))
2193
2206
}
2194
2207
@@ -2197,7 +2210,7 @@ object Parsers {
2197
2210
def classConstr (owner : Name , isCaseClass : Boolean = false ): DefDef = atPos(in.lastOffset) {
2198
2211
val tparams = typeParamClauseOpt(ParamOwner .Class )
2199
2212
val cmods = fromWithinClassConstr(constrModsOpt(owner))
2200
- val vparamss = paramClauses(owner, isCaseClass)
2213
+ val vparamss = paramClauses(owner, ofCaseClass = isCaseClass)
2201
2214
makeConstructor(tparams, vparamss).withMods(cmods)
2202
2215
}
2203
2216
@@ -2206,14 +2219,14 @@ object Parsers {
2206
2219
def constrModsOpt (owner : Name ): Modifiers =
2207
2220
modifiers(accessModifierTokens, annotsAsMods())
2208
2221
2209
- /** ObjectDef ::= id TemplateOpt
2222
+ /** ObjectDef ::= id [TemplateClause]
2210
2223
*/
2211
2224
def objectDef (start : Offset , mods : Modifiers ): ModuleDef = atPos(start, nameStart) {
2212
2225
objectDefRest(start, mods, ident())
2213
2226
}
2214
2227
2215
2228
def objectDefRest (start : Offset , mods : Modifiers , name : TermName ): ModuleDef = {
2216
- val template = templateOpt (emptyConstructor)
2229
+ val template = templateClauseOpt (emptyConstructor)
2217
2230
ModuleDef (name, template).withMods(mods).setComment(in.getDocComment(start))
2218
2231
}
2219
2232
@@ -2223,7 +2236,7 @@ object Parsers {
2223
2236
val modName = ident()
2224
2237
val clsName = modName.toTypeName
2225
2238
val constr = classConstr(clsName)
2226
- val impl = templateOpt (constr, isEnum = true )
2239
+ val impl = templateClauseOpt (constr, isEnum = true , bodyRequired = true )
2227
2240
TypeDef (clsName, impl).withMods(addMod(mods, enumMod)).setComment(in.getDocComment(start))
2228
2241
}
2229
2242
@@ -2269,6 +2282,36 @@ object Parsers {
2269
2282
Template (constr, parents, EmptyValDef , Nil )
2270
2283
}
2271
2284
2285
+ /** ExtensionDef ::= id [ExtensionParams] 'for' AnnotType ExtensionClause
2286
+ * ExtensionParams ::= [ClsTypeParamClause] [[nl] ImplicitParamClause]
2287
+ * ExtensionClause ::= [`:` Template]
2288
+ * | [nl] `{` `def` DefDef {semi `def` DefDef} `}`
2289
+ */
2290
+ def extensionDef (start : Offset , mods : Modifiers ): Extension = atPos(start, nameStart) {
2291
+ val name = ident().toTypeName
2292
+ val tparams = typeParamClauseOpt(ParamOwner .Class )
2293
+ val vparamss = paramClauses(tpnme.EMPTY , ofExtension = true ).take(1 )
2294
+ val constr = makeConstructor(Nil , vparamss)
2295
+ accept(FOR )
2296
+ val extended = annotType()
2297
+ val templ =
2298
+ if (in.token == COLON ) {
2299
+ in.nextToken()
2300
+ template(constr, bodyRequired = true )._1
2301
+ }
2302
+ else {
2303
+ val templ = templateClauseOpt(constr, bodyRequired = true )
2304
+ def checkDef (tree : Tree ) = tree match {
2305
+ case _ : DefDef | EmptyValDef => // ok
2306
+ case _ => syntaxError(" `def` expected" , tree.pos.startPos.orElse(templ.pos.startPos))
2307
+ }
2308
+ checkDef(templ.self)
2309
+ templ.body.foreach(checkDef)
2310
+ templ
2311
+ }
2312
+ Extension (name, extended, templ)
2313
+ }
2314
+
2272
2315
/* -------- TEMPLATES ------------------------------------------- */
2273
2316
2274
2317
/** ConstrApp ::= SimpleType {ParArgumentExprs}
@@ -2285,26 +2328,30 @@ object Parsers {
2285
2328
* @return a pair consisting of the template, and a boolean which indicates
2286
2329
* whether the template misses a body (i.e. no {...} part).
2287
2330
*/
2288
- def template (constr : DefDef , isEnum : Boolean = false ): (Template , Boolean ) = {
2331
+ def template (constr : DefDef , isEnum : Boolean = false , bodyRequired : Boolean = false ): (Template , Boolean ) = {
2289
2332
newLineOptWhenFollowedBy(LBRACE )
2290
2333
if (in.token == LBRACE ) (templateBodyOpt(constr, Nil , isEnum), false )
2291
2334
else {
2292
2335
val parents = tokenSeparated(WITH , constrApp)
2293
2336
newLineOptWhenFollowedBy(LBRACE )
2294
- if (isEnum && in.token != LBRACE )
2337
+ if (bodyRequired && in.token != LBRACE )
2295
2338
syntaxErrorOrIncomplete(ExpectedTokenButFound (LBRACE , in.token))
2296
2339
val missingBody = in.token != LBRACE
2297
2340
(templateBodyOpt(constr, parents, isEnum), missingBody)
2298
2341
}
2299
2342
}
2300
2343
2301
- /** TemplateOpt = [`extends' Template | TemplateBody]
2344
+ /** TemplateClause = `extends' Template | TemplateBody
2345
+ * TemplateClauseOpt = [TemplateClause]
2302
2346
*/
2303
- def templateOpt (constr : DefDef , isEnum : Boolean = false ): Template =
2304
- if (in.token == EXTENDS ) { in.nextToken(); template(constr, isEnum)._1 }
2347
+ def templateClauseOpt (constr : DefDef , isEnum : Boolean = false , bodyRequired : Boolean = false ): Template =
2348
+ if (in.token == EXTENDS ) {
2349
+ in.nextToken()
2350
+ template(constr, isEnum, bodyRequired)._1
2351
+ }
2305
2352
else {
2306
2353
newLineOptWhenFollowedBy(LBRACE )
2307
- if (in.token == LBRACE ) template(constr, isEnum)._1
2354
+ if (in.token == LBRACE || bodyRequired ) template(constr, isEnum, bodyRequired )._1
2308
2355
else Template (constr, Nil , EmptyValDef , Nil )
2309
2356
}
2310
2357
0 commit comments