Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Forked from paulp/test.scala
Created February 1, 2013 18:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xuwei-k/4693037 to your computer and use it in GitHub Desktop.
Save xuwei-k/4693037 to your computer and use it in GitHub Desktop.
package s
object Test {
// Observe that x.companion is statically typed such that foo is callable
def f1() = {
val x = new Foo
println(x) // Foo instance
println(x.companion) // Foo companion
println(x.companion.foo) // I'm foo!
}
// Observe that we now have a static handle on the case class factory
def f2() = {
val y = Bippy(5)
println(y) // Bippy(5)
println(y.companion) // Bippy
println(y.companion.apply(10)) // Bippy(10)
}
def f3() = {
val y = new Bar
/****
println(y.companion) // does not compile
b.scala:12: error: Instance of s.Bar has no companion object
println(y.companion)
^
one error found
****/
()
}
def main(args: Array[String]): Unit = {
f1()
f2()
}
}
class Foo {
override def toString = "Foo instance"
}
object Foo {
def foo = "I'm foo!"
override def toString = "Foo companion"
}
case class Bippy(x: Int)
class Bar {
override def toString = "Bar instance"
}
/** No object Bar **/
import scala.language.experimental.macros
import scala.language.implicitConversions
import scala.reflect.macros.Context
package s {
object typeOps {
def companionImpl[T](c: Context) = {
import c.universe._
val CompanionOpsClass = typeOf[CompanionOps[_]].typeSymbol
val clazzType = c.prefix.actualType match {
case TypeRef(_, CompanionOpsClass, arg :: Nil) => arg
case tp => c.abort(c.enclosingPosition, s"Unexpected prefix: $tp/${tp.getClass}")
}
val companion = clazzType.typeSymbol.companionSymbol match {
case NoSymbol => c.abort(c.enclosingPosition, s"Instance of $clazzType has no companion object")
case sym => sym
}
def make[U: c.WeakTypeTag] = c.Expr[U](treeBuild.mkAttributedRef(companion))
make(c.WeakTypeTag(companion.typeSignature))
}
}
}
package object s {
implicit class CompanionOps[T](val clazz: T) {
def companion: AnyRef = macro typeOps.companionImpl[T]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment