Skip to content

Commit c4985b5

Browse files
committed
Warning if code after an empty template body is indented
Under -noindent, warn id code that follows an empty template is indented more deeply than the template header. Inserting braces automatically would change meaning in this case. Example: ```scala trait A case class B() extends A // error: Line is indented too far to the right case object C extends A // error: Line is indented too far to the right ```
1 parent 59bb86b commit c4985b5

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

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

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,16 @@ object Parsers {
619619
else body()
620620
case _ => body()
621621

622+
/** If indentation is not significant, check that this is not the start of a
623+
* statement that's indented relative to the current region.
624+
*/
625+
def checkNextNotIndented(): Unit = in.currentRegion match
626+
case r: InBraces if in.token == NEWLINE || in.token == NEWLINES =>
627+
val nextIndentWidth = in.indentWidth(in.next.offset)
628+
if r.indentWidth < nextIndentWidth then
629+
warning(i"Line is indented too far to the right, or a `{' is missing", in.next.offset)
630+
case _ =>
631+
622632
/* -------- REWRITES ----------------------------------------------------------- */
623633

624634
/** The last offset where a colon at the end of line would be required if a subsequent { ... }
@@ -3460,22 +3470,27 @@ object Parsers {
34603470

34613471
/** TemplateOpt = [Template]
34623472
*/
3463-
def templateOpt(constr: DefDef): Template = {
3473+
def templateOpt(constr: DefDef): Template =
34643474
possibleTemplateStart()
3465-
if (in.token == EXTENDS || isIdent(nme.derives))
3475+
if in.token == EXTENDS || isIdent(nme.derives) then
34663476
template(constr)
34673477
else
3468-
if (in.isNestedStart) template(constr)
3469-
else Template(constr, Nil, Nil, EmptyValDef, Nil)
3470-
}
3478+
if in.isNestedStart then
3479+
template(constr)
3480+
else
3481+
checkNextNotIndented()
3482+
Template(constr, Nil, Nil, EmptyValDef, Nil)
34713483

34723484
/** TemplateBody ::= [nl] `{' TemplateStatSeq `}'
34733485
*/
3474-
def templateBodyOpt(constr: DefDef, parents: List[Tree], derived: List[Tree]): Template = {
3486+
def templateBodyOpt(constr: DefDef, parents: List[Tree], derived: List[Tree]): Template =
34753487
val (self, stats) =
3476-
if (in.isNestedStart) templateBody() else (EmptyValDef, Nil)
3488+
if in.isNestedStart then
3489+
templateBody()
3490+
else
3491+
checkNextNotIndented()
3492+
(EmptyValDef, Nil)
34773493
Template(constr, parents, derived, self, stats)
3478-
}
34793494

34803495
def templateBody(): (ValDef, List[Tree]) = {
34813496
val r = inDefScopeBraces { templateStatSeq() }

tests/neg-custom-args/indentRight.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ object Test {
1717

1818
}
1919

20+
trait A
21+
case class B() extends A // error: Line is indented too far to the right
22+
case object C extends A // error: Line is indented too far to the right
23+
2024
if (true) // OK
2125
println("hi")
2226
}

0 commit comments

Comments
 (0)