From 7c9bd2b258c0c766fbd3bfcc5e7c5662f2f13c59 Mon Sep 17 00:00:00 2001 From: Raphael Bosshard Date: Wed, 27 Sep 2017 18:16:25 +0200 Subject: [PATCH 1/8] part of #1589; error message for DesugarEnums.scala:47 --- .../dotty/tools/dotc/ast/DesugarEnums.scala | 3 ++- .../reporting/diagnostic/ErrorMessageID.java | 1 + .../dotc/reporting/diagnostic/messages.scala | 19 ++++++++++++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 4dc4ec68448b..bbcc758fd39d 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -6,6 +6,7 @@ import core._ import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ import Decorators._ +import dotty.tools.dotc.reporting.diagnostic.messages.EnumCaseDefinitionInNonEnumOwner import collection.mutable.ListBuffer import util.Property import typer.ErrorReporting._ @@ -32,7 +33,7 @@ object DesugarEnums { /** Is enum case `tree` situated in a companion object of an enum class? */ def enumCaseIsLegal(tree: Tree)(implicit ctx: Context): Boolean = ( ctx.owner.is(ModuleClass) && enumClass.derivesFrom(defn.EnumClass) - || { ctx.error(em"case not allowed here, since owner ${ctx.owner} is not an `enum' object", tree.pos) + || { ctx.error(EnumCaseDefinitionInNonEnumOwner(), tree.pos) false } ) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index 37a368b00823..ac8a45405eac 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -101,6 +101,7 @@ public enum ErrorMessageID { ReturnOutsideMethodDefinitionID, UncheckedTypePatternID, ExtendFinalClassID, + EnumCaseDefinitionInNonEnumOwnerID, ; public int errorNumber() { diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 474b07e0415a..9d76ae812ca1 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1748,7 +1748,7 @@ object messages { val explanation = hl"you have to provide either ${"class"}, ${"trait"}, ${"object"}, or ${"enum"} definitions after qualifiers" } - + case class NoReturnFromInline(owner: Symbol)(implicit ctx: Context) extends Message(NoReturnFromInlineID) { val kind = "Syntax" @@ -1778,4 +1778,21 @@ object messages { hl"""A class marked with the ${"final"} keyword cannot be extended""" } + case class EnumCaseDefinitionInNonEnumOwner()(implicit ctx: Context) + extends Message(EnumCaseDefinitionInNonEnumOwnerID) { + val kind = "Syntax" + val msg = em"case not allowed here, since owner ${ctx.owner} is not an `enum' object" + val explanation = { + + hl""" + | ${"case"} is only allowed at this place if the surrounding object is the companion object of an `enum class`. + | If you wanted to create an enumeration, make sure that the corresponding class has the `enum` keyword. + | Otherwise you might have forgotten `class` or `object` after this `enum`. + | + | See http://dotty.epfl.ch/docs/reference/enums/enums.html for more details on enumerations. + """.stripMargin + } + + } + } From 430c3d0bad4dd347968b9ea564492a8a14fc72a9 Mon Sep 17 00:00:00 2001 From: Raphael Bosshard Date: Wed, 27 Sep 2017 18:28:58 +0200 Subject: [PATCH 2/8] fix typo --- .../src/dotty/tools/dotc/reporting/diagnostic/messages.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 9d76ae812ca1..1e0e2c7a1ece 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1786,7 +1786,7 @@ object messages { hl""" | ${"case"} is only allowed at this place if the surrounding object is the companion object of an `enum class`. - | If you wanted to create an enumeration, make sure that the corresponding class has the `enum` keyword. + | If you wanted to create an enumeration make sure that the corresponding class has the `enum` keyword. | Otherwise you might have forgotten `class` or `object` after this `enum`. | | See http://dotty.epfl.ch/docs/reference/enums/enums.html for more details on enumerations. From 746efc31ec81bea675002fa3acc635386e70289d Mon Sep 17 00:00:00 2001 From: Raphael Bosshard Date: Thu, 28 Sep 2017 00:50:27 +0200 Subject: [PATCH 3/8] add test and provide owner on message creation --- .../src/dotty/tools/dotc/ast/DesugarEnums.scala | 2 +- .../tools/dotc/reporting/diagnostic/messages.scala | 5 ++--- .../tools/dotc/reporting/ErrorMessagesTests.scala | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index bbcc758fd39d..de67467eb751 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -33,7 +33,7 @@ object DesugarEnums { /** Is enum case `tree` situated in a companion object of an enum class? */ def enumCaseIsLegal(tree: Tree)(implicit ctx: Context): Boolean = ( ctx.owner.is(ModuleClass) && enumClass.derivesFrom(defn.EnumClass) - || { ctx.error(EnumCaseDefinitionInNonEnumOwner(), tree.pos) + || { ctx.error(EnumCaseDefinitionInNonEnumOwner(ctx.owner), tree.pos) false } ) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 1e0e2c7a1ece..9f4e70fbc872 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1777,11 +1777,10 @@ object messages { val explanation = hl"""A class marked with the ${"final"} keyword cannot be extended""" } - - case class EnumCaseDefinitionInNonEnumOwner()(implicit ctx: Context) + case class EnumCaseDefinitionInNonEnumOwner(owner: Symbol)(implicit ctx: Context) extends Message(EnumCaseDefinitionInNonEnumOwnerID) { val kind = "Syntax" - val msg = em"case not allowed here, since owner ${ctx.owner} is not an `enum' object" + val msg = em"case not allowed here, since owner ${owner} is not an `enum' object" val explanation = { hl""" diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index 2961a5c8c42f..b9846c665dba 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -998,6 +998,7 @@ class ErrorMessagesTests extends ErrorMessagesTest { val ReturnOutsideMethodDefinition(owner) :: Nil = messages assertEquals("object A", owner.show) } + @Test def extendFinalClass = checkMessagesAfter("refchecks") { """final class A | @@ -1010,4 +1011,17 @@ class ErrorMessagesTests extends ErrorMessagesTest { assertEquals(extender.show, "class B") assertEquals(parent.show, "class A") } + + @Test def enumCaseDefinitionInNonEnumOwner = + checkMessagesAfter("frontend") { + """object Qux { + | case Foo + |} + """.stripMargin + }.expect { (ictx, messages) => + implicit val ctx: Context = ictx + assertMessageCount(1, messages) + val EnumCaseDefinitionInNonEnumOwner(owner) :: Nil = messages + assertEquals("object Qux", owner.show) + } } From e5486069c9caa0cc849a176e0d8008d7f7ca2779 Mon Sep 17 00:00:00 2001 From: Raphael Bosshard Date: Fri, 29 Sep 2017 17:10:21 +0200 Subject: [PATCH 4/8] shorten import --- compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index de67467eb751..bd9e24f76dc7 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -6,7 +6,7 @@ import core._ import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ import Decorators._ -import dotty.tools.dotc.reporting.diagnostic.messages.EnumCaseDefinitionInNonEnumOwner +import reporting.diagnostic.messages.EnumCaseDefinitionInNonEnumOwner import collection.mutable.ListBuffer import util.Property import typer.ErrorReporting._ From 8eac58d6b0bf4b6846d66205a8c3c306dc6a8141 Mon Sep 17 00:00:00 2001 From: Raphael Bosshard Date: Fri, 29 Sep 2017 17:10:39 +0200 Subject: [PATCH 5/8] improve wording and make styling consistent --- .../tools/dotc/reporting/diagnostic/messages.scala | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 9f4e70fbc872..5ff56841f7cd 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1780,18 +1780,15 @@ object messages { case class EnumCaseDefinitionInNonEnumOwner(owner: Symbol)(implicit ctx: Context) extends Message(EnumCaseDefinitionInNonEnumOwnerID) { val kind = "Syntax" - val msg = em"case not allowed here, since owner ${owner} is not an `enum' object" + val msg = em"case not allowed here, since owner `${owner}` is not an `${"enum"}` object" val explanation = { hl""" - | ${"case"} is only allowed at this place if the surrounding object is the companion object of an `enum class`. - | If you wanted to create an enumeration make sure that the corresponding class has the `enum` keyword. - | Otherwise you might have forgotten `class` or `object` after this `enum`. + | `${"case"}` is only allowed at this place if the surrounding object is the companion object of an `${"enum"} ${"class"}`. + | If you wanted to create an enumeration make sure that the corresponding class has the `${"enum"}` keyword. + | Otherwise you might have forgotten `${"class"}` or `${"object"}` after this `${"case"}` here. | - | See http://dotty.epfl.ch/docs/reference/enums/enums.html for more details on enumerations. """.stripMargin } - } - } From f429f3aa1ad87f02ffd56e7038daff6202111dfd Mon Sep 17 00:00:00 2001 From: Raphael Bosshard Date: Fri, 29 Sep 2017 17:17:27 +0200 Subject: [PATCH 6/8] remove trailing space --- .../src/dotty/tools/dotc/reporting/diagnostic/messages.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 5ff56841f7cd..f27fbf996f0b 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1748,7 +1748,7 @@ object messages { val explanation = hl"you have to provide either ${"class"}, ${"trait"}, ${"object"}, or ${"enum"} definitions after qualifiers" } - + case class NoReturnFromInline(owner: Symbol)(implicit ctx: Context) extends Message(NoReturnFromInlineID) { val kind = "Syntax" From fe21e42b0f960d327acb987d5a7f5465db4f9e94 Mon Sep 17 00:00:00 2001 From: Raphael Bosshard Date: Wed, 11 Oct 2017 18:13:18 +0200 Subject: [PATCH 7/8] remove whitespace and .stripMargin --- .../dotty/tools/dotc/reporting/diagnostic/messages.scala | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index f27fbf996f0b..9baac32d9f35 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1781,14 +1781,11 @@ object messages { extends Message(EnumCaseDefinitionInNonEnumOwnerID) { val kind = "Syntax" val msg = em"case not allowed here, since owner `${owner}` is not an `${"enum"}` object" - val explanation = { - + val explanation = hl""" | `${"case"}` is only allowed at this place if the surrounding object is the companion object of an `${"enum"} ${"class"}`. | If you wanted to create an enumeration make sure that the corresponding class has the `${"enum"}` keyword. | Otherwise you might have forgotten `${"class"}` or `${"object"}` after this `${"case"}` here. - | - """.stripMargin - } + """ } } From f4e6b5906ffbe670eab2e7776a1bf60761f87e50 Mon Sep 17 00:00:00 2001 From: Raphael Bosshard Date: Wed, 11 Oct 2017 19:04:37 +0200 Subject: [PATCH 8/8] remove backticks and improve wording of explanation --- .../tools/dotc/reporting/diagnostic/messages.scala | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 9baac32d9f35..753bb76a551b 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1780,12 +1780,10 @@ object messages { case class EnumCaseDefinitionInNonEnumOwner(owner: Symbol)(implicit ctx: Context) extends Message(EnumCaseDefinitionInNonEnumOwnerID) { val kind = "Syntax" - val msg = em"case not allowed here, since owner `${owner}` is not an `${"enum"}` object" + val msg = em"case not allowed here, since owner ${owner} is not an ${"enum"} object" val explanation = - hl""" - | `${"case"}` is only allowed at this place if the surrounding object is the companion object of an `${"enum"} ${"class"}`. - | If you wanted to create an enumeration make sure that the corresponding class has the `${"enum"}` keyword. - | Otherwise you might have forgotten `${"class"}` or `${"object"}` after this `${"case"}` here. - """ - } + hl"""${"enum"} cases are only allowed within the companion ${"object"} of an ${"enum class"}. + |If you want to create an ${"enum"} case, make sure the corresponding ${"enum class"} exists + |and has the ${"enum"} keyword.""" + } }