aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java1
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala14
-rw-r--r--compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala14
4 files changed, 33 insertions, 3 deletions
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
index c14108d2e..f9187c5fe 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -1607,6 +1607,7 @@ object Parsers {
* LocalModifier ::= abstract | final | sealed | implicit | lazy
*/
def modifiers(allowed: BitSet = modifierTokens, start: Modifiers = Modifiers()): Modifiers = {
+ @tailrec
def loop(mods: Modifiers): Modifiers = {
if (allowed contains in.token) {
val isAccessMod = accessModifierTokens contains in.token
@@ -2057,7 +2058,7 @@ object Parsers {
val name = ident().toTypeName
val constr = atPos(in.lastOffset) {
val tparams = typeParamClauseOpt(ParamOwner.Class)
- val cmods = constrModsOpt()
+ val cmods = constrModsOpt(name)
val vparamss = paramClauses(name, mods is Case)
makeConstructor(tparams, vparamss).withMods(cmods)
@@ -2070,11 +2071,11 @@ object Parsers {
/** ConstrMods ::= AccessModifier
* | Annotation {Annotation} (AccessModifier | `this')
*/
- def constrModsOpt(): Modifiers = {
+ def constrModsOpt(owner: Name): Modifiers = {
val mods = modifiers(accessModifierTokens, annotsAsMods())
if (mods.hasAnnotations && !mods.hasFlags)
if (in.token == THIS) in.nextToken()
- else syntaxError("`private', `protected', or `this' expected")
+ else syntaxError(AnnotatedPrimaryConstructorRequiresModifierOrThis(owner))
mods
}
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
index 2bf15cb7c..bbd93eb30 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
@@ -51,6 +51,7 @@ public enum ErrorMessageID {
ExpectedTokenButFoundID,
MixedLeftAndRightAssociativeOpsID,
CantInstantiateAbstractClassOrTraitID,
+ AnnotatedPrimaryConstructorRequiresModifierOrThisID,
;
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 34190c114..e367e9ab2 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
@@ -1146,4 +1146,18 @@ object messages {
|""".stripMargin
}
+ case class AnnotatedPrimaryConstructorRequiresModifierOrThis(cls: Name)(implicit ctx: Context)
+ extends Message(AnnotatedPrimaryConstructorRequiresModifierOrThisID) {
+ val kind = "Syntax"
+ val msg = hl"""${"private"}, ${"protected"}, or ${"this"} expected for annotated primary constructor"""
+ val explanation =
+ hl"""|When using annotations with a primary constructor of a class,
+ |the annotation must be followed by an access modifier
+ |(${"private"} or ${"protected"}) or ${"this"}.
+ |
+ |For example:
+ | ${"class Sample @deprecated this(param: Parameter) { ..."}
+ | ^^^^
+ |""".stripMargin
+ }
}
diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
index 971a40a1b..d6e687a1e 100644
--- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
+++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
@@ -198,4 +198,18 @@ class ErrorMessagesTests extends ErrorMessagesTest {
assertTrue("expected trait", isTrait)
}
+ @Test def constructorModifier =
+ checkMessagesAfter("frontend") {
+ """
+ |class AnotherClass @deprecated ()
+ """.stripMargin
+ }
+ .expect { (ictx, messages) =>
+ implicit val ctx: Context = ictx
+ val defn = ictx.definitions
+
+ assertMessageCount(1, messages)
+ val AnnotatedPrimaryConstructorRequiresModifierOrThis(cls) :: Nil = messages
+ assertEquals("AnotherClass", cls.show)
+ }
}