aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/ast/TreeInfo.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/ast/TreeInfo.scala')
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala356
1 files changed, 178 insertions, 178 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index cde8c10b0..de00cee7e 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -7,14 +7,9 @@ import Flags._, Trees._, Types._, Contexts._
import Names._, StdNames._, NameOps._, Decorators._, Symbols._
import util.HashSet
-/** This class ...
- *
- * @author Martin Odersky
- * @version 1.0
- */
-abstract class TreeInfo {
-
- def isDeclarationOrTypeDef(tree: Tree[_ >: Untyped]): Boolean = tree match {
+trait TreeInfo[T >: Untyped] { self: Trees.Instance[T] =>
+
+ def isDeclarationOrTypeDef(tree: Tree): Boolean = tree match {
case DefDef(_, _, _, _, _, EmptyTree)
| ValDef(_, _, _, EmptyTree)
| TypeDef(_, _, _) => true
@@ -23,7 +18,7 @@ abstract class TreeInfo {
/** Is tree legal as a member definition of an interface?
*/
- def isInterfaceMember(tree: Tree[_ >: Untyped]): Boolean = tree match {
+ def isInterfaceMember(tree: Tree): Boolean = tree match {
case EmptyTree => true
case Import(_, _) => true
case TypeDef(_, _, _) => true
@@ -32,71 +27,14 @@ abstract class TreeInfo {
case _ => false
}
- /** Is tree a definition that has no side effects when
- * evaluated as part of a block after the first time?
- */
- def isIdempotentDef(tree: Tree[Type])(implicit ctx: Context): Boolean = tree match {
- case EmptyTree
- | TypeDef(_, _, _)
- | Import(_, _)
- | DefDef(_, _, _, _, _, _) =>
- true
- case ValDef(mods, _, _, rhs) =>
- !(mods is Mutable) && isIdempotentExpr(rhs)
- case _ =>
- false
- }
-
- def isOpAssign(tree: untpd.Tree) = tree match {
+ def isOpAssign(tree: Tree) = tree match {
case Apply(Select(_, name), _ :: Nil) if name.isOpAssignmentName => true
case _ => false
}
- /** Is tree an expression which can be inlined without affecting program semantics?
- *
- * Note that this is not called "isExprPure" since purity (lack of side-effects)
- * is not the litmus test. References to modules and lazy vals are side-effecting,
- * both because side-effecting code may be executed and because the first reference
- * takes a different code path than all to follow; but they are safe to inline
- * because the expression result from evaluating them is always the same.
- */
- def isIdempotentExpr(tree: Tree[Type])(implicit ctx: Context): Boolean = tree match {
- case EmptyTree
- | This(_)
- | Super(_, _)
- | Literal(_) =>
- true
- case Ident(_) =>
- tree.symbol is Stable
- case Select(qual, _) =>
- tree.symbol.isStable && isIdempotentExpr(qual)
- case TypeApply(fn, _) =>
- isIdempotentExpr(fn)
-/*
- * Not sure we'll need that. Comment out until we find out
- case Apply(Select(free @ Ident(_), nme.apply), _) if free.symbol.name endsWith nme.REIFY_FREE_VALUE_SUFFIX =>
- // see a detailed explanation of this trick in `GenSymbols.reifyFreeTerm`
- free.symbol.hasStableFlag && isIdempotentExpr(free)
-*/
- case Apply(fn, Nil) =>
- // Note: After uncurry, field accesses are represented as Apply(getter, Nil),
- // so an Apply can also be pure.
- // However, before typing, applications of nullary functional values are also
- // Apply(function, Nil) trees. To prevent them from being treated as pure,
- // we check that the callee is a method.
- // The callee might also be a Block, which has a null symbol, so we guard against that (SI-7185)
- fn.symbol != null && (fn.symbol is (Method, butNot = Lazy)) && isIdempotentExpr(fn)
- case Typed(expr, _) =>
- isIdempotentExpr(expr)
- case Block(stats, expr) =>
- (stats forall isIdempotentDef) && isIdempotentExpr(expr)
- case _ =>
- false
- }
-
- class MatchingArgs[T >: Untyped](params: List[Symbol], args: List[Tree[T]])(implicit ctx: Context) {
- def foreach(f: (Symbol, Tree[T]) => Unit): Boolean = {
- def recur(params: List[Symbol], args: List[Tree[T]]): Boolean = params match {
+ class MatchingArgs(params: List[Symbol], args: List[Tree])(implicit ctx: Context) {
+ def foreach(f: (Symbol, Tree) => Unit): Boolean = {
+ def recur(params: List[Symbol], args: List[Tree]): Boolean = params match {
case Nil => args.isEmpty
case param :: params1 =>
if (param.info.isRepeatedParam) {
@@ -111,8 +49,8 @@ abstract class TreeInfo {
}
recur(params, args)
}
- def zipped: List[(Symbol, Tree[T])] = map((_, _))
- def map[R](f: (Symbol, Tree[T]) => R): List[R] = {
+ def zipped: List[(Symbol, Tree)] = map((_, _))
+ def map[R](f: (Symbol, Tree) => R): List[R] = {
val b = List.newBuilder[R]
foreach(b += f(_, _))
b.result
@@ -129,7 +67,7 @@ abstract class TreeInfo {
* <init>(x$2, x$1)
* }
*/
- def methPart[T >: Untyped](tree: Tree[T]): Tree[T] = tree match {
+ def methPart(tree: Tree): Tree = tree match {
case Apply(fn, _) => methPart(fn)
case TypeApply(fn, _) => methPart(fn)
case AppliedTypeTree(fn, _) => methPart(fn)
@@ -138,7 +76,7 @@ abstract class TreeInfo {
}
/** The number of arguments in an application */
- def numArgs[T >: Untyped](tree: Tree[T]): Int = tree match {
+ def numArgs(tree: Tree): Int = tree match {
case Apply(fn, args) => numArgs(fn) + args.length
case TypeApply(fn, args) => numArgs(fn) + args.length
case AppliedTypeTree(fn, args) => numArgs(fn) + args.length
@@ -146,120 +84,75 @@ abstract class TreeInfo {
case _ => 0
}
- /** Is symbol potentially a getter of a mutable variable?
- */
- def mayBeVarGetter(sym: Symbol)(implicit ctx: Context): Boolean = {
- def maybeGetterType(tpe: Type): Boolean = tpe match {
- case _: ExprType | _: ImplicitMethodType => true
- case tpe: PolyType => maybeGetterType(tpe.resultType)
- case _ => false
- }
- sym.owner.isClass && !sym.isStable && maybeGetterType(sym.info)
- }
-
- /** Is tree a reference to a mutable variable, or to a potential getter
- * that has a setter in the same class?
- */
- def isVariableOrGetter(tree: Tree[Type])(implicit ctx: Context) = {
- def sym = tree.symbol
- def isVar = sym is Mutable
- def isGetter =
- mayBeVarGetter(sym) && sym.owner.info.member(sym.name.asTermName.getterToSetter).exists
-
- tree match {
- case Ident(_) => isVar
- case Select(_, _) => isVar || isGetter
- case Apply(_, _) =>
- methPart(tree) match {
- case Select(qual, nme.apply) => qual.tpe.member(nme.update).exists
- case _ => false
- }
- case _ => false
- }
- }
-
/** Is tree a self constructor call this(...)? I.e. a call to a constructor of the
* same object?
*/
- def isSelfConstrCall(tree: Tree[_ >: Untyped]): Boolean = methPart(tree) match {
+ def isSelfConstrCall(tree: Tree): Boolean = methPart(tree) match {
case Ident(nme.CONSTRUCTOR) | Select(This(_), nme.CONSTRUCTOR) => true
case _ => false
}
/** Is tree a super constructor call?
*/
- def isSuperConstrCall(tree: Tree[_ >: Untyped]): Boolean = methPart(tree) match {
+ def isSuperConstrCall(tree: Tree): Boolean = methPart(tree) match {
case Select(Super(_, _), nme.CONSTRUCTOR) => true
case _ => false
}
- def isSelfOrSuperConstrCall(tree: Tree[_ >: Untyped]): Boolean = methPart(tree) match {
+ def isSelfOrSuperConstrCall(tree: Tree): Boolean = methPart(tree) match {
case Ident(nme.CONSTRUCTOR)
| Select(This(_), nme.CONSTRUCTOR)
| Select(Super(_, _), nme.CONSTRUCTOR) => true
case _ => false
}
- /** Strips layers of `.asInstanceOf[T]` / `_.$asInstanceOf[T]()` from an expression */
- def stripCast(tree: Tree[Type])(implicit ctx: Context): Tree[Type] = {
- def isCast(sel: Tree[Type]) = defn.asInstanceOfMethods contains sel.symbol
- tree match {
- case TypeApply(sel @ Select(inner, _), _) if isCast(sel) =>
- stripCast(inner)
- case Apply(TypeApply(sel @ Select(inner, _), _), Nil) if isCast(sel) =>
- stripCast(inner)
- case t =>
- t
- }
- }
-
/** Is tree a variable pattern? */
- def isVarPattern[T >: Untyped](pat: Tree[T]): Boolean = pat match {
- case x: BackquotedIdent[_] => false
- case x: Ident[_] => x.name.isVariableName
+ def isVarPattern(pat: Tree): Boolean = pat match {
+ case x: BackquotedIdent => false
+ case x: Ident => x.name.isVariableName
case _ => false
}
/** The first constructor definition in `stats` */
- def firstConstructor[T >: Untyped](stats: List[Tree[T]]): Tree[T] = stats match {
- case (meth: DefDef[_]) :: _ if meth.name.isConstructorName => meth
+ def firstConstructor(stats: List[Tree]): Tree = stats match {
+ case (meth: DefDef) :: _ if meth.name.isConstructorName => meth
case stat :: stats => firstConstructor(stats)
- case nil => emptyTree()
+ case nil => EmptyTree
}
/** The arguments to the first constructor in `stats`. */
- def firstConstructorArgs[T >: Untyped](stats: List[Tree[T]]): List[Tree[T]] = firstConstructor(stats) match {
+ def firstConstructorArgs(stats: List[Tree]): List[Tree] = firstConstructor(stats) match {
case DefDef(_, _, _, args :: _, _, _) => args
case _ => Nil
}
/** The value definitions marked PRESUPER in this statement sequence */
- def preSuperFields[T >: Untyped](stats: List[Tree[T]]): List[ValDef[T]] =
- (stats filter isEarlyValDef).asInstanceOf[List[ValDef[T]]]
+ def preSuperFields(stats: List[Tree]): List[ValDef] =
+ (stats filter isEarlyValDef).asInstanceOf[List[ValDef]]
- def isEarlyDef(tree: Tree[_ >: Untyped]) = isEarlyValDef(tree) || isEarlyTypeDef(tree)
+ def isEarlyDef(tree: Tree) = isEarlyValDef(tree) || isEarlyTypeDef(tree)
- def isEarlyValDef(tree: Tree[_ >: Untyped]) = tree match {
+ def isEarlyValDef(tree: Tree) = tree match {
case ValDef(mods, _, _, _) => mods is Scala2PreSuper
case _ => false
}
- def isEarlyTypeDef(tree: Tree[_ >: Untyped]) = tree match {
+ def isEarlyTypeDef(tree: Tree) = tree match {
case TypeDef(mods, _, _) => mods is Scala2PreSuper
case _ => false
}
/** Is tpt a vararg type of the form T* ? */
- def isRepeatedParamType(tpt: Tree[_ >: Untyped])(implicit ctx: Context) = tpt match {
- case tpt: TypeTree[_] => tpt.typeOpt.isRepeatedParam
+ def isRepeatedParamType(tpt: Tree)(implicit ctx: Context) = tpt match {
+ case tpt: TypeTree => tpt.typeOpt.isRepeatedParam
case AppliedTypeTree(Select(_, tpnme.REPEATED_PARAM_CLASS), _) => true
case AppliedTypeTree(Select(_, tpnme.JAVA_REPEATED_PARAM_CLASS), _) => true
case _ => false
}
/** Is tpt a by-name parameter type of the form => T? */
- def isByNameParamType(tpt: Tree[_ >: Untyped])(implicit ctx: Context) = tpt match {
- case tpt: TypeTree[_] => tpt.typeOpt.typeSymbol == defn.ByNameParamClass
+ def isByNameParamType(tpt: Tree)(implicit ctx: Context) = tpt match {
+ case tpt: TypeTree => tpt.typeOpt.typeSymbol == defn.ByNameParamClass
case AppliedTypeTree(Select(_, tpnme.BYNAME_PARAM_CLASS), _) => true
case _ => false
}
@@ -267,22 +160,12 @@ abstract class TreeInfo {
/** Is name a left-associative operator? */
def isLeftAssoc(operator: Name) = operator.nonEmpty && (operator.last != ':')
- /** Is tree a `this` node which belongs to `enclClass`? */
- def isSelf(tree: Tree[_ >: Untyped], enclClass: Symbol)(implicit ctx: Context): Boolean = tree match {
- case This(_) => tree.symbol == enclClass
- case _ => false
- }
-
- /** a Match(Typed(_, tpt), _) must be translated into a switch if isSwitchAnnotation(tpt.tpe)
- def isSwitchAnnotation(tpe: Type) = tpe hasAnnotation defn.SwitchClass
- */
-
/** can this type be a type pattern? */
- def mayBeTypePat(tree: Tree[Untyped]): Boolean = tree match {
+ def mayBeTypePat(tree: untpd.Tree): Boolean = tree match {
case AndTypeTree(tpt1, tpt2) => mayBeTypePat(tpt1) || mayBeTypePat(tpt2)
case OrTypeTree(tpt1, tpt2) => mayBeTypePat(tpt1) || mayBeTypePat(tpt2)
- case RefinedTypeTree(tpt, refinements) => mayBeTypePat(tpt) || refinements.exists(_.isInstanceOf[Bind[_]])
- case AppliedTypeTree(tpt, args) => mayBeTypePat(tpt) || args.exists(_.isInstanceOf[Bind[_]])
+ case RefinedTypeTree(tpt, refinements) => mayBeTypePat(tpt) || refinements.exists(_.isInstanceOf[Bind])
+ case AppliedTypeTree(tpt, args) => mayBeTypePat(tpt) || args.exists(_.isInstanceOf[Bind])
case SelectFromTypeTree(tpt, _) => mayBeTypePat(tpt)
case Annotated(_, tpt) => mayBeTypePat(tpt)
case _ => false
@@ -290,13 +173,13 @@ abstract class TreeInfo {
/** Is this argument node of the form <expr> : _* ?
*/
- def isWildcardStarArg(tree: Tree[_ >: Untyped]): Boolean = tree match {
+ def isWildcardStarArg(tree: untpd.Tree): Boolean = tree match {
case Typed(_, Ident(tpnme.WILDCARD_STAR)) => true
case _ => false
}
/** If this tree has type parameters, those. Otherwise Nil.
- def typeParameters(tree: Tree[_]): List[TypeDef] = tree match {
+ def typeParameters(tree: Tree): List[TypeDef] = tree match {
case DefDef(_, _, tparams, _, _, _) => tparams
case ClassDef(_, _, tparams, _) => tparams
case TypeDef(_, _, tparams, _) => tparams
@@ -304,42 +187,42 @@ abstract class TreeInfo {
}*/
/** Does this argument list end with an argument of the form <expr> : _* ? */
- def isWildcardStarArgList(trees: List[Tree[_ >: Untyped]]) =
+ def isWildcardStarArgList(trees: List[Tree]) =
trees.nonEmpty && isWildcardStarArg(trees.last)
/** Is the argument a wildcard argument of the form `_` or `x @ _`?
*/
- def isWildcardArg(tree: Tree[_ >: Untyped]): Boolean = unbind(tree) match {
+ def isWildcardArg(tree: Tree): Boolean = unbind(tree) match {
case Ident(nme.WILDCARD) => true
case _ => false
}
/** Is the argument a wildcard star type of the form `_*`?
*/
- def isWildcardStarType(tree: Tree[_ >: Untyped]): Boolean = tree match {
+ def isWildcardStarType(tree: Tree): Boolean = tree match {
case Ident(tpnme.WILDCARD_STAR) => true
case _ => false
}
/** Is this pattern node a catch-all (wildcard or variable) pattern? */
- def isDefaultCase(cdef: CaseDef[_ >: Untyped]) = cdef match {
+ def isDefaultCase(cdef: CaseDef) = cdef match {
case CaseDef(pat, EmptyTree, _) => isWildcardArg(pat)
case _ => false
}
/** Is this pattern node a synthetic catch-all case, added during PartialFuction synthesis before we know
* whether the user provided cases are exhaustive. */
- def isSyntheticDefaultCase(cdef: CaseDef[_ >: Untyped]) = cdef match {
+ def isSyntheticDefaultCase(cdef: CaseDef) = cdef match {
case CaseDef(Bind(nme.DEFAULT_CASE, _), EmptyTree, _) => true
case _ => false
}
/** Does this CaseDef catch Throwable? */
- def catchesThrowable(cdef: CaseDef[_ >: Untyped])(implicit ctx: Context) =
+ def catchesThrowable(cdef: CaseDef)(implicit ctx: Context) =
catchesAllOf(cdef, defn.ThrowableClass.typeConstructor)
/** Does this CaseDef catch everything of a certain Type? */
- def catchesAllOf(cdef: CaseDef[_ >: Untyped], threshold: Type)(implicit ctx: Context) =
+ def catchesAllOf(cdef: CaseDef, threshold: Type)(implicit ctx: Context) =
isDefaultCase(cdef) ||
cdef.guard.isEmpty && {
unbind(cdef.pat) match {
@@ -348,8 +231,135 @@ abstract class TreeInfo {
}
}
+ /** Is this case guarded? */
+ def isGuardedCase(cdef: CaseDef) = cdef.guard ne EmptyTree
+
+ /** Is this pattern node a sequence-valued pattern? */
+ def isSequenceValued(tree: Tree): Boolean = unbind(tree) match {
+ case Alternative(ts) => ts exists isSequenceValued
+ case SeqLiteral(_) => true
+ case _ => false
+ }
+
+ /** The underlying pattern ignoring any bindings */
+ def unbind(x: Tree): Tree = x match {
+ case Bind(_, y) => unbind(y)
+ case y => y
+ }
+}
+
+trait TypedTreeInfo extends TreeInfo[Type] {self: Trees.Instance[Type] =>
+
+ /** Is tree a definition that has no side effects when
+ * evaluated as part of a block after the first time?
+ */
+ def isIdempotentDef(tree: tpd.Tree)(implicit ctx: Context): Boolean = tree match {
+ case EmptyTree
+ | TypeDef(_, _, _)
+ | Import(_, _)
+ | DefDef(_, _, _, _, _, _) =>
+ true
+ case ValDef(mods, _, _, rhs) =>
+ !(mods is Mutable) && isIdempotentExpr(rhs)
+ case _ =>
+ false
+ }
+
+ /** Is tree an expression which can be inlined without affecting program semantics?
+ *
+ * Note that this is not called "isExprPure" since purity (lack of side-effects)
+ * is not the litmus test. References to modules and lazy vals are side-effecting,
+ * both because side-effecting code may be executed and because the first reference
+ * takes a different code path than all to follow; but they are safe to inline
+ * because the expression result from evaluating them is always the same.
+ */
+ def isIdempotentExpr(tree: tpd.Tree)(implicit ctx: Context): Boolean = tree match {
+ case EmptyTree
+ | This(_)
+ | Super(_, _)
+ | Literal(_) =>
+ true
+ case Ident(_) =>
+ tree.symbol is Stable
+ case Select(qual, _) =>
+ tree.symbol.isStable && isIdempotentExpr(qual)
+ case TypeApply(fn, _) =>
+ isIdempotentExpr(fn)
+/*
+ * Not sure we'll need that. Comment out until we find out
+ case Apply(Select(free @ Ident(_), nme.apply), _) if free.symbol.name endsWith nme.REIFY_FREE_VALUE_SUFFIX =>
+ // see a detailed explanation of this trick in `GenSymbols.reifyFreeTerm`
+ free.symbol.hasStableFlag && isIdempotentExpr(free)
+*/
+ case Apply(fn, Nil) =>
+ // Note: After uncurry, field accesses are represented as Apply(getter, Nil),
+ // so an Apply can also be pure.
+ // However, before typing, applications of nullary functional values are also
+ // Apply(function, Nil) trees. To prevent them from being treated as pure,
+ // we check that the callee is a method.
+ // The callee might also be a Block, which has a null symbol, so we guard against that (SI-7185)
+ fn.symbol != null && (fn.symbol is (Method, butNot = Lazy)) && isIdempotentExpr(fn)
+ case Typed(expr, _) =>
+ isIdempotentExpr(expr)
+ case Block(stats, expr) =>
+ (stats forall isIdempotentDef) && isIdempotentExpr(expr)
+ case _ =>
+ false
+ }
+
+ /** Is symbol potentially a getter of a mutable variable?
+ */
+ def mayBeVarGetter(sym: Symbol)(implicit ctx: Context): Boolean = {
+ def maybeGetterType(tpe: Type): Boolean = tpe match {
+ case _: ExprType | _: ImplicitMethodType => true
+ case tpe: PolyType => maybeGetterType(tpe.resultType)
+ case _ => false
+ }
+ sym.owner.isClass && !sym.isStable && maybeGetterType(sym.info)
+ }
+
+ /** Is tree a reference to a mutable variable, or to a potential getter
+ * that has a setter in the same class?
+ */
+ def isVariableOrGetter(tree: tpd.Tree)(implicit ctx: Context) = {
+ def sym = tree.symbol
+ def isVar = sym is Mutable
+ def isGetter =
+ mayBeVarGetter(sym) && sym.owner.info.member(sym.name.asTermName.getterToSetter).exists
+
+ tree match {
+ case Ident(_) => isVar
+ case Select(_, _) => isVar || isGetter
+ case Apply(_, _) =>
+ methPart(tree) match {
+ case Select(qual, nme.apply) => qual.tpe.member(nme.update).exists
+ case _ => false
+ }
+ case _ => false
+ }
+ }
+
+ /** Is tree a `this` node which belongs to `enclClass`? */
+ def isSelf(tree: Tree, enclClass: Symbol)(implicit ctx: Context): Boolean = tree match {
+ case This(_) => tree.symbol == enclClass
+ case _ => false
+ }
+
+ /** Strips layers of `.asInstanceOf[T]` / `_.$asInstanceOf[T]()` from an expression */
+ def stripCast(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = {
+ def isCast(sel: tpd.Tree) = defn.asInstanceOfMethods contains sel.symbol
+ tree match {
+ case TypeApply(sel @ Select(inner, _), _) if isCast(sel) =>
+ stripCast(inner)
+ case Apply(TypeApply(sel @ Select(inner, _), _), Nil) if isCast(sel) =>
+ stripCast(inner)
+ case t =>
+ t
+ }
+ }
+
/** Is this pattern node a catch-all or type-test pattern? */
- def isCatchCase(cdef: CaseDef[Type])(implicit ctx: Context) = cdef match {
+ def isCatchCase(cdef: CaseDef)(implicit ctx: Context) = cdef match {
case CaseDef(Typed(Ident(nme.WILDCARD), tpt), EmptyTree, _) =>
isSimpleThrowable(tpt.tpe)
case CaseDef(Bind(_, Typed(Ident(nme.WILDCARD), tpt)), EmptyTree, _) =>
@@ -366,21 +376,10 @@ abstract class TreeInfo {
false
}
- /** Is this case guarded? */
- def isGuardedCase(cdef: CaseDef[_ >: Untyped]) = cdef.guard ne EmptyTree
-
- /** Is this pattern node a sequence-valued pattern? */
- def isSequenceValued(tree: Tree[_ >: Untyped]): Boolean = unbind(tree) match {
- case Alternative(ts) => ts exists isSequenceValued
- case SeqLiteral(_) => true
- case _ => false
- }
-
- /** The underlying pattern ignoring any bindings */
- def unbind[T >: Untyped](x: Tree[T]): Tree[T] = x match {
- case Bind(_, y) => unbind(y)
- case y => y
- }
+ /** a Match(Typed(_, tpt), _) must be translated into a switch if isSwitchAnnotation(tpt.tpe)
+ def isSwitchAnnotation(tpe: Type) = tpe hasAnnotation defn.SwitchClass
+ */
+}
/** Does list of trees start with a definition of
@@ -489,5 +488,6 @@ abstract class TreeInfo {
case tree: RefTree => true
case _ => false
})*/
-}
-object TreeInfo extends TreeInfo \ No newline at end of file
+
+
+