diff --git a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala index 123a54c631..7e49ccb3c6 100644 --- a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala +++ b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala @@ -456,9 +456,11 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { @inline def acceptIfStatSep(): Boolean = acceptIf(StatSep) + @inline + def isImplicitStatSep(): Boolean = prev[Indentation.Outdent] + def acceptStatSep(): Boolean = { - val ok = acceptIfStatSep() || isAtEndMarker() || - prev[Indentation.Outdent] && !at[Indentation.Outdent] + val ok = acceptIfStatSep() || isAtEndMarker() || isImplicitStatSep() && !at[Indentation.Outdent] if (!ok) syntaxErrorExpected[Semicolon] ok } @@ -2463,10 +2465,14 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { private def enumeratorGuardOnIf() = autoPos(Enumerator.Guard(guardOnIf())) def enumerators(): List[Enumerator] = listBy[Enumerator] { enums => + def notEnumsEnd(token: Token): Boolean = !token.isAny[Indentation.Outdent, KwDo, CloseDelim] doWhile { enums += enumerator(isFirst = enums.isEmpty) while (at[Token.KwIf]) enums += enumeratorGuardOnIf() - }(StatSep(currToken) && nextIf(!peekToken.isAny[Indentation.Outdent, KwDo, CloseDelim])) + } { + if (StatSep(currToken)) nextIf(notEnumsEnd(peekToken)) + else isImplicitStatSep() && notEnumsEnd(currToken) + } } private def enumerator(isFirst: Boolean = false): Enumerator = currToken match { diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/ControlSyntaxSuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/ControlSyntaxSuite.scala index f907b0f7dc..fbda8d4760 100644 --- a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/ControlSyntaxSuite.scala +++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/ControlSyntaxSuite.scala @@ -4108,4 +4108,39 @@ class ControlSyntaxSuite extends BaseDottySuite { runTestAssert[Stat](code, layout)(tree) } + test("indent in enumerator") { + val code = """|object a: + | val abstractTypeNames = + | for ( + | parent <- + | parents; + | mbr <- parent.abstractTypeMembers if qualifies(mbr.symbol)) + | yield mbr.name.asTypeName + |""".stripMargin + val layout = + "object a { val abstractTypeNames = for (parent <- parents; mbr <- parent.abstractTypeMembers; if qualifies(mbr.symbol)) yield mbr.name.asTypeName }" + val tree = Defn.Object( + Nil, + tname("a"), + tpl(Defn.Val( + Nil, + List(Pat.Var(tname("abstractTypeNames"))), + None, + Term.ForYield( + List( + Enumerator.Generator(Pat.Var(tname("parent")), tname("parents")), + Enumerator.Generator( + Pat.Var(tname("mbr")), + Term.Select(tname("parent"), tname("abstractTypeMembers")) + ), + Enumerator + .Guard(Term.Apply(tname("qualifies"), List(Term.Select(tname("mbr"), tname("symbol"))))) + ), + Term.Select(Term.Select(tname("mbr"), tname("name")), tname("asTypeName")) + ) + )) + ) + runTestAssert[Stat](code, layout)(tree) + } + }