Skip to content

Commit 618cebb

Browse files
authored
Merge pull request #1521 from felixmulder/topic/better-errormessages
Operation beautify error messages
2 parents 9ef0341 + 550c643 commit 618cebb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1186
-419
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
*.log
44
*.swp
55
*~
6-
*.swp
76

87
# sbt specific
98
dist/*
@@ -29,6 +28,7 @@ classes/
2928
/.worksheet/
3029

3130
# Partest
31+
dotty.jar
3232
tests/partest-generated/
3333
tests/locks/
3434
/test-classes/

bin/dotr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,13 @@ function runMain {
2929
fi
3030
}
3131

32+
first_arg=$1
33+
3234
if [ -z "$1" ]; then
3335
echo "Starting dotty REPL..."
3436
eval "$DOTTY_ROOT/bin/dotc -repl"
37+
elif [[ ${first_arg:0:1} == "-" ]]; then
38+
eval "$DOTTY_ROOT/bin/dotc -repl $@"
3539
else
3640
runMain "$@"
3741
fi

bridge/src/main/scala/xsbt/DelegatingReporter.scala

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package xsbt
66
import dotty.tools._
77
import dotc._
88
import reporting._
9+
import reporting.diagnostic.MessageContainer
10+
import reporting.diagnostic.messages
911
import core.Contexts._
1012

1113
import xsbti.{Maybe, Position}
@@ -16,19 +18,19 @@ final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
1618

1719
override def printSummary(implicit ctx: Context): Unit = delegate.printSummary()
1820

19-
def doReport(d: Diagnostic)(implicit ctx: Context): Unit = {
20-
val severity =
21-
d match {
22-
case _: Reporter.Error => xsbti.Severity.Error
23-
case _: Reporter.Warning => xsbti.Severity.Warn
21+
def doReport(cont: MessageContainer)(implicit ctx: Context): Unit = {
22+
val severity =
23+
cont match {
24+
case _: messages.Error => xsbti.Severity.Error
25+
case _: messages.Warning => xsbti.Severity.Warn
2426
case _ => xsbti.Severity.Info
2527
}
26-
val pos =
27-
if (d.pos.exists) Some(d.pos)
28+
val pos =
29+
if (cont.pos.exists) Some(cont.pos)
2830
else None
2931

30-
val file =
31-
if (d.pos.source.file.exists) Option(d.pos.source.file.file)
32+
val file =
33+
if (cont.pos.source.file.exists) Option(cont.pos.source.file.file)
3234
else None
3335

3436
val offset0 = pos.map(_.point)
@@ -43,16 +45,16 @@ final class DelegatingReporter(delegate: xsbti.Reporter) extends Reporter
4345
def sourcePath: Maybe[String] = maybe(file.map(_.getPath))
4446
}
4547

46-
delegate.log(position, d.message, severity)
48+
delegate.log(position, cont.message, severity)
4749
}
4850

49-
private[this] def maybe[T](opt: Option[T]): Maybe[T] = opt match {
51+
private[this] def maybe[T](opt: Option[T]): Maybe[T] = opt match {
5052
case None => Maybe.nothing[T]
5153
case Some(s) => Maybe.just[T](s)
5254
}
5355
import java.lang.{ Integer => I }
54-
private[this] def maybeInt(opt: Option[Int]): Maybe[I] = opt match {
56+
private[this] def maybeInt(opt: Option[Int]): Maybe[I] = opt match {
5557
case None => Maybe.nothing[I]
5658
case Some(s) => Maybe.just[I](s)
5759
}
58-
}
60+
}

src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Decorators._
99
import language.higherKinds
1010
import collection.mutable.ListBuffer
1111
import util.Property
12+
import reporting.diagnostic.messages._
1213

1314
object desugar {
1415
import untpd._
@@ -71,7 +72,9 @@ object desugar {
7172
val defctx = ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next
7273
var local = defctx.denotNamed(tp.name).suchThat(_ is ParamOrAccessor).symbol
7374
if (local.exists) (defctx.owner.thisType select local).dealias
74-
else throw new Error(s"no matching symbol for ${tp.symbol.showLocated} in ${defctx.owner} / ${defctx.effectiveScope}")
75+
else throw new java.lang.Error(
76+
s"no matching symbol for ${tp.symbol.showLocated} in ${defctx.owner} / ${defctx.effectiveScope}"
77+
)
7578
case _ =>
7679
mapOver(tp)
7780
}
@@ -281,7 +284,7 @@ object desugar {
281284
val constrVparamss =
282285
if (constr1.vparamss.isEmpty) { // ensure parameter list is non-empty
283286
if (isCaseClass)
284-
ctx.error("case class needs to have at least one parameter list", cdef.pos)
287+
ctx.error(CaseClassMissingParamList(cdef), cdef.namePos)
285288
ListOfNil
286289
}
287290
else constr1.vparamss.nestedMap(toDefParam)

src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package dotc
33
package ast
44

55
import core._
6-
import Types._, Names._, Flags._, util.Positions._, Contexts._, Constants._, SymDenotations._, Symbols._
7-
import Denotations._, StdNames._, Comments._
6+
import Types._, Names._, Flags._, util.Positions._, Contexts._, Constants._
7+
import SymDenotations._, Symbols._, Denotations._, StdNames._, Comments._
88
import annotation.tailrec
99
import language.higherKinds
1010
import collection.IndexedSeqOptimized
@@ -308,8 +308,6 @@ object Trees {
308308
if (rawMods.is(Synthetic)) Position(pos.point, pos.point)
309309
else Position(pos.point, pos.point + name.length, pos.point)
310310
else pos
311-
312-
313311
}
314312

315313
/** A ValDef or DefDef tree */

