summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-02-21 15:02:43 +0100
committerJason Zaugg <jzaugg@gmail.com>2014-02-21 15:02:43 +0100
commit25f23a443bc6831d1c8d7f6f57212a29e84bbaa5 (patch)
treee281e0034c7c3de89b1969da1791ab91daf66b54 /src/reflect
parentd79fc2cae4e550bf0a3276a3961ed007bdd428e7 (diff)
parent48a706dee8f7df9d1a6267b6b117cf1546915506 (diff)
downloadscala-25f23a443bc6831d1c8d7f6f57212a29e84bbaa5.tar.gz
scala-25f23a443bc6831d1c8d7f6f57212a29e84bbaa5.tar.bz2
scala-25f23a443bc6831d1c8d7f6f57212a29e84bbaa5.zip
Merge pull request #3546 from VladimirNik/typedTreesPrinter-2.11.0
CodePrinter added to Printers 2.11.0
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/api/Printers.scala12
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala184
-rw-r--r--src/reflect/scala/reflect/internal/ReificationSupport.scala8
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala61
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala10
5 files changed, 217 insertions, 58 deletions
diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala
index b262fdce68..92ae6d8b44 100644
--- a/src/reflect/scala/reflect/api/Printers.scala
+++ b/src/reflect/scala/reflect/api/Printers.scala
@@ -209,20 +209,22 @@ trait Printers { self: Universe =>
* Renders the code of the passed tree, so that:
* 1) it can be later compiled by scalac retaining the same meaning,
* 2) it looks pretty.
- * At the moment we have handled #1 for unattributed trees and
- * later on plan to account for typical idiosyncrasies of the typechecker.
+ * #1 is available for unattributed trees and attributed trees
* #2 is more or less okay indentation-wise, but at the moment there's a lot of desugaring
- * left in place, and that's what we also plan to improve in the future.
+ * left in place, and that's what we plan to improve in the future.
+ * printTypes, printIds, printPositions options have the same meaning as for TreePrinter
+ * printRootPkg option is available only for attributed trees.
*
* @group Printers
*/
- def showCode(tree: Tree) = render(tree, newCodePrinter)
+ def showCode(tree: Tree, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printOwners: BooleanFlag = None, printPositions: BooleanFlag = None, printRootPkg: Boolean = false) =
+ render(tree, newCodePrinter(_, tree, printRootPkg), printTypes, printIds, printOwners, printKinds = None, printMirrors = None, printPositions)
/**
* Hook to define what `showCode(...)` means.
* @group Printers
*/
- protected def newCodePrinter(out: PrintWriter): TreePrinter
+ protected def newCodePrinter(out: PrintWriter, tree: Tree, printRootPkg: Boolean): TreePrinter
/** Renders internal structure of a reflection artifact as the
* visualization of a Scala syntax tree.
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index b1d76b6056..680c19e426 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -73,7 +73,14 @@ trait Printers extends api.Printers { self: SymbolTable =>
def indent() = indentMargin += indentStep
def undent() = indentMargin -= indentStep
- def printPosition(tree: Tree) = if (printPositions) print(tree.pos.show)
+ def printPosition(tree: Tree) =
+ if (printPositions) comment(print(tree.pos.show))
+
+ protected def printTypesInfo(tree: Tree) =
+ if (printTypes && tree.isTerm && tree.canHaveAttrs)
+ comment{
+ print("{", if (tree.tpe eq null) "<null>" else tree.tpe.toString, "}")
+ }
def println() = {
out.println()
@@ -124,12 +131,17 @@ trait Printers extends api.Printers { self: SymbolTable =>
print(symName(p, p.name)); printOpt(": ", TypeTree() setType p.tpe)
}
- protected def parenthesize(condition: Boolean = true)(body: => Unit) = {
- if (condition) print("(")
+ protected def parenthesize(condition: Boolean = true, open: String = "(", close: String = ")")(body: => Unit) = {
+ if (condition) print(open)
body
- if (condition) print(")")
+ if (condition) print(close)
}
+ protected val commentsRequired = false
+
+ protected def comment(body: => Unit) =
+ parenthesize(commentsRequired, "/*", "*/")(body)
+
protected def printImplicitInParamsList(vds: List[ValDef]) =
if (vds.nonEmpty) printFlags(vds.head.mods.flags & IMPLICIT, "")
@@ -275,13 +287,20 @@ trait Printers extends api.Printers { self: SymbolTable =>
print("(");
printValueParams
print(" => ", body, ")")
- if (printIds && tree.symbol != null) print("#" + tree.symbol.id)
- if (printOwners && tree.symbol != null) print("@" + tree.symbol.owner.id)
+ if (printIds && tree.symbol != null)
+ comment{
+ print("#" + tree.symbol.id)
+ }
+
+ if (printOwners && tree.symbol != null)
+ comment{
+ print("@" + tree.symbol.owner.id)
+ }
}
- protected def printSuper(tree: Super, resultName: => String) = {
+ protected def printSuper(tree: Super, resultName: => String, checkSymbol: Boolean = true) = {
val Super(This(qual), mix) = tree
- if (qual.nonEmpty || tree.symbol != NoSymbol) print(resultName + ".")
+ if (qual.nonEmpty || (checkSymbol && tree.symbol != NoSymbol)) print(resultName + ".")
print("super")
if (mix.nonEmpty) print(s"[$mix]")
}
@@ -292,6 +311,9 @@ trait Printers extends api.Printers { self: SymbolTable =>
print("this")
}
+ protected def printBlock(stats: List[Tree], expr: Tree) =
+ printColumn(stats ::: List(expr), "{", ";", "}")
+
def printTree(tree: Tree) = {
tree match {
case EmptyTree =>
@@ -351,7 +373,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
currentOwner = currentOwner1
case Block(stats, expr) =>
- printColumn(stats ::: List(expr), "{", ";", "}")
+ printBlock(stats, expr)
case Match(selector, cases) =>
val selectorType1 = selectorType
@@ -498,9 +520,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
case tree =>
xprintTree(this, tree)
}
- if (printTypes && tree.isTerm && tree.canHaveAttrs) {
- print("{", if (tree.tpe eq null) "<null>" else tree.tpe.toString, "}")
- }
+ printTypesInfo(tree)
}
def print(args: Any*): Unit = args foreach {
@@ -514,21 +534,8 @@ trait Printers extends api.Printers { self: SymbolTable =>
}
}
- // it's the printer for trees after parser and before typer phases
- class ParsedTreePrinter(out: PrintWriter) extends TreePrinter(out) {
- override def withTypes = this
- override def withIds = this
- override def withKinds = this
- override def withMirrors = this
- override def withPositions = this
-
- // TODO: add print parameters to typed trees printer
- printTypes = false
- printIds = false
- printKinds = false
- printMirrors = false
- printPositions = false
-
+ // it's the printer for AST-based code generation
+ class CodePrinter(out: PrintWriter, printRootPkg: Boolean) extends TreePrinter(out) {
protected val parentsStack = scala.collection.mutable.Stack[Tree]()
protected def currentTree = if (parentsStack.nonEmpty) Some(parentsStack.top) else None
@@ -558,6 +565,8 @@ trait Printers extends api.Printers { self: SymbolTable =>
qualIsIntLit && name.isOperatorName
}
+ override protected val commentsRequired = true
+
protected def needsParentheses(parent: Tree)(insideIf: Boolean = true, insideMatch: Boolean = true,
insideTry: Boolean = true, insideAnnotated: Boolean = true, insideBlock: Boolean = true, insideLabelDef: Boolean = true) = {
parent match {
@@ -582,10 +591,21 @@ trait Printers extends api.Printers { self: SymbolTable =>
case Select(qual, name) if name.isTermName => s"${resolveSelect(qual)}.${printedName(name)}"
case Select(qual, name) if name.isTypeName => s"${resolveSelect(qual)}#${blankForOperatorName(name)}%${printedName(name)}"
case Ident(name) => printedName(name)
- case _ => showCode(t)
+ case _ => render(t, new CodePrinter(_, printRootPkg))
}
}
+ protected def emptyTree(tree: Tree) = tree match {
+ case EmptyTree | build.SyntacticEmptyTypeTree() => true
+ case _ => false
+ }
+
+ protected def originalTypeTrees(trees: List[Tree]) =
+ trees.filter(!emptyTree(_)) map {
+ case tt: TypeTree => tt.original
+ case tree => tree
+ }
+
val defaultClasses = List(tpnme.AnyRef)
val defaultTraitsForCase = List(tpnme.Product, tpnme.Serializable)
protected def removeDefaultTypesFromList(trees: List[Tree])(classesToRemove: List[Name] = defaultClasses)(traitsToRemove: List[Name]) = {
@@ -602,9 +622,24 @@ trait Printers extends api.Printers { self: SymbolTable =>
removeDefaultTraitsFromList(removeDefaultClassesFromList(trees, classesToRemove), traitsToRemove)
}
- protected def removeDefaultClassesFromList(trees: List[Tree], classesToRemove: List[Name] = defaultClasses) = trees filter {
- case Select(Ident(sc), name) => !(classesToRemove.contains(name) && sc == nme.scala_)
- case _ => true
+ protected def removeDefaultClassesFromList(trees: List[Tree], classesToRemove: List[Name] = defaultClasses) =
+ originalTypeTrees(trees) filter {
+ case Select(Ident(sc), name) => !(classesToRemove.contains(name) && sc == nme.scala_)
+ case _ => true
+ }
+
+ protected def syntheticToRemove(tree: Tree) =
+ tree match {
+ case _: ValDef | _: TypeDef => false // don't remove ValDef and TypeDef
+ case md: MemberDef if md.mods.isSynthetic => true
+ case _ => false
+ }
+
+ override def printOpt(prefix: String, tree: Tree) =
+ if (!emptyTree(tree)) super.printOpt(prefix, tree)
+
+ override def printColumn(ts: List[Tree], start: String, sep: String, end: String) = {
+ super.printColumn(ts.filter(!syntheticToRemove(_)), start, sep, end)
}
def printFlags(mods: Modifiers, primaryCtorParam: Boolean = false): Unit = {
@@ -635,6 +670,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
def printParam(tree: Tree, primaryCtorParam: Boolean): Unit =
tree match {
case vd @ ValDef(mods, name, tp, rhs) =>
+ printPosition(tree)
printAnnotations(vd)
val mutableOrOverride = mods.isOverride || mods.isMutable
val hideCtorMods = mods.isParamAccessor && mods.isPrivateLocal && !mutableOrOverride
@@ -648,6 +684,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
printOpt(": ", tp);
printOpt(" = ", rhs)
case TypeDef(_, name, tparams, rhs) =>
+ printPosition(tree)
print(printedName(name))
printTypeParams(tparams);
print(rhs)
@@ -682,7 +719,17 @@ trait Printers extends api.Printers { self: SymbolTable =>
override def printTree(tree: Tree): Unit = {
parentsStack.push(tree)
+ try {
+ processTreePrinting(tree);
+ printTypesInfo(tree)
+ } finally parentsStack.pop()
+ }
+
+ def processTreePrinting(tree: Tree): Unit = {
tree match {
+ // don't remove synthetic ValDef/TypeDef
+ case _ if syntheticToRemove(tree) =>
+
case cl @ ClassDef(mods, name, tparams, impl) =>
if (mods.isJavaDefined) super.printTree(cl)
printAnnotations(cl)
@@ -733,12 +780,11 @@ trait Printers extends api.Printers { self: SymbolTable =>
printSeq(stats) {
print(_)
} {
- print(";");
+ println()
println()
};
case _ =>
- val separator = scala.util.Properties.lineSeparator
- printPackageDef(pd, separator)
+ printPackageDef(pd, scala.util.Properties.lineSeparator)
}
case md @ ModuleDef(mods, name, impl) =>
@@ -786,7 +832,8 @@ trait Printers extends api.Printers { self: SymbolTable =>
case imp @ Import(expr, _) =>
printImport(imp, resolveSelect(expr))
- case Template(parents, self, body) =>
+ case t @ Template(parents, self, tbody) =>
+ val body = treeInfo.untypecheckedTemplBody(t)
val printedParents =
currentParent map {
case _: CompoundTypeTree => parents
@@ -840,7 +887,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
case dd: DefDef => dd.name != nme.CONSTRUCTOR
case _ => true
}
- val modBody = left ::: right.drop(1)
+ val modBody = (left ::: right.drop(1))
val showBody = !(modBody.isEmpty && (self == noSelfType || self.isEmpty))
if (showBody) {
if (self.name != nme.WILDCARD) {
@@ -855,7 +902,8 @@ trait Printers extends api.Printers { self: SymbolTable =>
printColumn(modBody, "", ";", "}")
}
- case Block(stats, expr) => super.printTree(tree)
+ case bl @ Block(stats, expr) =>
+ printBlock(treeInfo.untypecheckedBlockBody(bl), expr)
case Match(selector, cases) =>
/* Insert braces if match is inner
@@ -900,12 +948,24 @@ trait Printers extends api.Printers { self: SymbolTable =>
printFunction(f)(printValueParams(vparams, inParentheses = printParentheses))
case Typed(expr, tp) =>
+ def printTp = print("(", tp, ")")
+
tp match {
+ case EmptyTree | build.SyntacticEmptyTypeTree() => printTp
+ // case for untypechecked trees
+ case Annotated(annot, arg) if (expr ne null) && (arg ne null) && expr.equalsStructure(arg) => printTp // remove double arg - 5: 5: @unchecked
+ case tt: TypeTree if tt.original.isInstanceOf[Annotated] => printTp
case Function(List(), EmptyTree) => print("(", expr, " _)") //func _
// parentheses required when (a match {}) : Type
case _ => print("((", expr, "): ", tp, ")")
}
+ // print only fun when targs are TypeTrees with empty original
+ case TypeApply(fun, targs) =>
+ if (targs.exists(emptyTree(_))) {
+ print(fun)
+ } else super.printTree(tree)
+
case Apply(fun, vargs) =>
tree match {
// processing methods ending on colons (x \: list)
@@ -918,20 +978,48 @@ trait Printers extends api.Printers { self: SymbolTable =>
case _ => super.printTree(tree)
}
+ case UnApply(fun, args) =>
+ fun match {
+ case treeInfo.Unapplied(body) =>
+ body match {
+ case Select(qual, name) if name == nme.unapply => print(qual)
+ case TypeApply(Select(qual, name), args) if name == nme.unapply || name == nme.unapplySeq =>
+ print(TypeApply(qual, args))
+ case _ => print(body)
+ }
+ case _ => print(fun)
+ }
+ printRow(args, "(", ", ", ")")
+
case st @ Super(This(qual), mix) =>
- printSuper(st, printedName(qual))
+ printSuper(st, printedName(qual), checkSymbol = false)
case th @ This(qual) =>
- printThis(th, printedName(qual))
+ if (tree.hasExistingSymbol && tree.symbol.isPackage) print(tree.symbol.fullName)
+ else printThis(th, printedName(qual))
+
+ // remove this prefix from constructor invocation in typechecked trees: this.this -> this
+ case Select(This(_), name @ nme.CONSTRUCTOR) => print(printedName(name))
case Select(qual: New, name) =>
print(qual)
- case Select(qualifier, name) => {
- val printParentheses = needsParentheses(qualifier)(insideAnnotated = false) || isIntLitWithDecodedOp(qualifier, name)
- if (printParentheses) print("(", resolveSelect(qualifier), ").", printedName(name))
- else print(resolveSelect(qualifier), ".", printedName(name))
- }
+ case Select(qual, name) =>
+ def checkRootPackage(tr: Tree): Boolean =
+ (currentParent match { //check that Select is not for package def name
+ case Some(_: PackageDef) => false
+ case _ => true
+ }) && (tr match { // check that Select contains package
+ case Select(q, _) => checkRootPackage(q)
+ case _: Ident | _: This => val sym = tr.symbol
+ tr.hasExistingSymbol && sym.isPackage && sym.name != nme.ROOTPKG
+ case _ => false
+ })
+
+ if (printRootPkg && checkRootPackage(tree)) print(s"${printedName(nme.ROOTPKG)}.")
+ val printParentheses = needsParentheses(qual)(insideAnnotated = false) || isIntLitWithDecodedOp(qual, name)
+ if (printParentheses) print("(", resolveSelect(qual), ").", printedName(name))
+ else print(resolveSelect(qual), ".", printedName(name))
case id @ Ident(name) =>
if (name.nonEmpty) {
@@ -971,6 +1059,9 @@ trait Printers extends api.Printers { self: SymbolTable =>
case SelectFromTypeTree(qualifier, selector) =>
print("(", qualifier, ")#", blankForOperatorName(selector), printedName(selector))
+ case tt: TypeTree =>
+ if (!emptyTree(tt)) print(tt.original)
+
case AppliedTypeTree(tp, args) =>
// it's possible to have (=> String) => String type but Function1[=> String, String] is not correct
val containsByNameTypeParam = args exists treeInfo.isByNameParamType
@@ -996,7 +1087,6 @@ trait Printers extends api.Printers { self: SymbolTable =>
case tree => super.printTree(tree)
}
- parentsStack.pop()
}
}
@@ -1004,7 +1094,9 @@ trait Printers extends api.Printers { self: SymbolTable =>
def xprintTree(treePrinter: TreePrinter, tree: Tree) =
treePrinter.print(tree.productPrefix+tree.productIterator.mkString("(", ", ", ")"))
- def newCodePrinter(writer: PrintWriter): TreePrinter = new ParsedTreePrinter(writer)
+ def newCodePrinter(writer: PrintWriter, tree: Tree, printRootPkg: Boolean): TreePrinter =
+ new CodePrinter(writer, printRootPkg)
+
def newTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer)
def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream))
def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter))
diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala
index 087d4186be..ea230a215b 100644
--- a/src/reflect/scala/reflect/internal/ReificationSupport.scala
+++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala
@@ -237,7 +237,9 @@ trait ReificationSupport { self: SymbolTable =>
// undo gen.mkTemplate
protected object UnMkTemplate {
def unapply(templ: Template): Option[(List[Tree], ValDef, Modifiers, List[List[ValDef]], List[Tree], List[Tree])] = {
- val Template(parents, selfType, tbody) = templ
+ val Template(parents, selfType, _) = templ
+ val tbody = treeInfo.untypecheckedTemplBody(templ)
+
def result(ctorMods: Modifiers, vparamss: List[List[ValDef]], edefs: List[Tree], body: List[Tree]) =
Some((parents, selfType, ctorMods, vparamss, edefs, body))
def indexOfCtor(trees: List[Tree]) =
@@ -463,8 +465,8 @@ trait ReificationSupport { self: SymbolTable =>
else gen.mkBlock(stats)
def unapply(tree: Tree): Option[List[Tree]] = tree match {
- case self.Block(stats, SyntheticUnit()) => Some(stats)
- case self.Block(stats, expr) => Some(stats :+ expr)
+ case bl @ self.Block(stats, SyntheticUnit()) => Some(treeInfo.untypecheckedBlockBody(bl))
+ case bl @ self.Block(stats, expr) => Some(treeInfo.untypecheckedBlockBody(bl) :+ expr)
case EmptyTree => Some(Nil)
case _ if tree.isTerm => Some(tree :: Nil)
case _ => None
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index b7df2e82cb..7cf749c048 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -405,6 +405,67 @@ abstract class TreeInfo {
case _ => false
}
+ /** Does the tree have a structure similar to typechecked trees? */
+ private[internal] def detectTypecheckedTree(tree: Tree) =
+ tree.hasExistingSymbol || tree.exists {
+ case dd: DefDef => dd.mods.hasAccessorFlag || dd.mods.isSynthetic // for untypechecked trees
+ case md: MemberDef => md.hasExistingSymbol
+ case _ => false
+ }
+
+ /** Recover template body to parsed state */
+ private[internal] def untypecheckedTemplBody(templ: Template) =
+ untypecheckedTreeBody(templ, templ.body)
+
+ /** Recover block body to parsed state */
+ private[internal] def untypecheckedBlockBody(block: Block) =
+ untypecheckedTreeBody(block, block.stats)
+
+ /** Recover tree body to parsed state */
+ private[internal] def untypecheckedTreeBody(tree: Tree, tbody: List[Tree]) = {
+ def filterBody(body: List[Tree]) = body filter {
+ case _: ValDef | _: TypeDef => true
+ // keep valdef or getter for val/var
+ case dd: DefDef if dd.mods.hasAccessorFlag => !nme.isSetterName(dd.name) && !tbody.exists {
+ case vd: ValDef => dd.name == vd.name.dropLocal
+ case _ => false
+ }
+ case md: MemberDef => !md.mods.isSynthetic
+ case tree => true
+ }
+
+ def lazyValDefRhs(body: Tree) =
+ body match {
+ case Block(List(Assign(_, rhs)), _) => rhs
+ case _ => body
+ }
+
+ def recoverBody(body: List[Tree]) = body map {
+ case vd @ ValDef(vmods, vname, _, vrhs) if nme.isLocalName(vname) =>
+ tbody find {
+ case dd: DefDef => dd.name == vname.dropLocal
+ case _ => false
+ } map { dd =>
+ val DefDef(dmods, dname, _, _, _, drhs) = dd
+ // get access flags from DefDef
+ val vdMods = (vmods &~ Flags.AccessFlags) | (dmods & Flags.AccessFlags).flags
+ // for most cases lazy body should be taken from accessor DefDef
+ val vdRhs = if (vmods.isLazy) lazyValDefRhs(drhs) else vrhs
+ copyValDef(vd)(mods = vdMods, name = dname, rhs = vdRhs)
+ } getOrElse (vd)
+ // for abstract and some lazy val/vars
+ case dd @ DefDef(mods, name, _, _, tpt, rhs) if mods.hasAccessorFlag =>
+ // transform getter mods to field
+ val vdMods = (if (!mods.hasStableFlag) mods | Flags.MUTABLE else mods &~ Flags.STABLE) &~ Flags.ACCESSOR
+ ValDef(vdMods, name, tpt, rhs)
+ case tr => tr
+ }
+
+ if (detectTypecheckedTree(tree)) {
+ recoverBody(filterBody(tbody))
+ } else tbody
+ }
+
/** The first constructor definitions in `stats` */
def firstConstructor(stats: List[Tree]): Tree = stats find {
case x: DefDef => nme.isConstructorName(x.name)
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index 7a6862a770..9dc4baee32 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -1685,10 +1685,12 @@ trait Trees extends api.Trees {
// this is necessary to avoid crashes like https://github.com/scalamacros/paradise/issues/1
// when someone tries to c.typecheck a naked MemberDef
- def wrappingIntoTerm(tree: Tree)(op: Tree => Tree): Tree = {
- op(build.SyntacticBlock(tree :: Nil)) match {
- case build.SyntacticBlock(tree :: Nil) => tree
- case tree => tree
+ def wrappingIntoTerm(tree0: Tree)(op: Tree => Tree): Tree = {
+ val neededWrapping = !tree0.isTerm
+ val tree1 = build.SyntacticBlock(tree0 :: Nil)
+ op(tree1) match {
+ case Block(tree2 :: Nil, Literal(Constant(()))) if neededWrapping => tree2
+ case tree2 => tree2
}
}