Skip to content

Commit

Permalink
Merge pull request #3891 from kitbellew/sfmt4133_15
Browse files Browse the repository at this point in the history
ScalametaParser: terminate generator on outdent
  • Loading branch information
kitbellew authored Aug 9, 2024
2 parents c4e702e + e9013fa commit 11f8cd5
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

}

0 comments on commit 11f8cd5

Please sign in to comment.