src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class ScalaSettings extends Settings.SettingGroup {
2323
val migration = BooleanSetting("-migration", "Emit warning and location for migration issues from Scala 2.")
2424
val encoding = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding)
2525
val explaintypes = BooleanSetting("-explaintypes", "Explain type errors in more detail.")
26+
val explain = BooleanSetting("-explain", "Explain errors in more detail.")
2627
val feature = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.")
2728
val g = ChoiceSetting("-g", "level", "Set level of generated debugging info.", List("none", "source", "line", "vars", "notailcalls"), "vars")
2829
val help = BooleanSetting("-help", "Print a synopsis of standard options")

src/dotty/tools/dotc/core/Decorators.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ object Decorators {
176176
*/
177177
def ex(args: Any*)(implicit ctx: Context): String =
178178
explained2(implicit ctx => em(args: _*))
179+
180+
/** Formatter that adds syntax highlighting to all interpolated values */
181+
def hl(args: Any*)(implicit ctx: Context): String =
182+
new SyntaxFormatter(sc).assemble(args)
179183
}
180184
}
181185

src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
3636
* Instead we produce an annotated type that marks the prefix as unsafe:
3737
*
3838
* (x: (C @ UnsafeNonvariant)#T)C#T
39-
39+
*
4040
* We also set a global state flag `unsafeNonvariant` to the current run.
4141
* When typing a Select node, typer will check that flag, and if it
4242
* points to the current run will scan the result type of the select for

src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import rewrite.Rewrites.patch
2727
object Parsers {
2828

2929
import ast.untpd._
30+
import reporting.diagnostic.Message
31+
import reporting.diagnostic.messages._
3032

3133
case class OpInfo(operand: Tree, operator: Name, offset: Offset)
3234

@@ -97,7 +99,7 @@ object Parsers {
9799
/** Issue an error at given offset if beyond last error offset
98100
* and update lastErrorOffset.
99101
*/
100-
def syntaxError(msg: String, offset: Int = in.offset): Unit =
102+
def syntaxError(msg: Message, offset: Int = in.offset): Unit =
101103
if (offset > lastErrorOffset) {
102104
syntaxError(msg, Position(offset))
103105
lastErrorOffset = in.offset
@@ -106,7 +108,7 @@ object Parsers {
106108
/** Unconditionally issue an error at given position, without
107109
* updating lastErrorOffset.
108110
*/
109-
def syntaxError(msg: String, pos: Position): Unit =
111+
def syntaxError(msg: Message, pos: Position): Unit =
110112
ctx.error(msg, source atPos pos)
111113

112114
}
@@ -213,20 +215,23 @@ object Parsers {
213215
}
214216
}
215217

216-
def warning(msg: String, offset: Int = in.offset) =
218+
def warning(msg: Message, sourcePos: SourcePosition) =
219+
ctx.warning(msg, sourcePos)
220+
221+
def warning(msg: Message, offset: Int = in.offset) =
217222
ctx.warning(msg, source atPos Position(offset))
218223

219-
def deprecationWarning(msg: String, offset: Int = in.offset) =
224+
def deprecationWarning(msg: Message, offset: Int = in.offset) =
220225
ctx.deprecationWarning(msg, source atPos Position(offset))
221226

222227
/** Issue an error at current offset taht input is incomplete */
223-
def incompleteInputError(msg: String) =
228+
def incompleteInputError(msg: Message) =
224229
ctx.incompleteInputError(msg, source atPos Position(in.offset))
225230

226231
/** If at end of file, issue an incompleteInputError.
227232
* Otherwise issue a syntax error and skip to next safe point.
228233
*/
229-
def syntaxErrorOrIncomplete(msg: String) =
234+
def syntaxErrorOrIncomplete(msg: Message) =
230235
if (in.token == EOF) incompleteInputError(msg)
231236
else {
232237
syntaxError(msg)
@@ -732,7 +737,7 @@ object Parsers {
732737

733738
def withTypeRest(t: Tree): Tree =
734739
if (in.token == WITH) {
735-
deprecationWarning("`with' as a type operator has been deprecated; use `&' instead")
740+
deprecationWarning(DeprecatedWithOperator())
736741
in.nextToken()
737742
AndTypeTree(t, withType())
738743
}
@@ -1004,28 +1009,33 @@ object Parsers {
10041009
DoWhile(body, cond)
10051010
}
10061011
case TRY =>
1012+
val tryOffset = in.offset
10071013
atPos(in.skipToken()) {
10081014
val body = expr()
1009-
val handler =
1015+
val (handler, handlerStart) =
10101016
if (in.token == CATCH) {
1017+
val pos = in.offset
10111018
in.nextToken()
1012-
expr()
1013-
} else EmptyTree
1019+
(expr(), pos)
1020+
} else (EmptyTree, -1)
10141021

10151022
handler match {
1016-
case Block(Nil, EmptyTree) => syntaxError(
1017-
"`catch` block does not contain a valid expression, try adding a case like - `case e: Exception =>` to the block",
1018-
handler.pos
1019-
)
1023+
case Block(Nil, EmptyTree) =>
1024+
assert(handlerStart != -1)
1025+
syntaxError(
1026+
new EmptyCatchBlock(body),
1027+
Position(handlerStart, handler.pos.end)
1028+
)
10201029
case _ =>
10211030
}
10221031

10231032
val finalizer =
10241033
if (in.token == FINALLY) { accept(FINALLY); expr() }
10251034
else {
1026-
if (handler.isEmpty)
1027-
warning("A try without `catch` or `finally` is equivalent to putting its body in a block; no exceptions are handled.")
1028-
1035+
if (handler.isEmpty) warning(
1036+
EmptyCatchAndFinallyBlock(body),
1037+
source atPos Position(tryOffset, body.pos.end)
1038+
)
10291039
EmptyTree
10301040
}
10311041
ParsedTry(body, handler, finalizer)

0 commit comments

Comments
 (0)