@@ -28,8 +28,9 @@ import scala.annotation.{tailrec, switch}
2828import rewrites .Rewrites .{patch , overlapsPatch }
2929import reporting .Message
3030import 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
3334
3435object Parsers {
3536
@@ -454,9 +455,10 @@ object Parsers {
454455 case Tuple (ts) =>
455456 ts.map(convertToParam(_, mods))
456457 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
460462 patch(source, t.span.startPos, " (" )
461463 patch(source, t.span.endPos, " )" )
462464 convertToParam(t, mods) :: Nil
@@ -1188,10 +1190,12 @@ object Parsers {
11881190 Quote (t)
11891191 }
11901192 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
11951199 patch(source, Span (in.offset, in.offset + 1 ), " Symbol(\" " )
11961200 patch(source, Span (in.charOffset - 1 ), " \" )" )
11971201 atSpan(in.skipToken()) { SymbolLit (in.strVal) }
@@ -1729,7 +1733,9 @@ object Parsers {
17291733 AppliedTypeTree (toplevelTyp(), Ident (pname))
17301734 } :: contextBounds(pname)
17311735 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())
17331739 atSpan(in.skipToken()) {
17341740 Function (Ident (pname) :: Nil , toplevelTyp())
17351741 } :: contextBounds(pname)
@@ -1759,7 +1765,7 @@ object Parsers {
17591765 * the initially parsed (...) region?
17601766 */
17611767 def toBeContinued (altToken : Token ): Boolean =
1762- if in.token == altToken || in.isNewLine || in. migrateTo3 then
1768+ if in.token == altToken || in.isNewLine || migrateTo3 then
17631769 false // a newline token means the expression is finished
17641770 else if ! in.canStartStatTokens.contains(in.token)
17651771 || in.isLeadingInfixOperator(inConditional = true )
@@ -1883,17 +1889,18 @@ object Parsers {
18831889 }
18841890 }
18851891 case DO =>
1886- in .errorOrMigrationWarning(
1892+ ctx .errorOrMigrationWarning(
18871893 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())
18891896 val start = in.skipToken()
18901897 atSpan(start) {
18911898 val body = expr()
18921899 if (isStatSep) in.nextToken()
18931900 val whileStart = in.offset
18941901 accept(WHILE )
18951902 val cond = expr()
1896- if in. migrateTo3 then
1903+ if migrateTo3 then
18971904 patch(source, Span (start, start + 2 ), " while ({" )
18981905 patch(source, Span (whileStart, whileStart + 5 ), " ;" )
18991906 cond match {
@@ -2080,10 +2087,12 @@ object Parsers {
20802087 if sourceVersion.isAtLeast(`3.1`)
20812088 // Don't error in non-strict mode, as the alternative syntax "implicit (x: T) => ... "
20822089 // 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())
20842093 in.nextToken()
20852094 val t = infixType()
2086- if (false && in. migrateTo3) {
2095+ if (false && migrateTo3) {
20872096 patch(source, Span (start), " (" )
20882097 patch(source, Span (in.lastOffset), " )" )
20892098 }
@@ -2576,15 +2585,19 @@ object Parsers {
25762585 infixPattern() match {
25772586 case pt @ Ident (tpnme.WILDCARD_STAR ) =>
25782587 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)))
25802591 atSpan(startOffset(p), offset) { Typed (p, pt) }
25812592 case pt =>
25822593 atSpan(startOffset(p), 0 ) { Bind (name, pt) }
25832594 }
25842595 case p @ Ident (tpnme.WILDCARD_STAR ) =>
25852596 // compatibility for Scala2 `_*` syntax
25862597 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)))
25882601 atSpan(startOffset(p)) { Typed (Ident (nme.WILDCARD ), p) }
25892602 case p =>
25902603 p
@@ -3012,6 +3025,25 @@ object Parsers {
30123025 }
30133026 }
30143027
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+
30153047 /** ImportExpr ::= StableId ‘.’ ImportSpec
30163048 * ImportSpec ::= id
30173049 * | ‘_’
@@ -3181,8 +3213,10 @@ object Parsers {
31813213 def toInsert =
31823214 if in.token == LBRACE then s " $resultTypeStr = "
31833215 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())
31863220 patch(source, Span (in.lastOffset), toInsert)
31873221 true
31883222 else
@@ -3197,7 +3231,7 @@ object Parsers {
31973231 case EOF => incompleteInputError(AuxConstructorNeedsNonImplicitParameter ())
31983232 case _ => syntaxError(AuxConstructorNeedsNonImplicitParameter (), nameStart)
31993233 }
3200- if (in. migrateTo3) newLineOptWhenFollowedBy(LBRACE )
3234+ if (migrateTo3) newLineOptWhenFollowedBy(LBRACE )
32013235 val rhs = {
32023236 if (! (in.token == LBRACE && scala2ProcedureSyntax(" " ))) accept(EQUALS )
32033237 atSpan(in.offset) { subPart(constrExpr) }
@@ -3249,7 +3283,7 @@ object Parsers {
32493283 toplevelTyp()
32503284 else typedOpt()
32513285 }
3252- if (in. migrateTo3) newLineOptWhenFollowedBy(LBRACE )
3286+ if (migrateTo3) newLineOptWhenFollowedBy(LBRACE )
32533287 val rhs =
32543288 if (in.token == EQUALS )
32553289 in.endMarkerScope(name) {
@@ -3594,7 +3628,9 @@ object Parsers {
35943628 if (in.token == EXTENDS ) {
35953629 in.nextToken()
35963630 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())
35983634 Nil
35993635 }
36003636 else constrApps(commaOK = true , templateCanFollow = true )
@@ -3675,7 +3711,7 @@ object Parsers {
36753711 * | package object objectDef
36763712 * |
36773713 */
3678- def topStatSeq (): List [Tree ] = {
3714+ def topStatSeq (outermost : Boolean = false ): List [Tree ] = {
36793715 val stats = new ListBuffer [Tree ]
36803716 while (! isStatSeqEnd) {
36813717 setLastStatOffset()
@@ -3688,7 +3724,7 @@ object Parsers {
36883724 else stats += packaging(start)
36893725 }
36903726 else if (in.token == IMPORT )
3691- stats ++= importClause(IMPORT , Import )
3727+ stats ++= importClause(IMPORT , mkImport(outermost) )
36923728 else if (in.token == EXPORT )
36933729 stats ++= importClause(EXPORT , Export .apply)
36943730 else if (in.token == AT || isDefIntro(modifierTokens))
@@ -3739,7 +3775,7 @@ object Parsers {
37393775 while (! isStatSeqEnd && ! exitOnError) {
37403776 setLastStatOffset()
37413777 if (in.token == IMPORT )
3742- stats ++= importClause(IMPORT , Import )
3778+ stats ++= importClause(IMPORT , mkImport() )
37433779 else if (in.token == EXPORT )
37443780 stats ++= importClause(EXPORT , Export .apply)
37453781 else if (isDefIntro(modifierTokensOrCase))
@@ -3816,7 +3852,7 @@ object Parsers {
38163852 while (! isStatSeqEnd && in.token != CASE && ! exitOnError) {
38173853 setLastStatOffset()
38183854 if (in.token == IMPORT )
3819- stats ++= importClause(IMPORT , Import )
3855+ stats ++= importClause(IMPORT , mkImport() )
38203856 else if (isExprIntro)
38213857 stats += expr(Location .InBlock )
38223858 else if in.token == IMPLICIT && ! in.inModifierPosition() then
@@ -3868,7 +3904,7 @@ object Parsers {
38683904 ts ++= topStatSeq()
38693905 }
38703906 else
3871- ts ++= topStatSeq()
3907+ ts ++= topStatSeq(outermost = true )
38723908
38733909 ts.toList
38743910 }
@@ -3881,7 +3917,6 @@ object Parsers {
38813917 }
38823918 }
38833919
3884-
38853920 /** OutlineParser parses top-level declarations in `source` to find declared classes, ignoring their bodies (which
38863921 * must only have balanced braces). This is used to map class names to defining sources.
38873922 */
0 commit comments