Skip to content

Commit

Permalink
REPL summarizes warnings (#7756)
Browse files Browse the repository at this point in the history
REPL summarizes warnings
  • Loading branch information
lrytz committed Feb 3, 2020
2 parents b9513cf + c75af77 commit bc05029
Show file tree
Hide file tree
Showing 12 changed files with 54 additions and 21 deletions.
3 changes: 3 additions & 0 deletions src/compiler/scala/tools/nsc/Reporting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ trait Reporting extends internal.Reporting { self: ast.Positions with Compilatio

def allConditionalWarnings = _allConditionalWarnings flatMap (_.warnings)

// useful in REPL because line parsing doesn't entail a new Run
def clearAllConditionalWarnings() = _allConditionalWarnings.foreach(_.warnings.clear())

// behold! the symbol that caused the deprecation warning (may not be deprecated itself)
def deprecationWarning(pos: Position, sym: Symbol, msg: String, since: String): Unit = _deprecationWarnings.warn(pos, msg, since)
def deprecationWarning(pos: Position, sym: Symbol): Unit = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ class ReplReporterImpl(val config: ShellConfig, val settings: Settings = new Set
withoutTruncating { printMessage(error) }
}


// whether to print anything
var totalSilence: Boolean = false
def suppressOutput[T](operation: => T): T = {
Expand Down
33 changes: 17 additions & 16 deletions src/repl/scala/tools/nsc/interpreter/IMain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ package scala.tools.nsc.interpreter
import java.io.{PrintWriter, StringWriter, Closeable}
import java.net.URL

import scala.language.implicitConversions
import scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
import scala.language.implicitConversions
import scala.reflect.internal.{FatalError, Flags, MissingRequirementError, NoPhase}
import scala.reflect.runtime.{universe => ru}
import scala.reflect.{ClassTag, classTag}
Expand All @@ -31,12 +32,12 @@ import scala.tools.nsc.reporters.StoreReporter
import scala.tools.nsc.typechecker.{StructuredTypeStrings, TypeStrings}
import scala.reflect.internal.util.ScalaClassLoader.URLClassLoader
import scala.tools.util.PathResolver
import scala.util.{Try => Trying}
import scala.tools.nsc.util.{stackTraceString, stringFromWriter}
import scala.tools.nsc.interpreter.Results.{Error, Incomplete, Result, Success}
import scala.tools.nsc.util.Exceptional.rootCause
import scala.util.{Try => Trying}
import scala.util.chaining._
import scala.util.control.NonFatal
import scala.annotation.tailrec


/** An interpreter for Scala code.
Expand Down Expand Up @@ -423,7 +424,6 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
def compileSourcesKeepingRun(sources: SourceFile*) = {
val run = new Run()
assert(run.typerPhase != NoPhase, "REPL requires a typer phase.")
reporter.reset()
run compileSources sources.toList
(!reporter.hasErrors, run)
}
Expand Down Expand Up @@ -487,10 +487,17 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
}
}

compile(line, synthetic, fatally).fold(identity, loadAndRunReq)
compile(line, synthetic, fatally).fold(identity, loadAndRunReq).tap(res =>
// besides regular errors, clear deprecation and feature warnings
// so they don't leak from last compilation run into next provisional parse
if (res != Incomplete) {
reporter.reset()
currentRun.reporting.clearAllConditionalWarnings()
}
)
}

// create a Request and compile it
// create a Request and compile it if input is complete
def compile(line: String, synthetic: Boolean): Either[Result, Request] = compile(line, synthetic, fatally = false)
def compile(line: String, synthetic: Boolean, fatally: Boolean): Either[Result, Request] =
if (global == null) Left(Error)
Expand Down Expand Up @@ -702,7 +709,6 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
val run = new Run()
assert(run.typerPhase != NoPhase, "REPL requires a typer phase.")

reporter.reset()
run.compileUnits(unit :: Nil)
val success = !reporter.hasErrors

Expand Down Expand Up @@ -786,7 +792,6 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
case _ => Nil
}


/** The path of the value that contains the user code. */
def fullAccessPath = s"${lineRep.readPathInstance}$accessPath"

Expand Down Expand Up @@ -914,8 +919,6 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
/** Compile the object file. Returns whether the compilation succeeded.
* If all goes well, the "types" map is computed. */
def compile: Boolean = {
// error counting is wrong, hence interpreter may overlook failure - so we reset
reporter.reset()

// compile the object containing the user's code
lineRep.compile(mkUnit) && {
Expand Down Expand Up @@ -1125,17 +1128,15 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
var isIncomplete = false
val handler = if (fatally) null else (_: Position, _: String) => isIncomplete = true
currentRun.parsing.withIncompleteHandler(handler) {
reporter.reset()
val unit = newCompilationUnit(line, label)
val trees = newUnitParser(unit).parseStats()
if (reporter.hasErrors) Left(Error)
else if (reporter.hasWarnings && settings.fatalWarnings) {
if (!isIncomplete)
currentRun.reporting.summarizeErrors()
Left(Error)
}
if (reporter.hasErrors) Left(Error)
else if (isIncomplete) Left(Incomplete)
else if (reporter.hasWarnings && settings.fatalWarnings) Left(Error)
else Right((trees, unit.firstXmlPos))
}
}.tap(_ => if (!isIncomplete) reporter.reset())
}

/** Does code start with a package definition? */
Expand Down
2 changes: 1 addition & 1 deletion test/files/run/reify_newimpl_23.check
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import scala.tools.reflect.ToolBox
scala> import scala.tools.reflect.Eval
import scala.tools.reflect.Eval

scala> def foo[T]{
scala> def foo[T] = {
val code = reify {
List[T]()
}
Expand Down
2 changes: 1 addition & 1 deletion test/files/run/reify_newimpl_23.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ object Test extends ReplTest {
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox
import scala.tools.reflect.Eval
def foo[T]{
def foo[T] = {
val code = reify {
List[T]()
}
Expand Down
2 changes: 1 addition & 1 deletion test/files/run/reify_newimpl_26.check
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

scala> def foo[T]{
scala> def foo[T] = {
import scala.reflect.runtime.universe._
val tt = implicitly[WeakTypeTag[List[T]]]
println(tt)
Expand Down
2 changes: 1 addition & 1 deletion test/files/run/reify_newimpl_26.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import scala.tools.partest.ReplTest
object Test extends ReplTest {
override def extraSettings = "-Xlog-free-types"
def code = """
def foo[T]{
def foo[T] = {
import scala.reflect.runtime.universe._
val tt = implicitly[WeakTypeTag[List[T]]]
println(tt)
Expand Down
1 change: 1 addition & 0 deletions test/files/run/repl-paste-2.check
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ res10: Int = 12
// Replaying 8 commands from transcript.

scala> 999l
warning: 1 deprecation (since 2.13.0); for details, enable `:setting -deprecation' or `:replay -deprecation'
val res0: Long = 999

scala> val res5 = { 123 }
Expand Down
12 changes: 12 additions & 0 deletions test/files/run/t11402.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

scala> def f = {
val x = 'abc
val x = 'abc
^
On line 2: warning: symbol literal is deprecated; use Symbol("abc") instead
val y = x.toString
y
}
def f: String

scala> :quit
14 changes: 14 additions & 0 deletions test/files/run/t11402.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

import scala.tools.nsc.Settings
import scala.tools.partest.ReplTest
import scala.util.chaining._

object Test extends ReplTest {
override def transformSettings(ss: Settings) = ss.tap(_.deprecation.value = true)
override def code =
"""|def f = {
| val x = 'abc
| val y = x.toString
| y
|}""".stripMargin
}
1 change: 1 addition & 0 deletions test/files/run/t4710.check
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

scala> def method : String = { implicit def f(s: Symbol) = "" ; 'symbol }
warning: 1 deprecation (since 2.13.0); for details, enable `:setting -deprecation' or `:replay -deprecation'
warning: 1 feature warning; for details, enable `:setting -feature' or `:replay -feature'
def method: String

Expand Down
2 changes: 2 additions & 0 deletions test/files/run/t6549.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ scala> case class `X"`(var xxx: Any)
class X$u0022

scala> val m = Map(("": Any) -> `X"`("\""), ('s: Any) -> `X"`("\""))
warning: 1 deprecation (since 2.13.0); for details, enable `:setting -deprecation' or `:replay -deprecation'
val m: scala.collection.immutable.Map[Any,X"] = Map("" -> X"("), 's -> X"("))

scala> m("")
Expand All @@ -18,6 +19,7 @@ scala> m("").xxx = "\""
// mutated m("").xxx

scala> m('s).xxx = 's
warning: 2 deprecations (since 2.13.0); for details, enable `:setting -deprecation' or `:replay -deprecation'
// mutated m(scala.Symbol("s")).xxx

scala> val `"` = 0
Expand Down

0 comments on commit bc05029

Please sign in to comment.