8000 Merge pull request #1998 from JamesIry/2.10.x_6963_2 · scala/scala@b403234 · GitHub
[go: up one dir, main page]

Skip to content

Commit b403234

Browse files
committed
Merge pull request #1998 from JamesIry/2.10.x_6963_2
SI-6963 Add version to -Xmigration
2 parents adf51ee + 1de399d commit b403234

File tree

18 files changed

+318
-16
lines changed

18 files changed

+318
-16
lines changed

src/compiler/scala/tools/nsc/matching/ParallelMatching.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import symtab.Flags
1515
import mutable.ListBuffer
1616
import scala.annotation.elidable
1717
import scala.language.postfixOps
18+
import scala.tools.nsc.settings.ScalaVersion
1819

1920
trait ParallelMatching extends ast.TreeDSL
2021
with MatchSupport
@@ -821,7 +822,7 @@ trait ParallelMatching extends ast.TreeDSL
821822
// match that's unimportant; so we add an instance check only if there
822823
// is a binding.
823824
def bindingWarning() = {
824-
if (isBound && settings.Xmigration28.value) {
825+
if (isBound && settings.Xmigration.value < ScalaVersion.twoDotEight) {
825826
cunit.warning(scrutTree.pos,
826827
"A bound pattern such as 'x @ Pattern' now matches fewer cases than the same pattern with no binding.")
827828
}

src/compiler/scala/tools/nsc/settings/MutableSettings.scala

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ class MutableSettings(val errorFn: String => Unit)
221221
def OutputSetting(outputDirs: OutputDirs, default: String) = add(new OutputSetting(outputDirs, default))
222222
def PhasesSetting(name: String, descr: String, default: String = "") = add(new PhasesSetting(name, descr, default))
223223
def StringSetting(name: String, arg: String, descr: String, default: String) = add(new StringSetting(name, arg, descr, default))
224+
def ScalaVersionSetting(name: String, arg: String, descr: String, default: ScalaVersion) = add(new ScalaVersionSetting(name, arg, descr, default))
224225
def PathSetting(name: String, descr: String, default: String): PathSetting = {
225226
val prepend = StringSetting(name + "/p", "", "", "").internalOnly()
226227
val append = StringSetting(name + "/a", "", "", "").internalOnly()
@@ -486,6 +487,35 @@ class MutableSettings(val errorFn: String => Unit)
486487
withHelpSyntax(name + " <" + arg + ">")
487488
}
488489

490+
/** A setting represented by a Scala version, (`default` unless set) */
491+
class ScalaVersionSetting private[nsc](
492+
name: String,
493+
val arg: String,
494+
descr: String,
495+
default: ScalaVersion)
496+
extends Setting(name, descr) {
497+
import ScalaVersion._
498+
499+
type T = ScalaVersion
500+
protected var v: T = NoScalaVersion
501+
502+
override def tryToSet(args: List[String]) = {
503+
value = default
504+
Some(args)
505+
}
506+
507+
override def tryToSetColon(args: List[String]) = args match {
508+
case Nil => value = default; Some(Nil)
509+
case x :: xs => value = ScalaVersion(x, errorFn) ; Some(xs)
510+
}
511+
512+
override def tryToSetFromPropertyValue(s: String) = tryToSet(List(s))
513+
514+
def unparse: List[String] = if (value == NoScalaVersion) Nil else List(s"${name}:${value.unparse}")
515+
516+
withHelpSyntax(s"${name}:<${arg}>")
517+
}
518+
489519
class PathSetting private[nsc](
490520
name: String,
491521
descr: String,

src/compiler/scala/tools/nsc/settings/ScalaSettings.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ trait ScalaSettings extends AbsScalaSettings
8585
val logFreeTerms = BooleanSetting ("-Xlog-free-terms", "Print a message when reification creates a free term.")
8686
val logFreeTypes = BooleanSetting ("-Xlog-free-types", "Print a message when reification resorts to generating a free type.")
8787
val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None)
88-
val Xmigration28 = BooleanSetting ("-Xmigration", "Warn about constructs whose behavior may have changed between 2.7 and 2.8.").
89-
withDeprecationMessage("This setting is no longer useful and will be removed. Please remove it from your build.")
88+
val Xmigration = ScalaVersionSetting("-Xmigration", "version", "Warn about constructs whose behavior may have changed since version.", AnyScalaVersion)
9089
val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.")
9190
val Xnojline = BooleanSetting ("-Xnojline", "Do not use JLine for editing.")
9291
val Xverify = BooleanSetting ("-Xverify", "Verify generic signatures in generated bytecode (asm backend only.)")
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/* NSC -- new Scala compiler
2+
* Copyright 2005-2013 LAMP/EPFL
3+
* @author James Iry
4+
*/
5+
// $Id$
6+
7+
package scala.tools.nsc.settings
8+
9+
/**
10+
* Represents a single Scala version in a manner that
11+
* supports easy comparison and sorting.
12+
*/
13+
abstract class ScalaVersion extends Ordered[ScalaVersion] {
14+
def unparse: String
15+
}
16+
17+
/**
18+
* A scala version that sorts higher than all actual versions
19+
*/
20+
case object NoScalaVersion extends ScalaVersion {
21+
def unparse = "none"
22+
23+
def compare(that: ScalaVersion): Int = that match {
24+
case NoScalaVersion => 0
25+
case _ => 1
26+
}
27+
}
28+
29+
/**
30+
* A specific Scala version, not one of the magic min/max versions. An SpecificScalaVersion
31+
* may or may not be a released version - i.e. this same class is used to represent
32+
* final, release candidate, milestone, and development builds. The build argument is used
33+
* to segregate builds
34+
*/
35+
case class SpecificScalaVersion(major: Int, minor: Int, rev: Int, build: ScalaBuild) extends ScalaVersion {
36+
def unparse = s"${major}.${minor}.${rev}.${build.unparse}"
37+
38+
def compare(that: ScalaVersion): Int = that match {
39+
case SpecificScalaVersion(thatMajor, thatMinor, thatRev, thatBuild) =>
40+
// this could be done more cleanly by importing scala.math.Ordering.Implicits, but we have to do these
41+
// comparisons a lot so I'm using brute force direct style code
42+
if (major < thatMajor) -1
43+
else if (major > thatMajor) 1
44+
else if (minor < thatMinor) -1
45+
else if (minor > thatMinor) 1
46+
else if (rev < thatRev) -1
47+
else if (rev > thatRev) 1
48+
else build compare thatBuild
49+
case AnyScalaVersion => 1
50+
case NoScalaVersion => -1
51+
}
52+
}
53+
54+
/**
55+
* A Scala version that sorts lower than all actual versions
56+
*/
57+
case object AnyScalaVersion extends ScalaVersion {
58+
def unparse = "any"
59+
60+
def compare(that: ScalaVersion): Int = that match {
61+
case AnyScalaVersion => 0
62+
case _ => -1
63+
}
64+
}
65+
66+
/**
67+
* Factory methods for producing ScalaVersions
68+
*/
69+
object ScalaVersion {
70+
private val dot = "\\."
71+
private val dash = "\\-"
72+
private def not(s:String) = s"[^${s}]"
73+
private val R = s"((${not(dot)}*)(${dot}(${not(dot)}*)(${dot}(${not(dash)}*)(${dash}(.*))?)?)?)".r
74+
75+
def apply(versionString : String, errorHandler: String => Unit): ScalaVersion = {
76+
def errorAndValue() = {
77+
errorHandler(
78+
s"There was a problem parsing ${versionString}. " +
79+
"Versions should be in the form major[.minor[.revision]] " +
80+
"where each part is a positive number, as in 2.10.1. " +
81+
"The minor and revision parts are optional."
82+
)
83+
AnyScalaVersion
84+
}
85+
86+
def toInt(s: String) = s match {
87+
case null | "" => 0
88+
case _ => s.toInt
89+
}
90+
91+
def isInt(s: String) = util.Try(toInt(s)).isSuccess
92+
93+
def toBuild(s: String) = s match {
94+
case null | "FINAL" => Final
95+
case s if (s.toUpperCase.startsWith("RC") && isInt(s.substring(2))) => RC(toInt(s.substring(2)))
96+
case s if (s.toUpperCase.startsWith("M") && isInt(s.substring(1))) => Milestone(toInt(s.substring(1)))
97+
case _ => Development(s)
98+
}
99+
100+
try versionString match {
101+
case "none" => NoScalaVersion
102+
case "any" => AnyScalaVersion
103+
case R(_, majorS, _, minorS, _, revS, _, buildS) =>
104+
SpecificScalaVersion(toInt(majorS), toInt(minorS), toInt(revS), toBuild(buildS))
105+
case _ =>
106+
errorAndValue()
107+
} catch {
108+
case e: NumberFormatException => errorAndValue()
109+
}
110+
}
111+
112+
def apply(versionString: String): ScalaVersion =
113+
apply(versionString, msg => throw new NumberFormatException(msg))
114+
115+
/**
116+
* The version of the compiler running now
117+
*/
118+
val current = apply(util.Properties.versionNumberString)
119+
120+
/**
121+
* The 2.8.0 version.
122+
*/
123+
val twoDotEight = SpecificScalaVersion(2, 8, 0, Final)
124+
}
125+
126+
/**
127+
* Represents the data after the dash in major.minor.rev-build
128+
*/
129+
abstract class ScalaBuild extends Ordered[ScalaBuild] {
130+
/**
131+
* Return a version of this build information that can be parsed back into the
132+
* same ScalaBuild
133+
*/
134+
def unparse: String
135+
}
136+
/**
137+
* A development, test, nightly, snapshot or other "unofficial" build
138+
*/
139+
case class Development(id: String) extends ScalaBuild {
140+
def unparse = s"-${id}"
141+
142+
def compare(that: ScalaBuild) = that match {
143+
// sorting two development builds based on id is reasonably valid for two versions created with the same schema
144+
// otherwise it's not correct, but since it's impossible to put a total ordering on development build versions
145+
// this is a pragmatic compromise
146+
case Development(thatId) => id compare thatId
147+
// assume a development build is newer than anything else, that's not really true, but good luck
148+
// mapping development build versions to other build types
149+
case _ => 1
150+
}
151+
}
152+
/**
153+
* A final final
154+
*/
155+
case object Final extends ScalaBuild {
156+
def unparse = ""
157+
158+
def compare(that: ScalaBuild) = that match {
159+
case Final => 0
160+
// a final is newer than anything other than a development build or another final
161+
case Development(_) => -1
162+
case _ => 1
163+
}
164+
}
165+
166+
/**
167+
* A candidate for final release
168+
*/
169+
case class RC(n: Int) extends ScalaBuild {
170+
def unparse = s"-RC${n}"
171+
172+
def compare(that: ScalaBuild) = that match {
173+
// compare two rcs based on their RC numbers
174+
case RC(thatN) => n - thatN
175+
// an rc is older than anything other than a milestone or another rc
176+
case Milestone(_) => 1
177+
case _ => -1
178+
}
179+
}
180+
181+
/**
182+
* An intermediate release
183+
*/
184+
case class Milestone(n: Int) extends ScalaBuild {
185+
def unparse = s"-M${n}"
186+
187+
def compare(that: ScalaBuild) = that match {
188+
// compare two milestones based on their milestone numbers
189+
case Milestone(thatN) => n - thatN
190+
// a milestone is older than anything other than another milestone
191+
case _ => -1
192+
193+
}
194+
}

src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import symtab._
1010
import Flags.{ CASE => _, _ 741A }
1111
import scala.collection.mutable.ListBuffer
1212
import matching.{ Patterns, ParallelMatching }
13+
import scala.tools.nsc.settings.ScalaVersion
1314

1415
/** This class ...
1516
*
@@ -553,7 +554,7 @@ abstract class ExplicitOuter extends InfoTransform
553554
}
554555

555556
case _ =>
556-
if (settings.Xmigration28.value) tree match {
557+
if (settings.Xmigration.value < ScalaVersion.twoDotEight) tree match {
557558
case TypeApply(fn @ Select(qual, _), args) if fn.symbol == Object_isInstanceOf || fn.symbol == Any_isInstanceOf =>
558559
if (isArraySeqTest(qual.tpe, args.head.tpe))
559560
unit.warning(tree.pos, "An Array will no longer match as Seq[_].")

src/compiler/scala/tools/nsc/typechecker/RefChecks.scala

Lines changed: 16 additions & 5 deletions
F438
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import scala.collection.{ mutable, immutable }
1111
import transform.InfoTransform
1212
import scala.collection.mutable.ListBuffer
1313
import scala.language.postfixOps
14+
import scala.tools.nsc.settings.ScalaVersion
15+
import scala.tools.nsc.settings.AnyScalaVersion
16+
import scala.tools.nsc.settings.NoScalaVersion
1417

1518
/** <p>
1619
* Post-attribution checking and transformation.
@@ -1369,10 +1372,18 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
13691372
* indicating it has changed semantics between versions.
13701373
*/
13711374
private def checkMigration(sym: Symbol, pos: Position) = {
1372-
if (sym.hasMigrationAnnotation)
1373-
unit.warning(pos, "%s has changed semantics in version %s:\n%s".format(
1374-
sym.fullLocationString, sym.migrationVersion.get, sym.migrationMessage.get)
1375-
)
1375+
if (sym.hasMigrationAnnotation) {
1376+
val changed = try
1377+
settings.Xmigration.value < ScalaVersion(sym.migrationVersion.get)
1378+
catch {
1379+
case e : NumberFormatException =>
1380+
unit.warning(pos, s"${sym.fullLocationString} has an unparsable version number: ${e.getMessage()}")
1381+
// if we can't parse the format on the migration annotation just conservatively assume it changed
1382+
true
1383+
}
1384+
if (changed)
1385+
unit.warning(pos, s"${sym.fullLocationString} has changed semantics in version ${sym.migrationVersion.get}:\n${sym.migrationMessage.get}")
1386+
}
13761387
}
13771388

13781389
private def checkCompileTimeOnly(sym: Symbol, pos: Position) = {
@@ -1581,7 +1592,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
15811592
* arbitrarily choose one as more important than the other.
15821593
*/
15831594
checkDeprecated(sym, tree.pos)
1584-
if (settings.Xmigration28.value)
1595+
if(settings.Xmigration.value != NoScalaVersion)
15851596
checkMigration(sym, tree.pos)
15861597
checkCompileTimeOnly(sym, tree.pos)
15871598

src/library/scala/annotation/migration.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ package scala.annotation
1717
* order between Scala 2.7 and 2.8.
1818
*
1919
* @param message A message describing the change, which is emitted
20-
* by the compiler if the flag `-Xmigration` is set.
20+
* by the compiler if the flag `-Xmigration` indicates a version
21+
* prior to the changedIn version.
2122
*
2223
* @param changedIn The version, in which the behaviour change was
2324
* introduced.

test/files/neg/t6963.check

Lines changed: 0 additions & 2 deletions
This file was deleted.

test/files/neg/t6963.flags

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/files/neg/t6963.scala

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)
0