We have a multitude of errors that need to be ported to the new scheme - you'll find these under "Error Messages" below. But first, a tutorial:
Once you've identified an error you want to replace, you should decide what semantic information is needed in the message - i.e. the position, perhaps a tree or some types. For this example we're going to be implementing the error message for the following error:
case class Foo // you're not allowed to have a case class without a single parameter list!
So we create a file with this and compile it using ./bin/dotc test.scala. This gives us the error message:
case class Foo
^
case class needs to have at least one parameter list
So now we search the repository for "case class needs to have" - I do this with git grep -n "case class needs to have".
And now we find that in src/dotty/tools/dotc/ast/Desugar.scala we have the following line:
ctx.error("case class needs to have at least one parameter list", cdef.pos)
Cool - now we know what to replace. So next step is to add a case class to src/dotty/tools/dotc/reporting/diagnostic/messages.scala. The case class that we add should extend Message:
abstract class Message(val errorId: Int) {
/** The `msg` contains the diagnostic message e.g:
*
* > expected: String
* > found: Int
*
* This message wil be placed underneath the position given by the enclosing
* `MessageContainer`
*/
def msg: String
/** The kind of the error message is something like "Syntax" or "Type
* Mismatch"
*/
def kind: String
/** The explanation should provide a detailed description of why the error
* occurred and use examples from the user's own code to illustrate how to
* avoid these errors.
*/
def explanation: String
...
}
Now we name our case class something useful and give it a unique errorId:
case class CaseClassMissingParamList() extends Message(4)
Since we can see that the call to ctx.error took the position of a cdef: TypeDef, we could perhaps use this in the constructor of our Message?
case class CaseClassMissingParamList(cdef: untpd.TypeDef) extends Message(4)
It might also be that we're going to be manipulating cdef tree, as such we should pass a Context to get all the implicit operations:
case class CaseClassMissingParamList(cdef: untpd.TypeDef)(implicit ctx: Context)
extends Message(4)
Alright! Now we can start adding things to our Messsage:
case class CaseClassMissingParamList(cdef: untpd.TypeDef)(implicit ctx: Context)
extends Message(4) {
val kind = "Syntax" // this will be shown as a delimiter: "-- [E004] Syntax X -------"
// we can use the "hl" interpolator to give syntax highlighting to our message:
val msg =
hl"""|A ${"case class"} must have at least one parameter list"""
// not everything that is interpolated will be highlighted, for instance you can use
// colors like: Red("must") - this will get the red color.
val explanation =
hl"""|${cdef.name} ${Red("must")} have at least one parameter list, if you would rather
|have a singleton representation of ${cdef.name}, use a "${"case object"}".
|Or, add an explicit `()' as a parameter list to ${cdef.name}.""".stripMargin
}
So far, we've simplified the above cases a smidge, the error messages themselves actually don't extend Message by passing an integer. They should actually create an entry into the java enum defined in ErrorMessageID.java. This will enable us to have stable identifiers which helps tooling between the different compilers.
Now you replace the call to ctx.error(String) with ctx.error(CaseClassMissingParamList(cdef)) - and you're done with the implementation!
To test your solution, add a test to ErrorMessagesTests.scala. An example for TypeMismatch is provided and documented.
We really want to have online documentation providing more detailed information on what went wrong. Currently the idea is to create markdown pages in the docs/docs folder. Any contribution here would be greatly appreciated!
Types, Position, Treeval explanation = ""Please comment below saying which messages you'd like to tackle.
This is an _awesome_ way of empowering people to contribute to the project. I think I'll use this to contribute. Thanks a lot for writing this up @felixmulder!
To avoid duplicated work: I'm taking on Parsers.scala:403 (shall we just edit the issue description and put names behind the specific messages to keep it transparent for everyone?)
@markusthoemmes: yes! Done :) Added a clarification to the top :)
👍
Indeed, this is an awesome way to get people to contribute to the project ... I'm tackling Parsers.scala:2064
I'll take Desugar.scala and ErrorReporting.scala.
@felixmulder: I created a PR for Parsers.scala: 2064 :-)
Hi, I'm new here. I'll take Parsers.scala:1737, Parsers.scala:1738, Parsers.scala:1739, Parsers.scala:1901
Taking Parsers:1492, Parsers:1329, Parsers: 626 and TypeAssigner.scala:449
Was just sitting down with @ShaneDelmore and looking at these a little bit. Looks like quite a few Parsers and TypeAssigner messages left, if there are one or two 'easier' messages in there that I can take a look at, would someone mind assigning those to me?
Andrew
Hi, Working on Parsers.scala:1180.
@AndrewZurn - how about Parsers.scala:695 to start off with? I'll assign you, but if you don't want it let me know :)
@felixmulder can you mark Parsers:626 and Parsers:1492 as complete :-) ?
@sebastianharko - yes done! Thanks
Hi, also new over here, just trying to help this lovely project... I will work for now on Comments.scala:128, JavaParsers.scala:233 and Parsers.scala:319 ok?
@thiagoandrade6 - sounds great :)
I'd like to work on TypeAssigner.scala:447.
@felixmulder how about Parsers:1079 and Parsers:1082?
working on Parsers.scala:1620
@felixmulder Is there any chance for a Scala newbie to contribute to this issue? Maybe there are some easier error messages? 😃
@maseev - I think it's a perfect opportunity, you'll get to dissect an error and learn the reason as to why it is an error in the first place. Some things are non-obvious to beginners, and I think if you understand the explanation, then somebody with the same skill-level can too.
I would clone the repo and have a look at the ones available from Parsers.scala, they should be the most straight forward. Let us know if you need help on gitter.
That being said, you should probably have some general programming knowledge :)
@felixmulder Got it! I'll definitely have a look.
working on CollectEntryPoints.scala:69
Working on Parsers.scala:307
I got started with Parsers.scala:307!
BTW: shouldn't the kind be an ADT rather than a string?
@Blaisorblade: in the end, that may be best - it was kept as a string so that it is easy to customize for contributors without having to think about "can I add this?" or "should I just use the CC that doesn't really fit my error?"
@Blaisorblade take a look on my PR, it's about the same issue. Your contribution is welcome :)
@felixmulder I'll take this one - Parsers.scala:602, if you don't mind. Looks pretty straightforward.
BTW: shouldn't the kind be an ADT rather than a string?
I was thinking that we could have traits SyntaxMessage,TypeMessage, etc that define val kind: String, then the semantic information is embedded in the class hierarchy
Right now it seems the kind is also indicated by picking the error-reporting method (syntaxError or others). Something similar happens for positions:
You're creating a semantic object - this object will either be the output of the terminal or it could be used in an IDE, so make sure to include the relevant things. Typically: Types, Position, Tree
I've just noticed this and thought back to IdentifierExpected and AuxConstructorNeedsNonImplicitParameter — they include none of those things. Same for #1645 and for my take on it in
https://github.com/lampepfl/dotty/compare/master...Blaisorblade:topic/1645-parser-error.
In fact, right now the positions are passed directly to syntaxError, so having them also seem kind of redundant. What about having def position: Position in Message instead?
@Blaisorblade - you're welcome to improve on these messages by passing in whatever you need in order to bring semantic meaning to them.
In fact, right now the positions are passed directly to syntaxError, so having them also seem kind of redundant. What about having
def position: PositioninMessageinstead?
A Message is contained within a MessageContainer which carries the position. The reporters consume MessageContainers. These containers have a level - Warning, Error, Info etc. How this happens:
syntaxError calls ctx.error which in turn is implemented in trait Reporting, this creates the MessageContainer appropriate to what has been reported. I.e. if a Message is reported as a warning, it will be turned into a Warning container. These containers are then consumed by ConsoleReporter which prints kind, followed by the level represented as a string.
I will take Parsers.scala:2110 and 2112.
I started working on Parsers.scala:533 but noticed that the issue could also be addressed by refactoring the call to syntaxError away. Would that be a viable option for you?
@b-studios: if you want you can replace line 533 with something like
if (!thisOK && in.token != DOT) ctx.error("`.' expected", source atPost Position(in.offset))
But we want to keep the method syntaxError for a while so that it can be used as a convenience function.
@felixmulder: Just to clarify, I suggested to factor the call to syntaxError away, not the method syntaxError itself. In particular, the same syntax error would eventually be raised by accept(DOT) in someDotSelectors.
@Blaisorblade - you're welcome to improve on these messages by passing in whatever you need in order to bring semantic meaning to them.
Thanks for the explanation—those errors might then be fine; in my branch, I now point out in Message ScalaDocs that the position is part of MessageContainer, not semantic information.
@b-studios: yes - exactly, I was just making sure you don't do unnecessary work :)
I'll take these ones - Parsers.scala:1425, Parsers.scala:1437.
BTW, @felixmulder we can mark Parsers.scala:602 as done, because the error message implementation has already been merged into upstream, right?
@felixmulder I am working on MarkupParsers.scala:324 and 326
@felixmulder I was going to take a look at the following, however:
@rethab:
Context bounds are syntactic sugar, e.g:
def foo[T: Ordering](t: T) = ???
// desugars into:
def foo[T](t: T)(implicit ord: Ordering[T]) = ???
So we're actually recommending the same thing I guess...
Regarding @inline: in scalac (or nsc) the inline is heuristics defined, in Dotty it's mandatory. I.e. whatever you define as inline in Dotty, will be inlined. This means that calling super in a method declared inline and compiling it with scalac will probably not inline it - but we have to. The call site for the inline method probably does not have the same super and therefore it would lead to weird behavior unless we add a forwarder to the correct super etc.
@felixmulder I think we can mark Parsers.scala:1437 as implemented 'cause PR was successfully merged.
@felixmulder, I'll start working on Parsers.scala:664
@felixmulder looking at TypeAssigner.scala:298
@felixmulder working on Parsers.scala:712 (which is now 733)
@felixmulder Just to keep the list in sync, 533 now is merged and can be crossed out :)
Is there a good way to include a test case triggering the expected compilation error?
@ennru:
The easiest way currently is to create a check file in the repl tests dir, e.g: ./tests/repl/mytest.check
and then run dotty-compiler/testOnly dotc.tests -- *repl_all.
I'd love to have a custom Reporter that instead collected the errors in their case class form so that we could simply match on it in a unit test. In fact, here's an issue detailing the necessary steps for that: https://github.com/lampepfl/dotty/issues/1965
Update: functionality for this has been merged: #1966. I'll update the main post.
Can -explain be enabled per file during dotty-compiler/testOnly dotc.tests -- *repl_all ?
@ennru: it could be changed, but IMHO we should move away from testing error messages using the repl tests, instead - expose elements of the error message that you need to be able to test.
The idea is to provide semantic objects, so if a TypeMismatch message contains the expected type - it should expose it so that tooling can take that into account.
TypeAssigner.scala:298 was fixed in https://github.com/lampepfl/dotty/commit/d0621108bad55f9fc66c1c5ade9a0b7edb3117e7
I think the line numbers in the description might have drifted a bit. If no one is already working on I'll grab (Parsers.scala:2385) ☺️
only `case class` or `case object` allowed
expected class or object definition
@insdami: looks like it's still there, go ahead! :)
I think the line numbers are outdated, especially the ones defined for files where multiple PRs are being merged. Every time a PR is merged the line number changes... Despite this, I can take Typer.scala:453 which I think refers to the error reported here? https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/Typer.scala#L482
I also have identified this one, that I guess I know how to tackle it. https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/Typer.scala#L770
@gvolpe - they are indeed a bit outdated, I'll update them on Monday!
I'm assigning you to the correct ones in the list :tada:
Hi, @felixmulder can I take the PostTyper.scala:182?
Hi, @felixmulder can I take the Parsers.scala:1685 ?
Here's my take for Typer#482, https://github.com/lampepfl/dotty/pull/2779, sorry for the delay!
Hello, can I take Typer.scala:693?
Taking Typer.scala:775 (which is actually Typer.scala:801) "wrong number of parameters" error.
Can I take Parsers.scala:1709?
Which rather seems to be Parsers.scala:1703:
syntaxError("duplicate private/protected qualifier")
EDIT:
I shamelessly went ahead and did a PR:
https://github.com/lampepfl/dotty/pull/2897
Took Parsers.scala:2177 which was missing from this error index, or is out of sync.
Here's the PR:
https://github.com/lampepfl/dotty/pull/2919
Thanks!
I did a simple semantic search in Intellij and got following list of errors that need updating.
Valid for commit 0ec7e56ffc55c8127127a8a193e6824935d82afc:
Parsers.scala:2150
Parsers.scala:2257
Parsers.scala:2429
Parsers.scala:2447
Parsers.scala:2491
Scala2Unpickler.scala:681
SymDenotations.scala:1924
TypeAssigner.scala:35
TypeAssigner.scala:196
TypeAssigner.scala:223
TypeAssigner.scala:287
TypeAssigner.scala:300
TypeAssigner.scala:302
TypeAssigner.scala:339
TypeAssigner.scala:341
TypeAssigner.scala:357
TypeAssigner.scala:359
TypeAssigner.scala:399
TypeAssigner.scala:433
TypeAssigner.scala:548
Typer.scala:393
Typer.scala:862
Typer.scala:985
Typer.scala:990
Typer.scala:992
Typer.scala:1107
Typer.scala:1427
Typer.scala:1521
Typer.scala:1555
Typer.scala:1574
Typer.scala:1898 (def missingArgs)
I'll take Typer:992 (right now, it's Typer:991) if no-one else is on it.
And finished with that one; it's in #3094.
Hi,I know Dotty ships great detailed error message, could we make these error message more international ?
Eg, make them a template and could have native language support.
like
case class Foo
^
case class needs to have at least one parameter list
could be
case class Foo
^
case class 至少需要1个参数列表
@hepin1989 This is an interesting idea, I suggest you open a separate issue with more technical details on how this could be done.
I'll take Scala2Unpickler.scala:681
Hey there! I'll take Parsers.scala:2150
I'll take this one - Typer.scala:1898 (def missingArgs). Looks pretty straightforward to me.
@felixmulder it looks like these ones:
Typer.scala:992
are already implemented.
I'll take this one - Typer.scala:1427 (ctx.error("only static objects can extend scala.Phantom", cdef.pos))
And this one - Typer.scala:1555 (ctx.errorOrMigrationWarning(i"not a function: ${res.tpe}; cannot be followed by _", tree.pos))
I'll take Typer.scala:1427 - ctx.error("only static objects can extend scala.Phantom", cdef.pos)
@hermesespinola It looks like I already implemented this part in this PR. Unfortunately, if I understand correctly, phantom types will be removed from Dotty, so the PR will probably be closed.
Oh, didn't realize, even though it was two comments before. Just saw the comment from Odersky. Thanks for the info.
I'll try Parsers.scala:2500
It looks like these ones:
are already implemented.
Working on RefChecks.scala:609
Thanks for helping out with updating the missing messages. I updated the list according to your reports @maseev 👍
I'll take this one - Checking.scala:551
I think I'll take this one - Namer.scala:880 as well
Working on Namer.scala:872
Hello, I'm taking Applications.scala:95
I'd like to take Applications.scala:972.
What about Applications.scala:951-953:
errorType(
ex"Pattern type $unapplyArgType is neither a subtype nor a supertype of selector type $selType",
tree.pos)
Is that also something that can be fixed in this ticket?
@gosubpl Yes!
Thanks for the update @smarter . Taking Applications.scala:952.
There are a bunch of error messages that have been implemented lately:
Also taking Applications.scala:834 and Applications.scala:942
Taking Typer.scala:1109 which is now Typer.scala:1172.
Working on Checking.scala:526
Working on Applications.scala:95
Took Typer.scala:1519
Working on Checking.scala:555
Do not make error messages for Phantoms.
Some major changes to the phantoms are coming in #3410. Making error messages for phantoms is useless until we merge that PR as they might completely change
@nicolasstucki - are any of the listed available errors phantoms? If so, please mark them as on hold for #3410
I would like to encourage newcomers to look at #3759 rather than this one.
I think people volunteering their free time are going to do what they find to be most fun 😃
The line numbers are out of date. To make it easier for others to find the referenced line even if the file changes, it would be a good idea to copy the lines here so others can ctrl-f to find the line.
I could be wrong here but the error in Docstrings.scala:30 seems to be prevented at Comments.scala:127, which already has a new error message implementation.
I'll do Typer.scala:411. I guess it's the one about stable identifiers: "stable identifier required, but ${tree.show} found".
I am taking up the normal case $cls in ${cls.owner} cannot extend an enum from Checking.scala.
Does the backtick ` have any meaning for the interpolator ? As seen at:
val explanation =
hl"""|${cdef.name} ${Red("must")} have at least one parameter list, if you would rather
|have a singleton representation of ${cdef.name}, use a "${"case object"}".
|Or, add an explicit `()' as a parameter list to ${cdef.name}.""".stripMargin
Does it treat the fragment within as code?
On 20 October 2018 23:20:36 CEST, "João Pedro de Carvalho" notifications@github.com wrote:
Does the backtick ` have any meaning for the interpolator ? As seen at:
val explanation = hl"""|${cdef.name} ${Red("must")} have at least one parameter list, if you would rather |have a singleton representation of ${cdef.name}, use a "${"case object"}". |Or, add an explicit `()' as a parameter list to ${cdef.name}.""".stripMarginDoes it treat the fragment within as code?
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
https://github.com/lampepfl/dotty/issues/1589#issuecomment-431618962
No, the backtick doesn't do anything here
@smarter would be interesting remove the backticks from the messages and exaplanation and replacing where it should be formated as code by the interpolation literal, eg: `()` would become ${"()"} so the interpolator takes care of it? Because I also saw usage of backticks wraping interpolations like:
`${"case e: Exception =>"}`.
At least for me they only add clutter to the output
Sure, that seems like a good idea.
On lundi 29 octobre 2018 19:55:56 CET João Pedro de Carvalho wrote:
@smarter would be interesting remove the backticks from the messages and
exaplanation and replacing where it should be formated as code by the
interpolation literal, eg:`()`would become${"()"}so the
interpolator takes care of it? Because I also saw usage of backticks
wraping interpolations like:`${"case e: Exception =>"}`.At least for me they only add clutter to the output
I would like to take on PatternMatcher.scala:911
Typer.scala:866 should be done here #7385
Working on RefChecks.scala:119
Namer.scala:258 is tackled by #7457
Hi!
Desugar.scala:457 done there #7729
Hi!
Parser:1426, 1428 done there #7848
(and #7729 is fixed also)
Starting from the top I did Checking.scala:~49~ 53 and I've made a PR for it.
The architecture for errors described in this issue proved to be heavy and impractical. The migration process frequently interferes with in-flight PRs and the benefits are marginal. We should find a more light-weight way to represent errors.
Most helpful comment
This is an _awesome_ way of empowering people to contribute to the project. I think I'll use this to contribute. Thanks a lot for writing this up @felixmulder!