@@ -376,13 +376,13 @@ object Parsers {
376
376
in.nextToken() // needed to ensure progress; otherwise we might cycle forever
377
377
accept(SEMI )
378
378
379
- def rewriteNotice (additionalOption : String = " " ) = {
379
+ def rewriteNotice (version : String = " 3.0 " , additionalOption : String = " " ) = {
380
380
val optionStr = if (additionalOption.isEmpty) " " else " " ++ additionalOption
381
- i " \n This construct can be rewritten automatically under $optionStr -rewrite -source 3.0 -migration. "
381
+ i " \n This construct can be rewritten automatically under $optionStr -rewrite -source $version -migration. "
382
382
}
383
383
384
384
def syntaxVersionError (option : String , span : Span ) =
385
- syntaxError(em """ This construct is not allowed under $option. ${rewriteNotice(option)}""" , span)
385
+ syntaxError(em """ This construct is not allowed under $option. ${rewriteNotice(" 3.0 " , option)}""" , span)
386
386
387
387
def rewriteToNewSyntax (span : Span = Span (in.offset)): Boolean = {
388
388
if (in.newSyntax) {
@@ -919,7 +919,20 @@ object Parsers {
919
919
val next = in.lookahead.token
920
920
next == LBRACKET || next == LPAREN
921
921
922
- /* --------- OPERAND/OPERATOR STACK --------------------------------------- */
922
+ /** Is current ident a `*`, and is it followed by a `)` or `, )`? */
923
+ def followingIsVararg (): Boolean =
924
+ in.isIdent(nme.raw.STAR ) && {
925
+ val lookahead = in.LookaheadScanner ()
926
+ lookahead.nextToken()
927
+ lookahead.token == RPAREN
928
+ || lookahead.token == COMMA
929
+ && {
930
+ lookahead.nextToken()
931
+ lookahead.token == RPAREN
932
+ }
933
+ }
934
+
935
+ /* --------- OPERAND/OPERATOR STACK --------------------------------------- */
923
936
924
937
var opStack : List [OpInfo ] = Nil
925
938
@@ -956,8 +969,8 @@ object Parsers {
956
969
*/
957
970
def infixOps (
958
971
first : Tree , canStartOperand : Token => Boolean , operand : () => Tree ,
959
- isType : Boolean = false ,
960
- isOperator : => Boolean = true ,
972
+ isType : Boolean ,
973
+ isOperator : => Boolean ,
961
974
maybePostfix : Boolean = false ): Tree = {
962
975
val base = opStack
963
976
@@ -1522,15 +1535,9 @@ object Parsers {
1522
1535
*/
1523
1536
def infixType (): Tree = infixTypeRest(refinedType())
1524
1537
1525
- /** Is current ident a `*`, and is it followed by a `)` or `,`? */
1526
- def isPostfixStar : Boolean =
1527
- in.name == nme.raw.STAR && {
1528
- val nxt = in.lookahead.token
1529
- nxt == RPAREN || nxt == COMMA
1530
- }
1531
-
1532
1538
def infixTypeRest (t : Tree ): Tree =
1533
- infixOps(t, canStartTypeTokens, refinedType, isType = true , isOperator = ! isPostfixStar)
1539
+ infixOps(t, canStartTypeTokens, refinedType, isType = true ,
1540
+ isOperator = ! followingIsVararg())
1534
1541
1535
1542
/** RefinedType ::= WithType {[nl] Refinement}
1536
1543
*/
@@ -2046,7 +2053,7 @@ object Parsers {
2046
2053
case t =>
2047
2054
syntaxError(em " `inline` must be followed by an `if` or a `match` " , start)
2048
2055
t
2049
- else expr1Rest(postfixExpr(), location)
2056
+ else expr1Rest(postfixExpr(location ), location)
2050
2057
end expr1
2051
2058
2052
2059
def expr1Rest (t : Tree , location : Location ): Tree = in.token match
@@ -2068,22 +2075,25 @@ object Parsers {
2068
2075
2069
2076
def ascription (t : Tree , location : Location ): Tree = atSpan(startOffset(t)) {
2070
2077
in.token match {
2071
- case USCORE =>
2078
+ case USCORE if in.lookahead.isIdent(nme.raw. STAR ) =>
2072
2079
val uscoreStart = in.skipToken()
2073
- if isIdent(nme.raw.STAR ) then
2074
- in.nextToken()
2075
- if ! (location.inArgs && in.token == RPAREN ) then
2076
- if opStack.nonEmpty then
2077
- report.errorOrMigrationWarning(
2078
- em """ `_*` can be used only for last argument of method application.
2079
- |It is no longer allowed in operands of infix operations. """ ,
2080
- in.sourcePos(uscoreStart))
2081
- else
2082
- syntaxError(SeqWildcardPatternPos (), uscoreStart)
2083
- Typed (t, atSpan(uscoreStart) { Ident (tpnme.WILDCARD_STAR ) })
2080
+ val isVarargSplice = location.inArgs && followingIsVararg()
2081
+ in.nextToken()
2082
+ if isVarargSplice then
2083
+ if sourceVersion.isAtLeast(`3.1`) then
2084
+ report.errorOrMigrationWarning(
2085
+ em " The syntax `x: _*` is no longer supported for vararg splices; use `x*` instead ${rewriteNotice(" 3.1" )}" ,
2086
+ in.sourcePos(uscoreStart))
2087
+ if sourceVersion == `3.1-migration` then
2088
+ patch(source, Span (t.span.end, in.lastOffset), " *" )
2089
+ else if opStack.nonEmpty then
2090
+ report.errorOrMigrationWarning(
2091
+ em """ `_*` can be used only for last argument of method application.
2092
+ |It is no longer allowed in operands of infix operations. """ ,
2093
+ in.sourcePos(uscoreStart))
2084
2094
else
2085
- syntaxErrorOrIncomplete( IncorrectRepeatedParameterSyntax () )
2086
- t
2095
+ syntaxError( SeqWildcardPatternPos (), uscoreStart )
2096
+ Typed (t, atSpan(uscoreStart) { Ident (tpnme. WILDCARD_STAR ) })
2087
2097
case AT if ! location.inPattern =>
2088
2098
annotations().foldLeft(t)(Annotated )
2089
2099
case _ =>
@@ -2152,7 +2162,7 @@ object Parsers {
2152
2162
// Don't error in non-strict mode, as the alternative syntax "implicit (x: T) => ... "
2153
2163
// is not supported by Scala2.x
2154
2164
report.errorOrMigrationWarning(
2155
- s " This syntax is no longer supported; parameter needs to be enclosed in (...) ${rewriteNotice()}" ,
2165
+ s " This syntax is no longer supported; parameter needs to be enclosed in (...) ${rewriteNotice(" 3.1 " )}" ,
2156
2166
source.atSpan(Span (start, in.lastOffset)))
2157
2167
in.nextToken()
2158
2168
val t = infixType()
@@ -2200,10 +2210,18 @@ object Parsers {
2200
2210
* | InfixExpr id [nl] InfixExpr
2201
2211
* | InfixExpr MatchClause
2202
2212
*/
2203
- def postfixExpr (): Tree = postfixExprRest(prefixExpr())
2213
+ def postfixExpr (location : Location = Location .ElseWhere ): Tree =
2214
+ val t = postfixExprRest(prefixExpr(), location)
2215
+ if location.inArgs && followingIsVararg() then
2216
+ Typed (t, atSpan(in.skipToken()) { Ident (tpnme.WILDCARD_STAR ) })
2217
+ else
2218
+ t
2204
2219
2205
- def postfixExprRest (t : Tree ): Tree =
2206
- infixOps(t, in.canStartExprTokens, prefixExpr, maybePostfix = true )
2220
+ def postfixExprRest (t : Tree , location : Location = Location .ElseWhere ): Tree =
2221
+ infixOps(t, in.canStartExprTokens, prefixExpr,
2222
+ isType = false ,
2223
+ isOperator = ! (location.inArgs && followingIsVararg()),
2224
+ maybePostfix = true )
2207
2225
2208
2226
/** PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr
2209
2227
*/
@@ -2331,7 +2349,7 @@ object Parsers {
2331
2349
if (in.token == RPAREN ) Nil else commaSeparated(exprInParens)
2332
2350
2333
2351
/** ParArgumentExprs ::= `(' [‘using’] [ExprsInParens] `)'
2334
- * | `(' [ExprsInParens `,'] PostfixExpr `:' `_' ` *' ')'
2352
+ * | `(' [ExprsInParens `,'] PostfixExpr `*' ')'
2335
2353
*/
2336
2354
def parArgumentExprs (): (List [Tree ], Boolean ) = inParens {
2337
2355
if in.token == RPAREN then
@@ -2610,37 +2628,44 @@ object Parsers {
2610
2628
ascription(p, location)
2611
2629
else p
2612
2630
2613
- /** Pattern2 ::= [id `as'] InfixPattern
2631
+ /** Pattern3 ::= InfixPattern [‘*’]
2632
+ */
2633
+ def pattern3 (): Tree =
2634
+ val p = infixPattern()
2635
+ if followingIsVararg() then
2636
+ atSpan(in.skipToken()) {
2637
+ Typed (p, Ident (tpnme.WILDCARD_STAR ))
2638
+ }
2639
+ else p
2640
+
2641
+ /** Pattern2 ::= [id `@'] Pattern3
2614
2642
*/
2615
- val pattern2 : () => Tree = () => infixPattern () match {
2643
+ val pattern2 : () => Tree = () => pattern3 () match
2616
2644
case p @ Ident (name) if in.token == AT =>
2617
2645
val offset = in.skipToken()
2618
- infixPattern() match {
2619
- case pt @ Ident (tpnme.WILDCARD_STAR ) => // compatibility for Scala2 `x @ _*` syntax
2620
- warnMigration(p)
2621
- atSpan(startOffset(p), offset) { Typed (p, pt) }
2646
+ pattern3() match {
2622
2647
case pt @ Bind (nme.WILDCARD , pt1 : Typed ) if pt.mods.is(Given ) =>
2623
2648
atSpan(startOffset(p), 0 ) { Bind (name, pt1).withMods(pt.mods) }
2649
+ case Typed (Ident (nme.WILDCARD ), pt @ Ident (tpnme.WILDCARD_STAR )) =>
2650
+ atSpan(startOffset(p), 0 ) { Typed (p, pt) }
2624
2651
case pt =>
2625
2652
atSpan(startOffset(p), 0 ) { Bind (name, pt) }
2626
2653
}
2627
- case p @ Ident (tpnme.WILDCARD_STAR ) =>
2628
- warnMigration(p)
2629
- atSpan(startOffset(p)) { Typed (Ident (nme.WILDCARD ), p) }
2630
2654
case p =>
2631
2655
p
2632
- }
2633
2656
2634
- private def warnMigration (p : Tree ) =
2657
+ private def warnStarMigration (p : Tree ) =
2635
2658
if sourceVersion.isAtLeast(`3.1`) then
2636
2659
report.errorOrMigrationWarning(
2637
- " The syntax `x @ _*` is no longer supported; use `x : _ *` instead" ,
2660
+ em " The syntax `x: _*` is no longer supported for vararg splices ; use `x*` instead " ,
2638
2661
in.sourcePos(startOffset(p)))
2639
2662
2640
2663
/** InfixPattern ::= SimplePattern {id [nl] SimplePattern}
2641
2664
*/
2642
2665
def infixPattern (): Tree =
2643
- infixOps(simplePattern(), in.canStartExprTokens, simplePattern, isOperator = in.name != nme.raw.BAR )
2666
+ infixOps(simplePattern(), in.canStartExprTokens, simplePattern,
2667
+ isType = false ,
2668
+ isOperator = in.name != nme.raw.BAR && ! followingIsVararg())
2644
2669
2645
2670
/** SimplePattern ::= PatVar
2646
2671
* | Literal
@@ -2659,16 +2684,7 @@ object Parsers {
2659
2684
case id @ Ident (nme.raw.MINUS ) if isNumericLit => literal(startOffset(id))
2660
2685
case t => simplePatternRest(t)
2661
2686
case USCORE =>
2662
- val wildIdent = wildcardIdent()
2663
-
2664
- // compatibility for Scala2 `x @ _*` and `_*` syntax
2665
- // `x: _*' is parsed in `ascription'
2666
- if (isIdent(nme.raw.STAR )) {
2667
- in.nextToken()
2668
- if (in.token != RPAREN ) syntaxError(SeqWildcardPatternPos (), wildIdent.span)
2669
- atSpan(wildIdent.span) { Ident (tpnme.WILDCARD_STAR ) }
2670
- }
2671
- else wildIdent
2687
+ wildcardIdent()
2672
2688
case LPAREN =>
2673
2689
atSpan(in.offset) { makeTupleOrParens(inParens(patternsOpt())) }
2674
2690
case QUOTE =>
@@ -2710,7 +2726,7 @@ object Parsers {
2710
2726
if (in.token == RPAREN ) Nil else patterns(location)
2711
2727
2712
2728
/** ArgumentPatterns ::= ‘(’ [Patterns] ‘)’
2713
- * | ‘(’ [Patterns ‘,’] Pattern2 ‘:’ ‘_’ ‘ *’ ‘)’
2729
+ * | ‘(’ [Patterns ‘,’] Pattern2 ‘*’ ‘)’
2714
2730
*/
2715
2731
def argumentPatterns (): List [Tree ] =
2716
2732
inParens(patternsOpt(Location .InPatternArgs ))
0 commit comments