2
{ sealed trait Sealed; case object Foo extends Sealed; case class Bar(s: String) extends Sealed; trait Baz extends Sealed }
import scala.reflect.runtime.universe._
val List(bar, baz, foo) = symbolOf[Sealed].asClass.knownDirectSubclasses.toList

I've tried .asClass.primaryConstructor.isStatic, but that doesn't work if the sealed trait is defined as dependent type.

Reactormonk
  • 21,472
  • 14
  • 74
  • 123

1 Answers1

7

Symbol#isModuleClass looks like it can determine if the symbol is an object, and foo.asClass.isClass can determine whether it has the case modifier. Note that asClass will throw an exception if you use it on other type of symbol, though (method, term, etc).

Object test:

scala> bar.isModuleClass // case class
res28: Boolean = false

scala> baz.isModuleClass // trait
res29: Boolean = false

scala> foo.isModuleClass // case object
res30: Boolean = true

For other types:

scala> val a = ""
a: String = ""

scala> symbolOf[a.type].isModuleClass
res34: Boolean = false

case class A(value: String) ; object A { def default = A("") }

scala> symbolOf[A].isModuleClass
res35: Boolean = false

scala> symbolOf[A.type].isModuleClass
res36: Boolean = true

Based on the API documentation and SI-6012 it seems like isModule should also work, but it only returns true for the companionSymbol.

Case test:

scala> bar.asClass.isCaseClass // case class
res44: Boolean = true

scala> baz.asClass.isCaseClass // trait
res45: Boolean = false

scala> foo.asClass.isCaseClass // case object
res46: Boolean = true

For other types (same definitions as the examples above):

scala> symbolOf[a.type].asClass.isCaseClass // plain singleton object
res47: Boolean = false

scala> symbolOf[A].asClass.isCaseClass // case class
res48: Boolean = true

scala> symbolOf[A.type].asClass.isCaseClass // non-case object
res49: Boolean = false

Putting it together:

def isCaseObject(symbol: Symbol): Boolean =
  symbol.isModuleClass && symbol.asClass.isCaseClass

scala> isCaseObject(bar)
res50: Boolean = false

scala> isCaseObject(baz)
res51: Boolean = false

scala> isCaseObject(foo)
res52: Boolean = true

scala> isCaseObject(symbolOf[a.type])
res53: Boolean = false

scala> isCaseObject(symbolOf[A])
res54: Boolean = false

scala> isCaseObject(symbolOf[A.type])
res55: Boolean = false
Michael Zajac
  • 55,144
  • 7
  • 113
  • 138