diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index 32dac326b93d..957b2b0d35ef 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -119,6 +119,7 @@ public enum ErrorMessageID { CyclicInheritanceID, UnableToExtendSealedClassID, UnableToEmitSwitchID, + MissingCompanionForStaticID, ; 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 eb2947893753..af64f12e38b6 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -2001,4 +2001,11 @@ object messages { |- there are less than three cases""" } } + + case class MissingCompanionForStatic(member: Symbol)(implicit ctx: Context) extends Message(MissingCompanionForStaticID) { + val msg = hl"${member.owner} does not have a companion class" + val kind = "Syntax" + val explanation = + hl"An object that contains ${"@static"} members must have a companion class." + } } diff --git a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala index fca3f09e6ba0..775965f59c1e 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala @@ -11,7 +11,8 @@ import Flags._ import Contexts.Context import Symbols._ import Constants._ -import Denotations._, SymDenotations._ +import Denotations._ +import SymDenotations._ import Decorators.StringInterpolators import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Annotations.ConcreteAnnotation @@ -21,7 +22,7 @@ import Names.Name import NameOps._ import Decorators._ import TypeUtils._ -import reporting.diagnostic.messages.StaticFieldsOnlyAllowedInObjects +import reporting.diagnostic.messages.{MissingCompanionForStatic, StaticFieldsOnlyAllowedInObjects} /** A transformer that check that requirements of Static fields\methods are implemented: * 1. Only objects can have members annotated with `@static` @@ -57,7 +58,7 @@ class CheckStatic extends MiniPhase { def clashes = companion.asClass.membersNamed(defn.name) if (!companion.exists) { - ctx.error("object that contains @static members should have companion class", defn.pos) + ctx.error(MissingCompanionForStatic(defn.symbol), defn.pos) } else if (clashes.exists) { ctx.error("companion classes cannot define members with same name as @static member", defn.pos) } else if (defn.symbol.is(Flags.Mutable) && companion.is(Flags.Trait)) { diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index 6783b0375815..61e114205027 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -1249,4 +1249,17 @@ class ErrorMessagesTests extends ErrorMessagesTest { val CyclicInheritance(symbol, _) :: Nil = messages assertEquals("class A", symbol.show) } + + @Test def missingCompanionForStatic = + checkMessagesAfter("checkStatic") { + """ + |object Foo { + | @annotation.static def bar(): Unit = () + |} + """.stripMargin + }.expect { (itcx, messages) => + implicit val ctx: Context = itcx + val MissingCompanionForStatic(member) = messages.head + assertEquals(member.show, "method bar") + } }