Reputation: 36
case class Address( address :String ,pinCode : Int)
case class Person (a: String,b:Int ,c: Address)
def getClassDefinition[T:TypeTag] =
(typeOf[T].members.filter(!_.isMethod).map(r => (r.name -> r.typeSignature)))
val m = getClassDefinition[Address]
(pinCode ,scala.Int)
(address ,String)
val p =getClassDefinition[Person]
(c ,A$A332.this.Address)
(b ,scala.Int)
(a ,String)
I am looking for an nested result instead of just going till Address case class
Upvotes: 0
Views: 286
Reputation: 7529
If I understand the problem, it is to get a class definition that includes a name -> type signature pair for each of the the non-method members of the type. If the type signature is a standard type, that is all that is required; but for some types a nested definition is required. I've modelled this either/or case with an Either[Definition, NestedDefinition].
In this example I've chosen an isNested(...) rule that matches on the package name, but it could be any rule that identifies a class for deeper inspection.
I'm not sure if the output is in the format that you expected, but you can either modify the example code, or map the result into your own data structure.
import scala.reflect.runtime.universe._
object TypeTags {
// Define your domain name here for the isNested(...) test!
val myDomainName: String = ???
// Define some type aliases
type Definition = ((AnyRef with SymbolApi)#NameType, Type)
type EitherDefinitionOrNested = Either[Definition, NestedDefinition]
// A nested definition contains the original definition and an iterable collection of its member definitions (recursively).
case class NestedDefinition(t: Definition, m: Iterable[EitherDefinitionOrNested])
// The test to determine if a nested definition is needed.
def isNested(r: Symbol): Boolean = {
r.info.typeSymbol.fullName.startsWith(myDomainName)
}
// Obtain a class definition from a Symbol.
def classDefinition(symbol: Symbol): Iterable[EitherDefinitionOrNested] = {
symbol.typeSignature.members.filter(!_.isMethod).map {
case r @ nested if isNested(r) => Right(NestedDefinition(nested.name -> nested.typeSignature, classDefinition(nested)))
case r => Left(r.name -> r.typeSignature)
}
}
// Obtain a class definition from a type.
def getClassDefinition[T: TypeTag]: Iterable[EitherDefinitionOrNested] = classDefinition(typeOf[T].typeSymbol)
// The test case
case class Address(address: String ,pinCode: Int)
case class Person(a: String, b: Int ,c: Address)
def main(args: Array[String]): Unit = {
val m = getClassDefinition[Address]
val p = getClassDefinition[Person]
println(s"address: $m")
println(s"person: $p")
}
}
Upvotes: 1