Type members
Abstract type declarations
Abstract type declarations are written using TYPEVAR(sym|"T"). Optionally, lower bounds and higher bounds can be specified:
import treehugger.forest._, definitions._, treehuggerDSL._
val tree = (TYPEVAR("T"): Tree)
// tree: Tree = TypeDef(
// Modifiers(0L, TypeName(""), List()),
// TypeName("T"),
// List(),
// EmptyTree
// )
treeToString(tree)
// res0: String = "type T"
val tree2 = (TYPEVAR("T") LOWER(IntClass): Tree)
// tree2: Tree = TypeDef(
// Modifiers(0L, TypeName(""), List()),
// TypeName("T"),
// List(),
// TypeTree()
// )
treeToString(tree2)
// res1: String = "type T >: Int"
object sym {
val T = RootClass.newAliasType("T")
val A = RootClass.newAliasType("A")
val B = RootClass.newAliasType("B")
}
val tree3 = (TYPEVAR(sym.T) UPPER(ComparableClass TYPE_OF sym.T): Tree)
// tree3: Tree = TypeDef(
// Modifiers(0L, TypeName(""), List()),
// TypeName("T"),
// List(),
// TypeTree()
// )
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(...), ...):
val tree4 = TYPEVAR("IntList") := TYPE_LIST(IntClass)
// tree4: TypeDef = TypeDef(
// Modifiers(0L, TypeName(""), List()),
// TypeName("IntList"),
// List(),
// TypeTree()
// )
treeToString(tree4)
// res3: String = "type IntList = List[Int]"
val tree5 = TYPEVAR("Two") withTypeParams(TYPEVAR(sym.A)) := TYPE_TUPLE(sym.A, sym.A)
// tree5: TypeDef = TypeDef(
// Modifiers(0L, TypeName(""), List()),
// TypeName("Two"),
// List(
// TypeDef(
// Modifiers(0L, TypeName(""), List()),
// TypeName("A"),
// List(),
// EmptyTree
// )
// ),
// TypeTree()
// )
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(...):
val A = RootClass.newTypeParameter("A")
// A: TypeSymbol = A
val tree6 = (TYPEVAR("M") withTypeParams(TYPEVAR(COVARIANT(A))): Tree)
// tree6: Tree = TypeDef(
// Modifiers(0L, TypeName(""), List()),
// TypeName("M"),
// List(
// TypeDef(
// Modifiers(0L, TypeName(""), List()),
// TypeName("A"),
// List(),
// EmptyTree
// )
// ),
// EmptyTree
// )
val tree7 = (TYPEVAR("M") withTypeParams(TYPEVAR(CONTRAVARIANT(A))): Tree)
// tree7: Tree = TypeDef(
// Modifiers(0L, TypeName(""), List()),
// TypeName("M"),
// List(
// TypeDef(
// Modifiers(0L, TypeName(""), List()),
// TypeName("A"),
// List(),
// EmptyTree
// )
// ),
// EmptyTree
// )
The above examples print as:
treeToString(tree6)
// res5: String = "type M[+A]"
treeToString(tree7)
// res6: String = "type M[-A]"