Scala の compiler 内部の非公式(?) な Class 紹介

以下のようなちょっと便利そうなclass見つけたので、使ってみた。version は 2.9.0.1
http://github.com/scala/scala/blob/master/src/compiler/scala/tools/nsc/interpreter/RichClass.scala


REPL起動すると、自動でscala-compiler.jarはpathに含まれているので

implicit def toRichClass[T](c:Class[T]) = new tools.nsc.interpreter.RichClass(c)

というimplicit defを定義するだけで使えるはず。なおコンパイラ内部のもので、普通はユーザーが使うものではないので、次回のversionで急に無くなる可能性もある。


ところで、

ということがあるみたいですが、今紹介したRichClassみたいな感じというか、もっと色々便利なものが入ったりするかもしれないんですかね?*1


ちなみに、2.9.0.1時点のRichClassのソースコード

/* NSC -- new Scala compiler
 * Copyright 2005-2011 LAMP/EPFL
 * @author  Paul Phillips
 */

package scala.tools.nsc
package interpreter

class RichClass[T](val clazz: Class[T]) {
  def toManifest: Manifest[T] = Manifest.classType(clazz)
  def toTypeString: String = TypeStrings.fromClazz(clazz)
  
  // Sadly isAnonymousClass does not return true for scala anonymous
  // classes because our naming scheme is not doing well against the
  // jvm's many assumptions.
  def isScalaAnonymous = clazz.isAnonymousClass || (clazz.getName contains "$anon$")
  
  /** It's not easy... to be... me... */
  def supermans: List[Manifest[_]] = supers map (_.toManifest)
  def superNames: List[String]     = supers map (_.getName)
  def interfaces: List[JClass]     = supers filter (_.isInterface)

  def hasAncestorName(f: String => Boolean) = superNames exists f
  def hasAncestor(f: JClass => Boolean) = supers exists f
  def hasAncestorInPackage(pkg: String) = hasAncestorName(_ startsWith (pkg + "."))

  def supers: List[JClass] = {
    def loop(x: JClass): List[JClass] = x.getSuperclass match {
      case null   => List(x)
      case sc     => x :: (x.getInterfaces.toList flatMap loop) ++ loop(sc)
    }
    loop(clazz).distinct
  }
}

*1: https://wiki.scala-lang.org/display/SW/Reflection いつの間にかwikiにまとめられてる