@@ -28,8 +28,9 @@ import scala.annotation.{tailrec, switch}
28
28
import rewrites .Rewrites .{patch , overlapsPatch }
29
29
import reporting .Message
30
30
import reporting .messages ._
31
- import config .Feature .sourceVersion
32
- import config .SourceVersion .`3.1`
31
+ import config .Feature .{sourceVersion , migrateTo3 }
32
+ import config .SourceVersion ._
33
+ import config .SourceVersion
33
34
34
35
object Parsers {
35
36
@@ -454,9 +455,10 @@ object Parsers {
454
455
case Tuple (ts) =>
455
456
ts.map(convertToParam(_, mods))
456
457
case t : Typed =>
457
- in.errorOrMigrationWarning(
458
- em " parentheses are required around the parameter of a lambda $rewriteNotice" )
459
- if in.migrateTo3 then
458
+ ctx.errorOrMigrationWarning(
459
+ em " parentheses are required around the parameter of a lambda ${rewriteNotice()}" ,
460
+ in.sourcePos())
461
+ if migrateTo3 then
460
462
patch(source, t.span.startPos, " (" )
461
463
patch(source, t.span.endPos, " )" )
462
464
convertToParam(t, mods) :: Nil
@@ -1188,10 +1190,12 @@ object Parsers {
1188
1190
Quote (t)
1189
1191
}
1190
1192
else {
1191
- in.errorOrMigrationWarning(em """ symbol literal ' ${in.name} is no longer supported,
1192
- |use a string literal " ${in.name}" or an application Symbol(" ${in.name}") instead,
1193
- |or enclose in braces '{ ${in.name}} if you want a quoted expression. """ )
1194
- if in.migrateTo3 then
1193
+ ctx.errorOrMigrationWarning(
1194
+ em """ symbol literal ' ${in.name} is no longer supported,
1195
+ |use a string literal " ${in.name}" or an application Symbol(" ${in.name}") instead,
1196
+ |or enclose in braces '{ ${in.name}} if you want a quoted expression. """ ,
1197
+ in.sourcePos())
1198
+ if migrateTo3 then
1195
1199
patch(source, Span (in.offset, in.offset + 1 ), " Symbol(\" " )
1196
1200
patch(source, Span (in.charOffset - 1 ), " \" )" )
1197
1201
atSpan(in.skipToken()) { SymbolLit (in.strVal) }
@@ -1729,7 +1733,9 @@ object Parsers {
1729
1733
AppliedTypeTree (toplevelTyp(), Ident (pname))
1730
1734
} :: contextBounds(pname)
1731
1735
case VIEWBOUND =>
1732
- in.errorOrMigrationWarning(" view bounds `<%' are deprecated, use a context bound `:' instead" )
1736
+ ctx.errorOrMigrationWarning(
1737
+ " view bounds `<%' are deprecated, use a context bound `:' instead" ,
1738
+ in.sourcePos())
1733
1739
atSpan(in.skipToken()) {
1734
1740
Function (Ident (pname) :: Nil , toplevelTyp())
1735
1741
} :: contextBounds(pname)
@@ -1759,7 +1765,7 @@ object Parsers {
1759
1765
* the initially parsed (...) region?
1760
1766
*/
1761
1767
def toBeContinued (altToken : Token ): Boolean =
1762
- if in.token == altToken || in.isNewLine || in. migrateTo3 then
1768
+ if in.token == altToken || in.isNewLine || migrateTo3 then
1763
1769
false // a newline token means the expression is finished
1764
1770
else if ! in.canStartStatTokens.contains(in.token)
1765
1771
|| in.isLeadingInfixOperator(inConditional = true )
@@ -1883,17 +1889,18 @@ object Parsers {
1883
1889
}
1884
1890
}
1885
1891
case DO =>
1886
- in .errorOrMigrationWarning(
1892
+ ctx .errorOrMigrationWarning(
1887
1893
i """ `do <body> while <cond>` is no longer supported,
1888
- |use `while ({<body> ; <cond>}) ()` instead. $rewriteNotice""" )
1894
+ |use `while <body> ; <cond>} do ()` instead. ${rewriteNotice()}""" ,
1895
+ in.sourcePos())
1889
1896
val start = in.skipToken()
1890
1897
atSpan(start) {
1891
1898
val body = expr()
1892
1899
if (isStatSep) in.nextToken()
1893
1900
val whileStart = in.offset
1894
1901
accept(WHILE )
1895
1902
val cond = expr()
1896
- if in. migrateTo3 then
1903
+ if migrateTo3 then
1897
1904
patch(source, Span (start, start + 2 ), " while ({" )
1898
1905
patch(source, Span (whileStart, whileStart + 5 ), " ;" )
1899
1906
cond match {
@@ -2080,10 +2087,12 @@ object Parsers {
2080
2087
if sourceVersion.isAtLeast(`3.1`)
2081
2088
// Don't error in non-strict mode, as the alternative syntax "implicit (x: T) => ... "
2082
2089
// is not supported by Scala2.x
2083
- in.errorOrMigrationWarning(s " This syntax is no longer supported; parameter needs to be enclosed in (...) " )
2090
+ ctx.errorOrMigrationWarning(
2091
+ s " This syntax is no longer supported; parameter needs to be enclosed in (...) " ,
2092
+ in.sourcePos())
2084
2093
in.nextToken()
2085
2094
val t = infixType()
2086
- if (false && in. migrateTo3) {
2095
+ if (false && migrateTo3) {
2087
2096
patch(source, Span (start), " (" )
2088
2097
patch(source, Span (in.lastOffset), " )" )
2089
2098
}
@@ -2576,15 +2585,19 @@ object Parsers {
2576
2585
infixPattern() match {
2577
2586
case pt @ Ident (tpnme.WILDCARD_STAR ) =>
2578
2587
if sourceVersion.isAtLeast(`3.1`) then
2579
- in.errorOrMigrationWarning(" The syntax `x @ _*` is no longer supported; use `x : _*` instead" , Span (startOffset(p)))
2588
+ ctx.errorOrMigrationWarning(
2589
+ " The syntax `x @ _*` is no longer supported; use `x : _*` instead" ,
2590
+ in.sourcePos(startOffset(p)))
2580
2591
atSpan(startOffset(p), offset) { Typed (p, pt) }
2581
2592
case pt =>
2582
2593
atSpan(startOffset(p), 0 ) { Bind (name, pt) }
2583
2594
}
2584
2595
case p @ Ident (tpnme.WILDCARD_STAR ) =>
2585
2596
// compatibility for Scala2 `_*` syntax
2586
2597
if sourceVersion.isAtLeast(`3.1`) then
2587
- in.errorOrMigrationWarning(" The syntax `_*` is no longer supported; use `x : _*` instead" , Span (startOffset(p)))
2598
+ ctx.errorOrMigrationWarning(
2599
+ " The syntax `_*` is no longer supported; use `x : _*` instead" ,
2600
+ in.sourcePos(startOffset(p)))
2588
2601
atSpan(startOffset(p)) { Typed (Ident (nme.WILDCARD ), p) }
2589
2602
case p =>
2590
2603
p
@@ -3012,6 +3025,25 @@ object Parsers {
3012
3025
}
3013
3026
}
3014
3027
3028
+ /** Create an import node and handle source version imports */
3029
+ def mkImport (outermost : Boolean = false ): ImportConstr = (tree, selectors) =>
3030
+ val isLanguageImport = tree match
3031
+ case Ident (nme.language) => true
3032
+ case Select (Ident (nme.scala), nme.language) => true
3033
+ case _ => false
3034
+ if isLanguageImport then
3035
+ for
3036
+ case ImportSelector (id @ Ident (imported), EmptyTree , _) <- selectors
3037
+ if allSourceVersionNames.contains(imported)
3038
+ do
3039
+ if ! outermost then
3040
+ syntaxError(i " source version import is only allowed at the toplevel " , id.span)
3041
+ else if ctx.compilationUnit.sourceVersion.isDefined then
3042
+ syntaxError(i " duplicate source version import " , id.span)
3043
+ else
3044
+ ctx.compilationUnit.sourceVersion = Some (SourceVersion .valueOf(imported.toString))
3045
+ Import (tree, selectors)
3046
+
3015
3047
/** ImportExpr ::= StableId ‘.’ ImportSpec
3016
3048
* ImportSpec ::= id
3017
3049
* | ‘_’
@@ -3181,8 +3213,10 @@ object Parsers {
3181
3213
def toInsert =
3182
3214
if in.token == LBRACE then s " $resultTypeStr = "
3183
3215
else " : Unit " // trailing space ensures that `def f()def g()` works.
3184
- if in.migrateTo3 then
3185
- in.errorOrMigrationWarning(s " Procedure syntax no longer supported; ` $toInsert` should be inserted here " )
3216
+ if migrateTo3 then
3217
+ ctx.errorOrMigrationWarning(
3218
+ s " Procedure syntax no longer supported; ` $toInsert` should be inserted here " ,
3219
+ in.sourcePos())
3186
3220
patch(source, Span (in.lastOffset), toInsert)
3187
3221
true
3188
3222
else
@@ -3197,7 +3231,7 @@ object Parsers {
3197
3231
case EOF => incompleteInputError(AuxConstructorNeedsNonImplicitParameter ())
3198
3232
case _ => syntaxError(AuxConstructorNeedsNonImplicitParameter (), nameStart)
3199
3233
}
3200
- if (in. migrateTo3) newLineOptWhenFollowedBy(LBRACE )
3234
+ if (migrateTo3) newLineOptWhenFollowedBy(LBRACE )
3201
3235
val rhs = {
3202
3236
if (! (in.token == LBRACE && scala2ProcedureSyntax(" " ))) accept(EQUALS )
3203
3237
atSpan(in.offset) { subPart(constrExpr) }
@@ -3249,7 +3283,7 @@ object Parsers {
3249
3283
toplevelTyp()
3250
3284
else typedOpt()
3251
3285
}
3252
- if (in. migrateTo3) newLineOptWhenFollowedBy(LBRACE )
3286
+ if (migrateTo3) newLineOptWhenFollowedBy(LBRACE )
3253
3287
val rhs =
3254
3288
if (in.token == EQUALS )
3255
3289
in.endMarkerScope(name) {
@@ -3594,7 +3628,9 @@ object Parsers {
3594
3628
if (in.token == EXTENDS ) {
3595
3629
in.nextToken()
3596
3630
if (in.token == LBRACE || in.token == COLONEOL ) {
3597
- in.errorOrMigrationWarning(" `extends` must be followed by at least one parent" )
3631
+ ctx.errorOrMigrationWarning(
3632
+ " `extends` must be followed by at least one parent" ,
3633
+ in.sourcePos())
3598
3634
Nil
3599
3635
}
3600
3636
else constrApps(commaOK = true , templateCanFollow = true )
@@ -3675,7 +3711,7 @@ object Parsers {
3675
3711
* | package object objectDef
3676
3712
* |
3677
3713
*/
3678
- def topStatSeq (): List [Tree ] = {
3714
+ def topStatSeq (outermost : Boolean = false ): List [Tree ] = {
3679
3715
val stats = new ListBuffer [Tree ]
3680
3716
while (! isStatSeqEnd) {
3681
3717
setLastStatOffset()
@@ -3688,7 +3724,7 @@ object Parsers {
3688
3724
else stats += packaging(start)
3689
3725
}
3690
3726
else if (in.token == IMPORT )
3691
- stats ++= importClause(IMPORT , Import )
3727
+ stats ++= importClause(IMPORT , mkImport(outermost) )
3692
3728
else if (in.token == EXPORT )
3693
3729
stats ++= importClause(EXPORT , Export .apply)
3694
3730
else if (in.token == AT || isDefIntro(modifierTokens))
@@ -3739,7 +3775,7 @@ object Parsers {
3739
3775
while (! isStatSeqEnd && ! exitOnError) {
3740
3776
setLastStatOffset()
3741
3777
if (in.token == IMPORT )
3742
- stats ++= importClause(IMPORT , Import )
3778
+ stats ++= importClause(IMPORT , mkImport() )
3743
3779
else if (in.token == EXPORT )
3744
3780
stats ++= importClause(EXPORT , Export .apply)
3745
3781
else if (isDefIntro(modifierTokensOrCase))
@@ -3816,7 +3852,7 @@ object Parsers {
3816
3852
while (! isStatSeqEnd && in.token != CASE && ! exitOnError) {
3817
3853
setLastStatOffset()
3818
3854
if (in.token == IMPORT )
3819
- stats ++= importClause(IMPORT , Import )
3855
+ stats ++= importClause(IMPORT , mkImport() )
3820
3856
else if (isExprIntro)
3821
3857
stats += expr(Location .InBlock )
3822
3858
else if in.token == IMPLICIT && ! in.inModifierPosition() then
@@ -3868,7 +3904,7 @@ object Parsers {
3868
3904
ts ++= topStatSeq()
3869
3905
}
3870
3906
else
3871
- ts ++= topStatSeq()
3907
+ ts ++= topStatSeq(outermost = true )
3872
3908
3873
3909
ts.toList
3874
3910
}
@@ -3881,7 +3917,6 @@ object Parsers {
3881
3917
}
3882
3918
}
3883
3919
3884
-
3885
3920
/** OutlineParser parses top-level declarations in `source` to find declared classes, ignoring their bodies (which
3886
3921
* must only have balanced braces). This is used to map class names to defining sources.
3887
3922
*/
0 commit comments