Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TreeSyntax: fix half-empty Self #3144

Merged
merged 3 commits into from
May 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4108,7 +4108,7 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser =>
if (isAfterOptNewLine[LeftBrace]) {
// @S: pre template body cannot stub like post body can!
val (self, body) = templateBody(enumCaseAllowed)
if (token.is[KwWith] && self.name.is[Name.Anonymous] && self.decltpe.isEmpty) {
if (token.is[KwWith] && self.isEmpty) {
val edefs = body.map(ensureEarlyDef)
next()
val parents = templateParents(afterExtend)
Expand Down
5 changes: 4 additions & 1 deletion scalameta/trees/shared/src/main/scala/scala/meta/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ object Pat {

@branch trait Member extends Tree {
def name: Name
final def isNameAnonymous: Boolean = name.is[Name.Anonymous]
}
object Member {
@branch trait Term extends Member {
Expand Down Expand Up @@ -837,7 +838,9 @@ object Ctor {
@replacedField("4.6.0") final def argss: List[List[Term]] = argClauses.map(_.values).toList
}

@ast class Self(name: Name, decltpe: Option[Type]) extends Member with Tree.WithDeclTpeOpt
@ast class Self(name: Name, decltpe: Option[Type]) extends Member with Tree.WithDeclTpeOpt {
final def isEmpty: Boolean = isNameAnonymous && decltpe.isEmpty
}

@ast class Template(
early: List[Stat],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -518,10 +518,8 @@ object TreeSyntax {
case t: Term.New => m(SimpleExpr, s(kw("new"), " ", t.init))
case t: Term.EndMarker => s(kw("end"), " ", t.name.value)
case t: Term.NewAnonymous =>
val needsExplicitBraces = {
val selfIsEmpty = t.templ.self.name.is[Name.Anonymous] && t.templ.self.decltpe.isEmpty
t.templ.early.isEmpty && t.templ.inits.length < 2 && selfIsEmpty && t.templ.stats.isEmpty
}
val needsExplicitBraces = t.templ.early.isEmpty && t.templ.inits.lengthCompare(2) < 0 &&
t.templ.self.isEmpty && t.templ.stats.isEmpty
m(SimpleExpr, s(kw("new"), " ", t.templ), w(" {", "", "}", needsExplicitBraces))
case _: Term.Placeholder => m(SimpleExpr1, kw("_"))
case t: Term.Eta => m(PostfixExpr, s(p(SimpleExpr1, t.expr), " ", kw("_")))
Expand Down Expand Up @@ -912,11 +910,13 @@ object TreeSyntax {
)

// Self
case t: Self => s(t.name, t.decltpe)
case t: Self =>
if (t.isNameAnonymous && t.decltpe.nonEmpty) s("_", t.decltpe)
else s(t.name, t.decltpe)

// Template
case t: Template =>
val isSelfEmpty = t.self.name.is[Name.Anonymous] && t.self.decltpe.isEmpty
val isSelfEmpty = t.self.isEmpty
val useExtends = (t.inits.nonEmpty || t.early.nonEmpty) &&
t.parent.exists(p => p.isNot[Defn.Given] && p.isNot[Term.NewAnonymous])
val extendsKeyword = if (useExtends) "extends" else ""
Expand Down Expand Up @@ -1061,7 +1061,7 @@ object TreeSyntax {
private def isUsingOrImplicit(m: Mod): Boolean = m.is[Mod.ParamsType]
private def printParam(t: Term.Param, keepImplicit: Boolean = false): Show.Result = {
val mods = if (keepImplicit) t.mods else t.mods.filterNot(isUsingOrImplicit)
val nameType = if (t.name.is[Name.Anonymous]) {
val nameType = if (t.isNameAnonymous) {
o(t.decltpe)
} else {
s(t.name, t.decltpe)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@ class ParseSuite extends TreeSuiteBase with CommonTrees {
code: String,
f: ScalametaParser => T,
syntax: String = null
)(tree: Tree)(implicit loc: munit.Location): Unit =
)(tree: Tree)(implicit loc: munit.Location, dialect: Dialect): Unit =
checkTree(parseRule(code, f), syntax)(tree)

protected def checkStat(code: String, syntax: String = null)(tree: Tree)(
implicit loc: munit.Location
): Unit =
protected def checkStat(
code: String,
syntax: String = null
)(tree: Tree)(implicit loc: munit.Location, dialect: Dialect): Unit =
checkParsedTree(code, _.entrypointStat(), syntax)(tree)

protected def runTestError[T <: Tree](
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,4 +382,16 @@ class TemplateSuite extends ParseSuite {
assertNoDiff(err.shortMessage, "class type required but A.type found")
}

test("#3142: template with anonymous self type") {
val code = "class foo { _: Int => }"
val tree = Defn.Class(
Nil,
Type.Name("foo"),
Nil,
Ctor.Primary(Nil, Name(""), Nil),
Template(Nil, Nil, Self(Name(""), Some(Type.Name("Int"))), Nil, Nil)
)
checkStat(code, code)(tree)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class TreeSyntaxSuite extends scala.meta.tests.parsers.ParseSuite {

testBlockAfterDef(k => testBlockAddNL(s"$k foo: Int"))
testBlockNoNL("class foo { self => }")
testBlockNoNL("class foo { _: Int => }")
testBlockNoNL("type foo")
testBlockAfterDef(k => testBlockAddNL(s"$k foo: Int = 1"))
testBlockAfterDef(k => testBlockNoNL(s"$k foo: Int = {1}", s"$k foo: Int = {\n 1\n}"))
Expand Down