summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala13
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/Warnings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala12
-rw-r--r--src/eclipse/partest/.classpath2
-rw-r--r--src/eclipse/scaladoc/.classpath6
-rw-r--r--src/eclipse/test-junit/.classpath2
-rw-r--r--src/intellij/scala.ipr.SAMPLE12
-rw-r--r--src/library/scala/util/control/Exception.scala190
-rw-r--r--src/reflect/scala/reflect/internal/transform/Erasure.scala5
-rw-r--r--src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala26
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala2
-rw-r--r--test/files/pos/constant-warning.check4
-rw-r--r--test/files/pos/constant-warning.flags1
-rw-r--r--test/files/pos/constant-warning.scala3
-rw-r--r--test/junit/scala/issues/RunTest.scala12
-rw-r--r--test/scaladoc/run/t9752.check5
-rw-r--r--test/scaladoc/run/t9752.scala28
-rw-r--r--versions.properties2
19 files changed, 254 insertions, 75 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 847c4cb2d1..94a6a0e4e2 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -394,15 +394,18 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
if (settings.debug && (settings.verbose || currentRun.size < 5))
inform("[running phase " + name + " on " + unit + "]")
+ if (!cancelled(unit)) {
+ currentRun.informUnitStarting(this, unit)
+ try withCurrentUnitNoLog(unit)(task)
+ finally currentRun.advanceUnit()
+ }
+ }
+ final def withCurrentUnitNoLog(unit: CompilationUnit)(task: => Unit) {
val unit0 = currentUnit
try {
currentRun.currentUnit = unit
- if (!cancelled(unit)) {
- currentRun.informUnitStarting(this, unit)
- task
- }
- currentRun.advanceUnit()
+ task
} finally {
//assert(currentUnit == unit)
currentRun.currentUnit = unit0
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
index 340fdc849a..3520d57599 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
@@ -135,7 +135,7 @@ abstract class GenBCode extends BCodeSyncAndTry {
return
}
else {
- try { withCurrentUnit(item.cunit)(visit(item)) }
+ try { withCurrentUnitNoLog(item.cunit)(visit(item)) }
catch {
case ex: Throwable =>
ex.printStackTrace()
diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala
index 310025a336..7ef606b6ef 100644
--- a/src/compiler/scala/tools/nsc/settings/Warnings.scala
+++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala
@@ -59,6 +59,7 @@ trait Warnings {
val PackageObjectClasses = LintWarning("package-object-classes", "Class or object defined in package object.")
val UnsoundMatch = LintWarning("unsound-match", "Pattern match may not be typesafe.")
val StarsAlign = LintWarning("stars-align", "Pattern sequence wildcard must align with sequence component.")
+ val Constant = LintWarning("constant", "Evaluation of a constant arithmetic expression results in an error.")
def allLintWarnings = values.toSeq.asInstanceOf[Seq[LintWarning]]
}
@@ -80,6 +81,7 @@ trait Warnings {
def warnPackageObjectClasses = lint contains PackageObjectClasses
def warnUnsoundMatch = lint contains UnsoundMatch
def warnStarsAlign = lint contains StarsAlign
+ def warnConstant = lint contains Constant
// Lint warnings that are currently -Y, but deprecated in that usage
@deprecated("Use warnAdaptedArgs", since="2.11.2")
diff --git a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
index 828a79ac4f..2cd4785fbf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
@@ -40,9 +40,10 @@ abstract class ConstantFolder {
if ((x ne null) && x.tag != UnitTag) tree setType ConstantType(x)
else tree
} catch {
- case _: ArithmeticException => tree // the code will crash at runtime,
- // but that is better than the
- // compiler itself crashing
+ case e: ArithmeticException =>
+ if (settings.warnConstant)
+ warning(tree.pos, s"Evaluation of a constant expression results in an arithmetic error: ${e.getMessage}")
+ tree
}
private def foldUnop(op: Name, x: Constant): Constant = (op, x.tag) match {
@@ -158,7 +159,7 @@ abstract class ConstantFolder {
else if (x.isNumeric && y.isNumeric) math.max(x.tag, y.tag)
else NoTag
- try optag match {
+ optag match {
case BooleanTag => foldBooleanOp(op, x, y)
case ByteTag | ShortTag | CharTag | IntTag => foldSubrangeOp(op, x, y)
case LongTag => foldLongOp(op, x, y)
@@ -167,8 +168,5 @@ abstract class ConstantFolder {
case StringTag if op == nme.ADD => Constant(x.stringValue + y.stringValue)
case _ => null
}
- catch {
- case _: ArithmeticException => null
- }
}
}
diff --git a/src/eclipse/partest/.classpath b/src/eclipse/partest/.classpath
index 0b98dc67da..ab9ede5a19 100644
--- a/src/eclipse/partest/.classpath
+++ b/src/eclipse/partest/.classpath
@@ -9,6 +9,6 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/scala-compiler"/>
<classpathentry combineaccessrules="false" kind="src" path="/scala-library"/>
- <classpathentry kind="var" path="SCALA_BASEDIR/build/deps/partest/scala-partest_2.12.0_M4-1.0.13.jar"/>
+ <classpathentry kind="var" path="SCALA_BASEDIR/build/deps/partest/scala-partest_2.12.0-M4-1.0.13.jar"/>
<classpathentry kind="output" path="build-quick-partest-extras"/>
</classpath>
diff --git a/src/eclipse/scaladoc/.classpath b/src/eclipse/scaladoc/.classpath
index 870d1da61d..40387983b0 100644
--- a/src/eclipse/scaladoc/.classpath
+++ b/src/eclipse/scaladoc/.classpath
@@ -6,8 +6,8 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/scala-compiler"/>
<classpathentry combineaccessrules="false" kind="src" path="/scala-library"/>
- <classpathentry kind="var" path="SCALA_BASEDIR/build/deps/scaladoc/scala-xml_2.12.0_M4-1.0.5.jar"/>
- <classpathentry kind="var" path="SCALA_BASEDIR/build/deps/scaladoc/scala-parser-combinators_2.12.0_M4-1.0.4.jar"/>
- <classpathentry kind="var" path="SCALA_BASEDIR/build/deps/partest/scala-partest_2.12.0_M4-1.0.13.jar"/>
+ <classpathentry kind="var" path="SCALA_BASEDIR/build/deps/scaladoc/scala-xml_2.12.0-M4-1.0.5.jar"/>
+ <classpathentry kind="var" path="SCALA_BASEDIR/build/deps/scaladoc/scala-parser-combinators_2.12.0-M4-1.0.4.jar"/>
+ <classpathentry kind="var" path="SCALA_BASEDIR/build/deps/partest/scala-partest_2.12.0-M4-1.0.13.jar"/>
<classpathentry kind="output" path="build-quick-scaladoc"/>
</classpath>
diff --git a/src/eclipse/test-junit/.classpath b/src/eclipse/test-junit/.classpath
index 881b2b79ca..3635c85112 100644
--- a/src/eclipse/test-junit/.classpath
+++ b/src/eclipse/test-junit/.classpath
@@ -10,7 +10,7 @@
<classpathentry combineaccessrules="false" kind="src" path="/repl"/>
<classpathentry combineaccessrules="false" kind="src" path="/partest-extras"/>
<classpathentry combineaccessrules="false" kind="src" path="/scaladoc"/>
- <classpathentry kind="var" path="SCALA_BASEDIR/build/deps/scaladoc/scala-xml_2.12.0_M4-1.0.5.jar"/>
+ <classpathentry kind="var" path="SCALA_BASEDIR/build/deps/scaladoc/scala-xml_2.12.0-M4-1.0.5.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="build-test-junit"/>
</classpath>
diff --git a/src/intellij/scala.ipr.SAMPLE b/src/intellij/scala.ipr.SAMPLE
index 8184b0e45b..79ad2808f6 100644
--- a/src/intellij/scala.ipr.SAMPLE
+++ b/src/intellij/scala.ipr.SAMPLE
@@ -77,7 +77,7 @@
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-asm/bundles/scala-asm-5.0.4-scala-3.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12.0-M3-dc9effe/bundles/scala-xml_2.12.0-M3-dc9effe-1.0.5.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.12.0-M3-dc9effe/bundles/scala-parser-combinators_2.12.0-M3-dc9effe-1.0.4.jar!/" />
- <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.12.1.jar!/" />
+ <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.14.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
@@ -100,7 +100,7 @@
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-asm/bundles/scala-asm-5.0.4-scala-3.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12.0-M3-dc9effe/bundles/scala-xml_2.12.0-M3-dc9effe-1.0.5.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.12.0-M3-dc9effe/bundles/scala-parser-combinators_2.12.0-M3-dc9effe-1.0.4.jar!/" />
- <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.12.1.jar!/" />
+ <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.14.1.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-partest_2.12.0-M3-dc9effe/jars/scala-partest_2.12.0-M3-dc9effe-1.0.13.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/com.googlecode.java-diff-utils/diffutils/jars/diffutils-1.3.0.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/test-interface/jars/test-interface-1.0.jar!/" />
@@ -126,7 +126,7 @@
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-asm/bundles/scala-asm-5.0.4-scala-3.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12.0-M3-dc9effe/bundles/scala-xml_2.12.0-M3-dc9effe-1.0.5.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.12.0-M3-dc9effe/bundles/scala-parser-combinators_2.12.0-M3-dc9effe-1.0.4.jar!/" />
- <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.12.1.jar!/" />
+ <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.14.1.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-partest_2.12.0-M3-dc9effe/jars/scala-partest_2.12.0-M3-dc9effe-1.0.13.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/com.googlecode.java-diff-utils/diffutils/jars/diffutils-1.3.0.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/test-interface/jars/test-interface-1.0.jar!/" />
@@ -159,7 +159,7 @@
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-asm/bundles/scala-asm-5.0.4-scala-3.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12.0-M3-dc9effe/bundles/scala-xml_2.12.0-M3-dc9effe-1.0.5.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.12.0-M3-dc9effe/bundles/scala-parser-combinators_2.12.0-M3-dc9effe-1.0.4.jar!/" />
- <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.12.1.jar!/" />
+ <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.14.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
@@ -303,7 +303,7 @@
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-asm/bundles/scala-asm-5.0.4-scala-3.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-xml_2.12.0-M3-dc9effe/bundles/scala-xml_2.12.0-M3-dc9effe-1.0.5.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-parser-combinators_2.12.0-M3-dc9effe/bundles/scala-parser-combinators_2.12.0-M3-dc9effe-1.0.4.jar!/" />
- <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.12.1.jar!/" />
+ <root url="jar://$USER_HOME$/.ivy2/cache/jline/jline/jars/jline-2.14.1.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-lang.modules/scala-partest_2.12.0-M3-dc9effe/jars/scala-partest_2.12.0-M3-dc9effe-1.0.13.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/com.googlecode.java-diff-utils/diffutils/jars/diffutils-1.3.0.jar!/" />
<root url="jar://$USER_HOME$/.ivy2/cache/org.scala-sbt/test-interface/jars/test-interface-1.0.jar!/" />
@@ -312,4 +312,4 @@
<SOURCES />
</library>
</component>
-</project> \ No newline at end of file
+</project>
diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala
index 8aa4073a51..64f491d7f0 100644
--- a/src/library/scala/util/control/Exception.scala
+++ b/src/library/scala/util/control/Exception.scala
@@ -13,21 +13,136 @@ package control
import scala.reflect.{ ClassTag, classTag }
import scala.language.implicitConversions
-
/** Classes representing the components of exception handling.
- * Each class is independently composable. Some example usages:
+ *
+ * Each class is independently composable.
+ *
+ * This class differs from [[scala.util.Try]] in that it focuses on composing exception handlers rather than
+ * composing behavior. All behavior should be composed first and fed to a [[Catch]] object using one of the
+ * `opt`, `either` or `withTry` methods. Taken together the classes provide a DSL for composing catch and finally
+ * behaviors.
+ *
+ * === Examples ===
+ *
+ * Create a `Catch` which handles specified exceptions.
* {{{
* import scala.util.control.Exception._
* import java.net._
*
* val s = "http://www.scala-lang.org/"
- * val x1 = catching(classOf[MalformedURLException]) opt new URL(s)
- * val x2 = catching(classOf[MalformedURLException], classOf[NullPointerException]) either new URL(s)
+ *
+ * // Some(http://www.scala-lang.org/)
+ * val x1: Option[URL] = catching(classOf[MalformedURLException]) opt new URL(s)
+ *
+ * // Right(http://www.scala-lang.org/)
+ * val x2: Either[Throwable,URL] =
+ * catching(classOf[MalformedURLException], classOf[NullPointerException]) either new URL(s)
+ *
+ * // Success(http://www.scala-lang.org/)
+ * val x3: Try[URL] = catching(classOf[MalformedURLException], classOf[NullPointerException]) withTry new URL(s)
+ *
+ * val defaultUrl = new URL("http://example.com")
+ * // URL(http://example.com) because htt/xx throws MalformedURLException
+ * val x4: URL = failAsValue(classOf[MalformedURLException])(defaultUrl)(new URL("htt/xx"))
+ * }}}
+ *
+ * Create a `Catch` which logs exceptions using `handling` and `by`.
+ * {{{
+ * def log(t: Throwable): Unit = t.printStackTrace
+ *
+ * val withThrowableLogging: Catch[Unit] = handling(classOf[MalformedURLException]) by (log)
+ *
+ * def printUrl(url: String) : Unit = {
+ * val con = new URL(url) openConnection()
+ * val source = scala.io.Source.fromInputStream(con.getInputStream())
+ * source.getLines.foreach(println)
+ * }
+ *
+ * val badUrl = "htt/xx"
+ * // Prints stacktrace,
+ * // java.net.MalformedURLException: no protocol: htt/xx
+ * // at java.net.URL.<init>(URL.java:586)
+ * withThrowableLogging { printUrl(badUrl) }
+ *
+ * val goodUrl = "http://www.scala-lang.org/"
+ * // Prints page content,
+ * // &lt;!DOCTYPE html&gt;
+ * // &lt;html&gt;
+ * withThrowableLogging { printUrl(goodUrl) }
+ * }}}
+ *
+ * Use `unwrapping` to create a `Catch` that unwraps exceptions before rethrowing.
+ * {{{
+ * class AppException(cause: Throwable) extends RuntimeException(cause)
+ *
+ * val unwrappingCatch: Catch[Nothing] = unwrapping(classOf[AppException])
+ *
+ * def calcResult: Int = throw new AppException(new NullPointerException)
+ *
+ * // Throws NPE not AppException,
+ * // java.lang.NullPointerException
+ * // at .calcResult(&lt;console&gt;:17)
+ * val result = unwrappingCatch(calcResult)
* }}}
*
- * This class differs from `scala.util.Try` in that it focuses on composing exception handlers rather than
- * composing behavior. All behavior should be composed first and fed to a `Catch` object using one of the
- * `opt` or `either` methods.
+ * Use `failAsValue` to provide a default when a specified exception is caught.
+ *
+ * {{{
+ * val inputDefaulting: Catch[Int] = failAsValue(classOf[NumberFormatException])(0)
+ * val candidatePick = "seven" // scala.io.StdIn.readLine()
+ *
+ * // Int = 0
+ * val pick = inputDefaulting(candidatePick.toInt)
+ * }}}
+ *
+ * Compose multiple `Catch`s with `or` to build a `Catch` that provides default values varied by exception.
+ * {{{
+ * val formatDefaulting: Catch[Int] = failAsValue(classOf[NumberFormatException])(0)
+ * val nullDefaulting: Catch[Int] = failAsValue(classOf[NullPointerException])(-1)
+ * val otherDefaulting: Catch[Int] = nonFatalCatch withApply(_ => -100)
+ *
+ * val combinedDefaulting: Catch[Int] = formatDefaulting or nullDefaulting or otherDefaulting
+ *
+ * def p(s: String): Int = s.length * s.toInt
+ *
+ * // Int = 0
+ * combinedDefaulting(p("tenty-nine"))
+ *
+ * // Int = -1
+ * combinedDefaulting(p(null: String))
+ *
+ * // Int = -100
+ * combinedDefaulting(throw new IllegalStateException)
+ *
+ * // Int = 22
+ * combinedDefaulting(p("11"))
+ * }}}
+ *
+ * @groupname composition-catch Catch behavior composition
+ * @groupprio composition-catch 10
+ * @groupdesc composition-catch Build Catch objects from exception lists and catch logic
+ *
+ * @groupname composition-finally Finally behavior composition
+ * @groupprio composition-finally 20
+ * @groupdesc composition-finally Build Catch objects from finally logic
+ *
+ * @groupname canned-behavior General purpose catch objects
+ * @groupprio canned-behavior 30
+ * @groupdesc canned-behavior Catch objects with predefined behavior. Use combinator methods to compose additional behavior.
+ *
+ * @groupname dsl DSL behavior composition
+ * @groupprio dsl 40
+ * @groupdesc dsl Expressive Catch behavior composition
+ *
+ * @groupname composition-catch-promiscuously Promiscuous Catch behaviors
+ * @groupprio composition-catch-promiscuously 50
+ * @groupdesc composition-catch-promiscuously Useful if catching `ControlThrowable` or `InterruptedException` is required.
+ *
+ * @groupname logic-container Logic Containers
+ * @groupprio logic-container 60
+ * @groupdesc logic-container Containers for catch and finally behavior.
+ *
+ * @define protectedExceptions `ControlThrowable` or `InterruptedException`
*
* @author Paul Phillips
*/
@@ -51,6 +166,7 @@ object Exception {
/** !!! Not at all sure of every factor which goes into this,
* and/or whether we need multiple standard variations.
+ * @return true if `x` is $protectedExceptions otherwise false.
*/
def shouldRethrow(x: Throwable): Boolean = x match {
case _: ControlThrowable => true
@@ -70,7 +186,9 @@ object Exception {
override def toString() = name + "(" + desc + ")"
}
- /** A container class for finally code. */
+ /** A container class for finally code.
+ * @group logic-container
+ */
class Finally private[Exception](body: => Unit) extends Described {
protected val name = "Finally"
@@ -87,6 +205,7 @@ object Exception {
* @param pf Partial function used when applying catch logic to determine result value
* @param fin Finally logic which if defined will be invoked after catch logic
* @param rethrow Predicate on throwables determining when to rethrow a caught [[Throwable]]
+ * @group logic-container
*/
class Catch[+T](
val pf: Catcher[T],
@@ -153,23 +272,30 @@ object Exception {
final def nonFatalCatcher[T]: Catcher[T] = mkThrowableCatcher({ case NonFatal(_) => true; case _ => false }, throw _)
final def allCatcher[T]: Catcher[T] = mkThrowableCatcher(_ => true, throw _)
- /** The empty `Catch` object. */
+ /** The empty `Catch` object.
+ * @group canned-behavior
+ **/
final val noCatch: Catch[Nothing] = new Catch(nothingCatcher) withDesc "<nothing>"
- /** A `Catch` object which catches everything. */
+ /** A `Catch` object which catches everything.
+ * @group canned-behavior
+ **/
final def allCatch[T]: Catch[T] = new Catch(allCatcher[T]) withDesc "<everything>"
- /** A `Catch` object which catches non-fatal exceptions. */
+ /** A `Catch` object which catches non-fatal exceptions.
+ * @group canned-behavior
+ **/
final def nonFatalCatch[T]: Catch[T] = new Catch(nonFatalCatcher[T]) withDesc "<non-fatal>"
/** Creates a `Catch` object which will catch any of the supplied exceptions.
* Since the returned `Catch` object has no specific logic defined and will simply
- * rethrow the exceptions it catches, you will typically want to call `opt` or
- * `either` on the return value, or assign custom logic by calling "withApply".
+ * rethrow the exceptions it catches, you will typically want to call `opt`,
+ * `either` or `withTry` on the return value, or assign custom logic by calling "withApply".
*
* Note that `Catch` objects automatically rethrow `ControlExceptions` and others
* which should only be caught in exceptional circumstances. If you really want
* to catch exactly what you specify, use `catchingPromiscuously` instead.
+ * @group composition-catch
*/
def catching[T](exceptions: Class[_]*): Catch[T] =
new Catch(pfFromExceptions(exceptions : _*)) withDesc (exceptions map (_.getName) mkString ", ")
@@ -178,42 +304,56 @@ object Exception {
/** Creates a `Catch` object which will catch any of the supplied exceptions.
* Unlike "catching" which filters out those in shouldRethrow, this one will
- * catch whatever you ask of it: `ControlThrowable`, `InterruptedException`,
- * `OutOfMemoryError`, you name it.
+ * catch whatever you ask of it including $protectedExceptions.
+ * @group composition-catch-promiscuously
*/
def catchingPromiscuously[T](exceptions: Class[_]*): Catch[T] = catchingPromiscuously(pfFromExceptions(exceptions : _*))
def catchingPromiscuously[T](c: Catcher[T]): Catch[T] = new Catch(c, None, _ => false)
- /** Creates a `Catch` object which catches and ignores any of the supplied exceptions. */
+ /** Creates a `Catch` object which catches and ignores any of the supplied exceptions.
+ * @group composition-catch
+ */
def ignoring(exceptions: Class[_]*): Catch[Unit] =
catching(exceptions: _*) withApply (_ => ())
- /** Creates a `Catch` object which maps all the supplied exceptions to `None`. */
+ /** Creates a `Catch` object which maps all the supplied exceptions to `None`.
+ * @group composition-catch
+ */
def failing[T](exceptions: Class[_]*): Catch[Option[T]] =
catching(exceptions: _*) withApply (_ => None)
- /** Creates a `Catch` object which maps all the supplied exceptions to the given value. */
+ /** Creates a `Catch` object which maps all the supplied exceptions to the given value.
+ * @group composition-catch
+ */
def failAsValue[T](exceptions: Class[_]*)(value: => T): Catch[T] =
catching(exceptions: _*) withApply (_ => value)
+ class By[T,R](f: T => R) {
+ def by(x: T): R = f(x)
+ }
+
/** Returns a partially constructed `Catch` object, which you must give
- * an exception handler function as an argument to `by`. Example:
+ * an exception handler function as an argument to `by`.
+ * @example
* {{{
- * handling(ex1, ex2) by (_.printStackTrace)
+ * handling(classOf[MalformedURLException], classOf[NullPointerException]) by (_.printStackTrace)
* }}}
+ * @group dsl
*/
- class By[T,R](f: T => R) {
- def by(x: T): R = f(x)
- }
+ // TODO: Add return type
def handling[T](exceptions: Class[_]*) = {
def fun(f: Throwable => T) = catching(exceptions: _*) withApply f
new By[Throwable => T, Catch[T]](fun _)
}
- /** Returns a `Catch` object with no catch logic and the argument as `Finally`. */
+ /** Returns a `Catch` object with no catch logic and the argument as the finally logic.
+ * @group composition-finally
+ */
def ultimately[T](body: => Unit): Catch[T] = noCatch andFinally body
- /** Creates a `Catch` object which unwraps any of the supplied exceptions. */
+ /** Creates a `Catch` object which unwraps any of the supplied exceptions.
+ * @group composition-catch
+ */
def unwrapping[T](exceptions: Class[_]*): Catch[T] = {
def unwrap(x: Throwable): Throwable =
if (wouldMatch(x, exceptions) && x.getCause != null) unwrap(x.getCause)
diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala
index c069e2c198..412c49f571 100644
--- a/src/reflect/scala/reflect/internal/transform/Erasure.scala
+++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala
@@ -113,7 +113,8 @@ trait Erasure {
def apply(tp: Type): Type = tp match {
case ConstantType(ct) =>
- if (ct.tag == ClazzTag) ConstantType(Constant(apply(ct.typeValue)))
+ // erase classOf[List[_]] to classOf[List]. special case for classOf[Unit], avoid erasing to classOf[BoxedUnit].
+ if (ct.tag == ClazzTag && ct.typeValue.typeSymbol != UnitClass) ConstantType(Constant(apply(ct.typeValue)))
else tp
case st: ThisType if st.sym.isPackageClass =>
tp
@@ -165,7 +166,7 @@ trait Erasure {
/** The erasure |T| of a type T. This is:
*
- * - For a constant type, itself.
+ * - For a constant type classOf[T], classOf[|T|], unless T is Unit. For any other constant type, itself.
* - For a type-bounds structure, the erasure of its upper bound.
* - For every other singleton type, the erasure of its supertype.
* - For a typeref scala.Array+[T] where T is an abstract type, AnyRef.
diff --git a/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala
index 1f2b0952e7..95964e18d9 100644
--- a/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala
+++ b/src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala
@@ -11,10 +11,9 @@ import java.util.{Collection => JCollection, List => JList}
import _root_.jline.{console => jconsole}
import jline.console.ConsoleReader
-import jline.console.completer.{CompletionHandler, Completer}
+import jline.console.completer.{CandidateListCompletionHandler, Completer, CompletionHandler}
import jconsole.history.{History => JHistory}
-
import scala.tools.nsc.interpreter
import scala.tools.nsc.interpreter.{Completion, NoCompletion}
import scala.tools.nsc.interpreter.Completion.Candidates
@@ -133,32 +132,15 @@ private class JLineConsoleReader extends jconsole.ConsoleReader with interpreter
newCursor
}
}
+ getCompletionHandler match {
+ case clch: CandidateListCompletionHandler => clch.setPrintSpaceAfterFullCompletion(false)
+ }
completion match {
case NoCompletion => ()
case _ => this addCompleter completer
}
- // This is a workaround for https://github.com/jline/jline2/issues/208
- // and should not be necessary once we upgrade to JLine 2.13.1
- ///
- // Test by:
- // scala> {" ".char}<LEFT><TAB>
- //
- // And checking we don't get an extra } on the line.
- ///
- val handler = getCompletionHandler
- setCompletionHandler(new CompletionHandler {
- override def complete(consoleReader: ConsoleReader, list: JList[CharSequence], i: Int): Boolean = {
- try {
- handler.complete(consoleReader, list, i)
- } finally if (getCursorBuffer.cursor != getCursorBuffer.length()) {
- print(" ")
- getCursorBuffer.write(' ')
- backspace()
- }
- }
- })
setAutoprintThreshold(400) // max completion candidates without warning
}
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
index 8cd8a7ee09..d3b4bf8ff5 100644
--- a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
@@ -295,7 +295,7 @@ trait CommentFactoryBase { this: MemberLookupBase =>
}
case line :: ls if (lastTagKey.isDefined) => {
- val newtags = if (!line.isEmpty) {
+ val newtags = if (!line.isEmpty || inCodeBlock) {
val key = lastTagKey.get
val value =
((tags get key): @unchecked) match {
diff --git a/test/files/pos/constant-warning.check b/test/files/pos/constant-warning.check
new file mode 100644
index 0000000000..f7df2165d1
--- /dev/null
+++ b/test/files/pos/constant-warning.check
@@ -0,0 +1,4 @@
+constant-warning.scala:2: warning: Evaluation of a constant expression results in an arithmetic error: / by zero
+ val fails = 1 + 2 / (3 - 2 - 1)
+ ^
+one warning found
diff --git a/test/files/pos/constant-warning.flags b/test/files/pos/constant-warning.flags
new file mode 100644
index 0000000000..d00cbbe77b
--- /dev/null
+++ b/test/files/pos/constant-warning.flags
@@ -0,0 +1 @@
+-Xlint:constant
diff --git a/test/files/pos/constant-warning.scala b/test/files/pos/constant-warning.scala
new file mode 100644
index 0000000000..c8ca8823e7
--- /dev/null
+++ b/test/files/pos/constant-warning.scala
@@ -0,0 +1,3 @@
+object Test {
+ val fails = 1 + 2 / (3 - 2 - 1)
+}
diff --git a/test/junit/scala/issues/RunTest.scala b/test/junit/scala/issues/RunTest.scala
index 781f2ef343..0605947e63 100644
--- a/test/junit/scala/issues/RunTest.scala
+++ b/test/junit/scala/issues/RunTest.scala
@@ -147,4 +147,16 @@ class RunTest extends ClearAfterClass {
assertEquals(run[String](definitions("Object") + runCode), "hi" * 9)
assertEquals(run[String](definitions("String") + runCode), "hi" * 9) // bridge method for clone generated
}
+
+ @Test
+ def classOfUnitConstant(): Unit = {
+ val code =
+ """abstract class A { def f: Class[_] }
+ |class C extends A { final val f = classOf[Unit] }
+ |val c = new C
+ |(c.f, (c: A).f)
+ """.stripMargin
+ val u = Void.TYPE
+ assertEquals(run[(Class[_], Class[_])](code), (u, u))
+ }
}
diff --git a/test/scaladoc/run/t9752.check b/test/scaladoc/run/t9752.check
new file mode 100644
index 0000000000..daeafb8ecc
--- /dev/null
+++ b/test/scaladoc/run/t9752.check
@@ -0,0 +1,5 @@
+List(Body(List(Paragraph(Chain(List(Summary(Text())))), Code(class A
+
+
+class B))))
+Done.
diff --git a/test/scaladoc/run/t9752.scala b/test/scaladoc/run/t9752.scala
new file mode 100644
index 0000000000..b11c7f5c32
--- /dev/null
+++ b/test/scaladoc/run/t9752.scala
@@ -0,0 +1,28 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = s"""
+ /**
+ * Foo
+ *
+ * @example
+ * {{{
+ * class A
+ *
+ *
+ * class B
+ * }}}
+ */
+ object Foo
+ """
+
+ def scaladocSettings = ""
+
+ def testModel(root: Package) = {
+ import access._
+ val obj = root._object("Foo")
+ println(obj.comment.get.example)
+ }
+}
diff --git a/versions.properties b/versions.properties
index d4112325d2..2ab66086fb 100644
--- a/versions.properties
+++ b/versions.properties
@@ -26,7 +26,7 @@ scala-xml.version.number=1.0.5
scala-parser-combinators.version.number=1.0.4
scala-swing.version.number=2.0.0-M2
scala-swing.version.osgi=2.0.0.M2
-jline.version=2.12.1
+jline.version=2.14.1
scala-asm.version=5.0.4-scala-3
# external modules, used internally (not shipped)