diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/parsing/JavaParsers.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/MarkupParsers.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/Parsers.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/reporting/ErrorMessages.scala | 117 | ||||
-rw-r--r-- | src/dotty/tools/dotc/reporting/Examples.scala | 106 | ||||
-rw-r--r-- | src/dotty/tools/dotc/reporting/Reporter.scala | 18 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 3 |
7 files changed, 135 insertions, 120 deletions
diff --git a/src/dotty/tools/dotc/parsing/JavaParsers.scala b/src/dotty/tools/dotc/parsing/JavaParsers.scala index ed7cf9e3f..90eb90877 100644 --- a/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -30,6 +30,7 @@ import scala.reflect.internal.util.Collections._ object JavaParsers { import ast.untpd._ + import reporting.ErrorMessages.Syntax._ class JavaParser(source: SourceFile)(implicit ctx: Context) extends ParserCommon(source) { diff --git a/src/dotty/tools/dotc/parsing/MarkupParsers.scala b/src/dotty/tools/dotc/parsing/MarkupParsers.scala index f648b9e2c..ea40eb568 100644 --- a/src/dotty/tools/dotc/parsing/MarkupParsers.scala +++ b/src/dotty/tools/dotc/parsing/MarkupParsers.scala @@ -32,6 +32,7 @@ import Utility._ object MarkupParsers { import ast.untpd._ + import reporting.ErrorMessages.Syntax._ case object MissingEndTagControl extends ControlThrowable { override def getMessage = "start tag was here: " diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index e4378d82b..48422650c 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -17,7 +17,7 @@ import ast.Trees._ import Decorators._ import StdNames._ import util.Positions._ -import reporting.ErrorExplanations._ +import reporting.ErrorMessages._ import Constants._ import ScriptParsers._ import Comments._ @@ -28,6 +28,7 @@ import rewrite.Rewrites.patch object Parsers { import ast.untpd._ + import reporting.ErrorMessages.Syntax._ case class OpInfo(operand: Tree, operator: Name, offset: Offset) @@ -98,7 +99,7 @@ object Parsers { /** Issue an error at given offset if beyond last error offset * and update lastErrorOffset. */ - def syntaxError(expl: Explanation, offset: Int = in.offset): Unit = + def syntaxError(expl: ErrorMessage, offset: Int = in.offset): Unit = if (offset > lastErrorOffset) { syntaxError(expl, Position(offset)) lastErrorOffset = in.offset @@ -107,7 +108,7 @@ object Parsers { /** Unconditionally issue an error at given position, without * updating lastErrorOffset. */ - def syntaxError(expl: Explanation, pos: Position): Unit = + def syntaxError(expl: ErrorMessage, pos: Position): Unit = ctx.explainError(expl, source atPos pos) } @@ -214,7 +215,7 @@ object Parsers { } } - def warning(msg: Explanation, offset: Int = in.offset) = + def warning(msg: ErrorMessage, offset: Int = in.offset) = ctx.explainWarning(msg, source atPos Position(offset)) def deprecationWarning(msg: String, offset: Int = in.offset) = diff --git a/src/dotty/tools/dotc/reporting/ErrorMessages.scala b/src/dotty/tools/dotc/reporting/ErrorMessages.scala new file mode 100644 index 000000000..7186ccbe2 --- /dev/null +++ b/src/dotty/tools/dotc/reporting/ErrorMessages.scala @@ -0,0 +1,117 @@ +package dotty.tools +package dotc +package reporting + +import dotc.core._ +import Contexts.Context, Decorators._, Symbols._ +import dotc.printing.SyntaxHighlighting._ +import util.{SourcePosition, NoSourcePosition} + +object ErrorMessages { + import dotc.ast.Trees._ + import dotc.ast.untpd + + implicit class ShouldExplainCtx(val c: Context) extends AnyVal { + def shouldExplain(expl: ErrorMessage): Boolean = { + implicit val ctx = c + expl match { + case _: NoExplanation => false + case expl if ctx.settings.explainerrors.value => true + case _ => false + } + } + } + + trait ErrorMessage { + def kind: String + def msg: String + def explanation: String + } + + case class NoExplanation(msg: String)(implicit val kind: String) extends ErrorMessage { + val explanation = "" + } + + object Syntax { + implicit val kind: String = "Syntax" + implicit def stringToErrorMessage(s: String): ErrorMessage = NoExplanation(s) + + abstract class EmptyCatchOrFinallyBlock(tryBody: untpd.Tree)(implicit ctx: Context, val kind: String) extends ErrorMessage { + val explanation = { + val tryString = tryBody match { + case Block(Nil, untpd.EmptyTree) => "{}" + case _ => tryBody.show + } + + val code1 = + s"""|try $tryString catch { + | case t: Throwable => ??? + |}""".stripMargin + + val code2 = + s"""|try $tryString finally { + | // perform your cleanup here! + |}""".stripMargin + + hl"""|Explanation: + |============ + |A ${"try"} expression should be followed by some mechanism to handle any exceptions + |thrown. Typically a ${"catch"} expression follows the ${"try"} and pattern matches + |on any expected exceptions. For example: + | + |$code1 + | + |It is also possible to follow a ${"try"} immediately by a ${"finally"} - letting the + |exception propagate - but still allowing for some clean up in ${"finally"}: + | + |$code2 + """.stripMargin + } + } + + case class EmptyCatchBlock(tryBody: untpd.Tree)(implicit ctx: Context, override val kind: String) + extends EmptyCatchOrFinallyBlock(tryBody) { + val msg = + hl"""The ${"catch"} block does not contain a valid expression, try adding a case like - `${"case e: Exception =>"}` to the block""" + } + + case class EmptyCatchAndFinallyBlock(tryBody: untpd.Tree)(implicit ctx: Context, override val kind: String) + extends EmptyCatchOrFinallyBlock(tryBody) { + val msg = + hl"""A ${"try"} without ${"catch"} or ${"finally"} is equivalent to putting its body in a block; no exceptions are handled.""" + } + } + + object Type { + implicit val kind: String = "Type" + implicit def stringToErrorMessage(s: String): ErrorMessage = NoExplanation(s) + + case class DuplicateBind(bind: untpd.Bind, tree: untpd.CaseDef)(implicit ctx: Context, val kind: String) extends ErrorMessage { + val msg = + em"duplicate pattern variable: `${bind.name}`" + + val explanation = { + val pat = tree.pat.show + val guard = tree.guard match { + case untpd.EmptyTree => "" + case guard => s"if ${guard.show}" + } + + val body = tree.body match { + case Block(Nil, untpd.EmptyTree) => "" + case body => s" ${body.show}" + } + + val caseDef = s"case $pat$guard => $body" + + hl"""|Explanation + |=========== + |For each ${"case"} bound variable names have to be unique. In: + | + |$caseDef + | + |`${bind.name}` is not unique. Rename one of the binds!""".stripMargin + } + } + } +} diff --git a/src/dotty/tools/dotc/reporting/Examples.scala b/src/dotty/tools/dotc/reporting/Examples.scala deleted file mode 100644 index 652620e29..000000000 --- a/src/dotty/tools/dotc/reporting/Examples.scala +++ /dev/null @@ -1,106 +0,0 @@ -package dotty.tools -package dotc -package reporting - -import dotc.core._ -import Contexts.Context, Decorators._, Symbols._ -import dotc.printing.SyntaxHighlighting._ -import util.{SourcePosition, NoSourcePosition} - -object ErrorExplanations { - import dotc.ast.Trees._ - import dotc.ast.untpd - - implicit def stringToExplanation(s: String) = NoExplanation(s) - - implicit class ShouldExplainCtx(val c: Context) extends AnyVal { - def shouldExplain(expl: Explanation): Boolean = { - implicit val ctx = c - expl match { - case _: NoExplanation => false - case expl if ctx.settings.explainerrors.value => true - case _ => false - } - } - } - - trait Explanation { - def msg: String - def explanation: String - } - - case class NoExplanation(msg: String) extends Explanation { - val explanation = "" - } - - abstract class EmptyCatchOrFinallyBlock(tryBody: untpd.Tree)(implicit ctx: Context) extends Explanation { - val explanation = { - val tryString = tryBody match { - case Block(Nil, untpd.EmptyTree) => "{}" - case _ => tryBody.show - } - - val code1 = - s"""|try $tryString catch { - | case t: Throwable => ??? - |}""".stripMargin - - val code2 = - s"""|try $tryString finally { - | // perform your cleanup here! - |}""".stripMargin - - hl"""|Explanation: - |============ - |A ${"try"} expression should be followed by some mechanism to handle any exceptions - |thrown. Typically a ${"catch"} expression follows the ${"try"} and pattern matches - |on any expected exceptions. For example: - | - |$code1 - | - |It is also possible to follow a ${"try"} immediately by a ${"finally"} - letting the - |exception propagate - but still allowing for some clean up in ${"finally"}: - | - |$code2 - """.stripMargin - } - } - - case class EmptyCatchBlock(tryBody: untpd.Tree)(implicit ctx: Context) extends EmptyCatchOrFinallyBlock(tryBody) { - val msg = - hl"""The ${"catch"} block does not contain a valid expression, try adding a case like - `${"case e: Exception =>"}` to the block""" - } - - case class EmptyCatchAndFinallyBlock(tryBody: untpd.Tree)(implicit ctx: Context) extends EmptyCatchOrFinallyBlock(tryBody) { - val msg = - hl"""A ${"try"} without ${"catch"} or ${"finally"} is equivalent to putting its body in a block; no exceptions are handled.""" - } - - case class DuplicateBind(bind: untpd.Bind, tree: untpd.CaseDef)(implicit ctx: Context) extends Explanation { - val msg = - em"duplicate pattern variable: `${bind.name}`" - - val explanation = { - val pat = tree.pat.show - val guard = tree.guard match { - case untpd.EmptyTree => "" - case guard => s"if ${guard.show}" - } - - val body = tree.body match { - case Block(Nil, untpd.EmptyTree) => "" - case body => s" ${body.show}" - } - - val caseDef = s"case $pat$guard => $body" - - hl"""|Explanation - |=========== - |For each ${"case"} bound variable names have to be unique. In: - | - |$caseDef - | - |`${bind.name}` is not unique. Rename one of the binds!""".stripMargin - } - } -} diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala index eb9a10a59..401938859 100644 --- a/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/src/dotty/tools/dotc/reporting/Reporter.scala @@ -13,7 +13,7 @@ import java.lang.System.currentTimeMillis import core.Mode import interfaces.Diagnostic.{ERROR, WARNING, INFO} import dotty.tools.dotc.core.Symbols.Symbol -import ErrorExplanations._ +import ErrorMessages._ object Reporter { class Error(msgFn: => String, pos: SourcePosition) extends Diagnostic(msgFn, pos, ERROR) @@ -96,10 +96,10 @@ trait Reporting { this: Context => def warning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit = reporter.report(new Warning(msg, pos)) - def explainWarning(expl: => Explanation, pos: SourcePosition = NoSourcePosition): Unit = { - warning(expl.msg, pos) - if (this.shouldExplain(expl)) - reporter.report(new Info(expl.explanation, NoSourcePosition)) + def explainWarning(err: => ErrorMessage, pos: SourcePosition = NoSourcePosition): Unit = { + warning(err.msg, pos) + if (this.shouldExplain(err)) + reporter.report(new Info(err.explanation, NoSourcePosition)) } def strictWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit = @@ -111,10 +111,10 @@ trait Reporting { this: Context => reporter.report(new Error(msg, pos)) } - def explainError(expl: => Explanation, pos: SourcePosition = NoSourcePosition): Unit = { - error(expl.msg, pos) - if (this.shouldExplain(expl)) - reporter.report(new Info(expl.explanation, NoSourcePosition)) + def explainError(err: => ErrorMessage, pos: SourcePosition = NoSourcePosition): Unit = { + error(err.msg, pos) + if (this.shouldExplain(err)) + reporter.report(new Info(err.explanation, NoSourcePosition)) } def errorOrMigrationWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit = diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 19297f9ec..6fddd928b 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -38,7 +38,7 @@ import NavigateAST._ import transform.SymUtils._ import language.implicitConversions import printing.SyntaxHighlighting._ -import reporting.ErrorExplanations._ +import reporting.ErrorMessages._ object Typer { @@ -66,6 +66,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit import tpd.{cpy => _, _} import untpd.cpy import Dynamic.isDynamicMethod + import reporting.ErrorMessages.Type._ /** A temporary data item valid for a single typed ident: * The set of all root import symbols that have been |