Skip to content

Commit

Permalink
Merge pull request #2939 from kitbellew/2939
Browse files Browse the repository at this point in the history
Trees: improve detection of `mod` for ParamClause
  • Loading branch information
kitbellew committed Nov 3, 2022
2 parents 8320767 + 976bdb8 commit ee9eeca
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4464,8 +4464,9 @@ object ScalametaParser {
if (ok) copyPos(t)(Type.AnonymousLambda(t)) else t
}

private def toParamClause(mod: Option[Mod.ParamsType])(v: List[Term.Param]) =
Term.ParamClause(v, mod)
private def toParamClause(mod: Option[Mod.ParamsType]): List[Term.Param] => Term.ParamClause =
if (mod.isDefined) Term.ParamClause(_, mod)
else { v => Term.ParamClause(v, Term.ParamClause.getMod(v)) }

private implicit class ImplicitTree[T <: Tree](private val tree: T) extends AnyVal {

Expand Down
11 changes: 11 additions & 0 deletions scalameta/trees/shared/src/main/scala/scala/meta/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,17 @@ object Term {
extends Member.Param
@ast class ParamClause(values: List[Param], mod: Option[Mod.ParamsType] = None)
extends Member.ParamClause
object ParamClause {
private[meta] def getMod(v: Seq[Param]): Option[Mod.ParamsType] =
v.filter(!_.is[Param.Quasi]) match {
case head :: tail =>
head.mods.collectFirst {
case x: Mod.Using => x
case x: Mod.Implicit if tail.forall(_.mods.exists(_.is[Mod.Implicit])) => x
}
case _ => None
}
}
def fresh(): Term.Name = fresh("fresh")
def fresh(prefix: String): Term.Name = Term.Name(prefix + Fresh.nextId())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,8 @@ object TreeSyntax {
}
m(Expr, param, " ", kw("=>"), " ", p(Expr, body))
case Term.Function(params, body) =>
m(Expr, s(printParams(params), " ", kw("=>"), " ", p(Expr, body)))
val mod = Term.ParamClause.getMod(params)
m(Expr, s(printParams(params, mod), " ", kw("=>"), " ", p(Expr, body)))
}
case Term.QuotedMacroExpr(Term.Block(stats)) =>
stats match {
Expand Down Expand Up @@ -603,7 +604,7 @@ object TreeSyntax {
// NOTE: `implicit/using` in parameters is skipped as it applies to whole list
printParam(t)
case t: Term.ParamClause =>
printParams(t.values, needParens = !t.parent.exists(_.is[Term]))
printParams(t.values, t.mod, needParens = !t.parent.exists(_.is[Term]))

// Type
case t: Type.AnonymousName => m(Path, s(""))
Expand Down Expand Up @@ -1000,7 +1001,7 @@ object TreeSyntax {
case t: Pkg.Object =>
r(" ")(kw("package"), t.mods, kw("object"), t.name, t.templ)
case t: Ctor.Primary =>
val paramClauses = r(t.paramClauses.map(x => printParams(x.values)))
val paramClauses = r(t.paramClauses.map(x => printParams(x.values, x.mod)))
s(w(t.mods, " ", t.mods.nonEmpty && t.paramClauses.nonEmpty), paramClauses)
case t: Ctor.Secondary =>
if (t.stats.isEmpty)
Expand Down Expand Up @@ -1203,13 +1204,13 @@ object TreeSyntax {
implicit def syntaxAnnots: Syntax[Seq[Mod.Annot]] = Syntax { annots =>
r(annots, " ")
}
private def printParams(t: Seq[Term.Param], needParens: Boolean = true): Show.Result = {
private def printParams(
t: Seq[Term.Param],
modOpt: Option[Mod.ParamsType],
needParens: Boolean = true
): Show.Result = {
val (useParens, mod) = t match {
case head +: tail =>
val modOpt = head.mods.collectFirst {
case x: Mod.Using => x
case x: Mod.Implicit if tail.forall(_.mods.exists(_.is[Mod.Implicit])) => x
}
val useParens = needParens || tail.nonEmpty ||
modOpt.fold(head.decltpe.isDefined)(!_.is[Mod.Implicit])
(useParens, o(modOpt, " "))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ private[meta] trait Api {

implicit def termParamClauseToValues(v: Term.ParamClause): List[Term.Param] = v.values
implicit def termValuesToParamClause(v: List[Term.Param]): Term.ParamClause =
Term.ParamClause(v, v.flatMap(_.mods).collectFirst { case x: Mod.ParamsType => x })
Term.ParamClause(v, Term.ParamClause.getMod(v))
implicit def termListValuesToListParamClause(v: List[List[Term.Param]]): List[Term.ParamClause] =
v.map(termValuesToParamClause)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -676,12 +676,42 @@ class SyntacticSuite extends scala.meta.tests.parsers.ParseSuite {
test(
"#1837 class C(private implicit val x: Int, implicit final val y: String, protected implicit var z: Boolean)"
) {
assertEquals(
checkTree(
templStat(
"class C(private implicit val x: Int, implicit final val y: String, protected implicit var z: Boolean)"
).syntax,
),
"class C(implicit private val x: Int, final val y: String, protected var z: Boolean)"
)
) {
Defn.Class(
Nil,
Type.Name("C"),
Type.ParamClause(Nil),
Ctor.Primary(
Nil,
Name(""),
Term.ParamClause(
Term.Param(
List(Mod.Private(Name("")), Mod.Implicit(), Mod.ValParam()),
Term.Name("x"),
Some(Type.Name("Int")),
None
) :: Term.Param(
List(Mod.Implicit(), Mod.Final(), Mod.ValParam()),
Term.Name("y"),
Some(Type.Name("String")),
None
) :: Term.Param(
List(Mod.Protected(Name("")), Mod.Implicit(), Mod.VarParam()),
Term.Name("z"),
Some(Type.Name("Boolean")),
None
) :: Nil,
Some(Mod.Implicit())
) :: Nil
),
Template(Nil, Nil, Self(Name(""), None), Nil, Nil)
)
}
}

test("class C(var x: Int)") {
Expand Down

0 comments on commit ee9eeca

Please sign in to comment.