Skip to content

Commit 83a4f95

Browse files
authored
Merge pull request #2028 from ennru/ennru_AnnotatedPrimaryConstructorRequires
Change 'private, protected, or this expected' to Message
2 parents 783b978 + 8c406e9 commit 83a4f95

File tree

4 files changed

+33
-3
lines changed

4 files changed

+33
-3
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,7 @@ object Parsers {
16071607
* LocalModifier ::= abstract | final | sealed | implicit | lazy
16081608
*/
16091609
def modifiers(allowed: BitSet = modifierTokens, start: Modifiers = Modifiers()): Modifiers = {
1610+
@tailrec
16101611
def loop(mods: Modifiers): Modifiers = {
16111612
if (allowed contains in.token) {
16121613
val isAccessMod = accessModifierTokens contains in.token
@@ -2057,7 +2058,7 @@ object Parsers {
20572058
val name = ident().toTypeName
20582059
val constr = atPos(in.lastOffset) {
20592060
val tparams = typeParamClauseOpt(ParamOwner.Class)
2060-
val cmods = constrModsOpt()
2061+
val cmods = constrModsOpt(name)
20612062
val vparamss = paramClauses(name, mods is Case)
20622063

20632064
makeConstructor(tparams, vparamss).withMods(cmods)
@@ -2070,11 +2071,11 @@ object Parsers {
20702071
/** ConstrMods ::= AccessModifier
20712072
* | Annotation {Annotation} (AccessModifier | `this')
20722073
*/
2073-
def constrModsOpt(): Modifiers = {
2074+
def constrModsOpt(owner: Name): Modifiers = {
20742075
val mods = modifiers(accessModifierTokens, annotsAsMods())
20752076
if (mods.hasAnnotations && !mods.hasFlags)
20762077
if (in.token == THIS) in.nextToken()
2077-
else syntaxError("`private', `protected', or `this' expected")
2078+
else syntaxError(AnnotatedPrimaryConstructorRequiresModifierOrThis(owner), mods.annotations.last.pos)
20782079
mods
20792080
}
20802081

compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public enum ErrorMessageID {
5151
ExpectedTokenButFoundID,
5252
MixedLeftAndRightAssociativeOpsID,
5353
CantInstantiateAbstractClassOrTraitID,
54+
AnnotatedPrimaryConstructorRequiresModifierOrThisID,
5455
;
5556

5657
public int errorNumber() {

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,4 +1146,18 @@ object messages {
11461146
|""".stripMargin
11471147
}
11481148

1149+
case class AnnotatedPrimaryConstructorRequiresModifierOrThis(cls: Name)(implicit ctx: Context)
1150+
extends Message(AnnotatedPrimaryConstructorRequiresModifierOrThisID) {
1151+
val kind = "Syntax"
1152+
val msg = hl"""${"private"}, ${"protected"}, or ${"this"} expected for annotated primary constructor"""
1153+
val explanation =
1154+
hl"""|When using annotations with a primary constructor of a class,
1155+
|the annotation must be followed by an access modifier
1156+
|(${"private"} or ${"protected"}) or ${"this"}.
1157+
|
1158+
|For example:
1159+
| ${"class Sample @deprecated this(param: Parameter) { ..."}
1160+
| ^^^^
1161+
|""".stripMargin
1162+
}
11491163
}

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,18 @@ class ErrorMessagesTests extends ErrorMessagesTest {
198198
assertTrue("expected trait", isTrait)
199199
}
200200

201+
@Test def constructorModifier =
202+
checkMessagesAfter("frontend") {
203+
"""
204+
|class AnotherClass @deprecated ()
205+
""".stripMargin
206+
}
207+
.expect { (ictx, messages) =>
208+
implicit val ctx: Context = ictx
209+
val defn = ictx.definitions
210+
211+
assertMessageCount(1, messages)
212+
val AnnotatedPrimaryConstructorRequiresModifierOrThis(cls) :: Nil = messages
213+
assertEquals("AnotherClass", cls.show)
214+
}
201215
}

0 commit comments

Comments
 (0)