Type members 

Abstract type declarations 

Abstract type declarations are written using TYPEVAR(sym|"T"). Optionally, lower bounds and higher bounds can be specified:

scala> import treehugger.forest._, definitions._, treehuggerDSL._
import treehugger.forest._
import definitions._
import treehuggerDSL._

scala> val tree = (TYPEVAR("T"): Tree)
tree: treehugger.forest.Tree = TypeDef(Modifiers(, , Map()),T,List(),EmptyTree)

scala> treeToString(tree)
res0: String = type T

scala> val tree2 = (TYPEVAR("T") LOWER(IntClass): Tree)
tree2: treehugger.forest.Tree = TypeDef(Modifiers(, , Map()),T,List(),TypeTree())

scala> treeToString(tree2)
res1: String = type T >: Int

scala> object sym {
  val T = RootClass.newAliasType("T")
  val A = RootClass.newAliasType("A")
  val B = RootClass.newAliasType("B")
defined module sym

scala> val tree3 = (TYPEVAR(sym.T) UPPER(ComparableClass TYPE_OF sym.T): Tree)
tree3: treehugger.forest.Tree = TypeDef(Modifiers(, , Map()),T,List(),TypeTree())

scala> treeToString(tree3)
res2: String = type T <: Comparable[T]

or in general:

(TYPEVAR(sym|"T") [LOWER(lo|"C")] [UPPER(hi|"D")]).tree

where lo denotes an optional lower bound type and hi upper bound type.

Type alias definitions 

Type alias definitions are written by appending := and right-hand side Type. The alias may accompany type parameters given by withTypeParams(TYPEVAR(...), ...):

scala> val tree4 = TYPEVAR("IntList") := TYPE_LIST(IntClass)
tree4: treehugger.forest.TypeDef = TypeDef(Modifiers(, , Map()),IntList,List(),TypeTree())

scala> treeToString(tree4)
res3: String = type IntList = List[Int]

scala> val tree5 = TYPEVAR("Two") withTypeParams(TYPEVAR(sym.A)) := TYPE_TUPLE(sym.A, sym.A)
tree5: treehugger.forest.TypeDef = TypeDef(Modifiers(, , Map()),Two,List(TypeDef(Modifiers(, , Map()),A,List(),EmptyTree)),TypeTree())

scala> treeToString(tree5)
res4: String = type Two[A] = (A, A)

or in general:

TYPEVAR(sym|"T") [withTypeParams(TYPEVAR(typ1), ...)] := typ2

Variance annotations 

Variance annotations for the type parameters are set using COVARIANT(...) and CONTRAVARIANT(...):

scala> val A = RootClass.newTypeParameter("A")
A: treehugger.forest.TypeSymbol = A

scala> val tree6 = (TYPEVAR("M") withTypeParams(TYPEVAR(COVARIANT(A))): Tree)
tree6: treehugger.forest.Tree = TypeDef(Modifiers(, , Map()),M,List(TypeDef(Modifiers(, , Map()),A,List(),EmptyTree)),EmptyTree)

scala> val tree7 = (TYPEVAR("M") withTypeParams(TYPEVAR(CONTRAVARIANT(A))): Tree)
tree7: treehugger.forest.Tree = TypeDef(Modifiers(, , Map()),M,List(TypeDef(Modifiers(, , Map()),A,List(),EmptyTree)),EmptyTree)

The above examples print as:

scala> treeToString(tree6)
res5: String = type M[+A]

scala> treeToString(tree7)
res6: String = type M[-A]