diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/util/StackTracing.scala | 44 | ||||
-rw-r--r-- | src/library/scala/util/Properties.scala | 66 |
2 files changed, 66 insertions, 44 deletions
diff --git a/src/compiler/scala/tools/nsc/util/StackTracing.scala b/src/compiler/scala/tools/nsc/util/StackTracing.scala index 0765bb923f..c6749a13f3 100644 --- a/src/compiler/scala/tools/nsc/util/StackTracing.scala +++ b/src/compiler/scala/tools/nsc/util/StackTracing.scala @@ -8,7 +8,7 @@ private[util] trait StackTracing extends Any { /** Format a stack trace, returning the prefix consisting of frames that satisfy * a given predicate. - * The format is similar to the typical case described in the JavaDoc + * The format is similar to the typical case described in the Javadoc * for [[java.lang.Throwable#printStackTrace]]. * If a stack trace is truncated, it will be followed by a line of the form * `... 3 elided`, by analogy to the lines `... 3 more` which indicate @@ -19,25 +19,18 @@ private[util] trait StackTracing extends Any { def stackTracePrefixString(e: Throwable)(p: StackTraceElement => Boolean): String = { import collection.mutable.{ ArrayBuffer, ListBuffer } import compat.Platform.EOL - import scala.util.Properties.isJavaAtLeast - - val sb = ListBuffer.empty[String] type TraceRelation = String val Self = new TraceRelation("") val CausedBy = new TraceRelation("Caused by: ") val Suppressed = new TraceRelation("Suppressed: ") - val suppressable = isJavaAtLeast("1.7") - - def clazz(e: Throwable) = e.getClass.getName + def clazz(e: Throwable): String = e.getClass.getName def because(e: Throwable): String = e.getCause match { case null => null ; case c => header(c) } def msg(e: Throwable): String = e.getMessage match { case null => because(e) ; case s => s } def txt(e: Throwable): String = msg(e) match { case null => "" ; case s => s": $s" } def header(e: Throwable): String = s"${clazz(e)}${txt(e)}" - val indent = "\u0020\u0020" - val seen = new ArrayBuffer[Throwable](16) def unseen(t: Throwable) = { def inSeen = seen exists (_ eq t) @@ -46,28 +39,25 @@ private[util] trait StackTracing extends Any { interesting } + val sb = ListBuffer.empty[String] + + // format the stack trace, skipping the shared trace def print(e: Throwable, r: TraceRelation, share: Array[StackTraceElement], indents: Int): Unit = if (unseen(e)) { val trace = e.getStackTrace - val frames = ( - if (share.nonEmpty) { - val spare = share.reverseIterator - val trimmed = trace.reverse dropWhile (spare.hasNext && spare.next == _) - trimmed.reverse - } else trace - ) - val prefix = frames takeWhile p - val margin = indent * indents - val indented = margin + indent + val frames = if (share.isEmpty) trace else { + val spare = share.reverseIterator + val trimmed = trace.reverse dropWhile (spare.hasNext && spare.next == _) + trimmed.reverse + } + val prefix = frames takeWhile p + val margin = " " * indents + val indent = margin + " " sb append s"${margin}${r}${header(e)}" - prefix foreach (f => sb append s"${indented}at $f") - if (frames.size < trace.size) sb append s"$indented... ${trace.size - frames.size} more" - if (r == Self && prefix.size < frames.size) sb append s"$indented... ${frames.size - prefix.size} elided" + prefix foreach (f => sb append s"${margin} at $f") + if (frames.size < trace.size) sb append s"${margin} ... ${trace.size - frames.size} more" + if (r == Self && prefix.size < frames.size) sb append s"${margin} ... ${frames.size - prefix.size} elided" print(e.getCause, CausedBy, trace, indents) - if (suppressable) { - import scala.language.reflectiveCalls - type Suppressing = { def getSuppressed(): Array[Throwable] } - for (s <- e.asInstanceOf[Suppressing].getSuppressed) print(s, Suppressed, frames, indents + 1) - } + e.getSuppressed foreach (t => print(t, Suppressed, frames, indents + 1)) } print(e, Self, share = Array.empty, indents = 0) diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala index fc2302d148..9d62bfe6ef 100644 --- a/src/library/scala/util/Properties.scala +++ b/src/library/scala/util/Properties.scala @@ -168,29 +168,61 @@ private[scala] trait PropertiesTrait { /** Compares the given specification version to the specification version of the platform. * - * @param version a specification version of the form "major.minor" - * @return `true` iff the specification version of the current runtime - * is equal to or higher than the version denoted by the given string. - * @throws NumberFormatException if the given string is not a version string + * @param version a specification version number (legacy forms acceptable) + * @return `true` if the specification version of the current runtime + * is equal to or higher than the version denoted by the given string. + * @throws NumberFormatException if the given string is not a version string * - * @example {{{ - * // In this example, the runtime's Java specification is assumed to be at version 1.7. - * isJavaAtLeast("1.6") // true - * isJavaAtLeast("1.7") // true - * isJavaAtLeast("1.8") // false - * }}} + * @example {{{ + * // In this example, the runtime's Java specification is assumed to be at version 8. + * isJavaAtLeast("1.8") // true + * isJavaAtLeast("8") // true + * isJavaAtLeast("9") // false + * isJavaAtLeast("9.1") // false + * isJavaAtLeast("1.9") // throws + * }}} */ def isJavaAtLeast(version: String): Boolean = { - def parts(x: String) = { - val i = x.indexOf('.') - if (i < 0) throw new NumberFormatException("Not a version: " + x) - (x.substring(0, i), x.substring(i+1, x.length)) + def versionOf(s: String, depth: Int): (Int, String) = + s.indexOf('.') match { + case 0 => + (-2, s.substring(1)) + case 1 if depth == 0 && s.charAt(0) == '1' => + val r0 = s.substring(2) + val (v, r) = versionOf(r0, 1) + val n = if (v > 8 || r0.isEmpty) -2 else v // accept 1.8, not 1.9 or 1. + (n, r) + case -1 => + val n = if (!s.isEmpty) s.toInt else if (depth == 0) -2 else 0 + (n, "") + case i => + val r = s.substring(i + 1) + val n = if (depth < 2 && r.isEmpty) -2 else s.substring(0, i).toInt + (n, r) + } + def compareVersions(s: String, v: String, depth: Int): Int = { + if (depth >= 3) 0 + else { + val (sn, srest) = versionOf(s, depth) + val (vn, vrest) = versionOf(v, depth) + if (vn < 0) -2 + else if (sn < vn) -1 + else if (sn > vn) 1 + else compareVersions(srest, vrest, depth + 1) + } + } + compareVersions(javaSpecVersion, version, 0) match { + case -2 => throw new NumberFormatException(s"Not a version: $version") + case i => i >= 0 } - val (v, _v) = parts(version) - val (s, _s) = parts(javaSpecVersion) - s.toInt >= v.toInt && _s.toInt >= _v.toInt } + /** Tests whether the major version of the platform specification is at least the given value. + * + * @param version a major version number + */ + def isJavaAtLeast(version: Int): Boolean = isJavaAtLeast(version.toString) + // provide a main method so version info can be obtained by running this def main(args: Array[String]) { val writer = new PrintWriter(Console.err, true) |