Skip to content

Converters for java.util.function #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
retronym opened this issue Apr 30, 2015 · 1 comment
Closed

Converters for java.util.function #32

retronym opened this issue Apr 30, 2015 · 1 comment
Assignees
Milestone

Comments

@retronym
Copy link
Member

We could generate these reflectively. Here's a sketch:

object Test {
  def main(args: Array[String]): Unit = {
    reflect
  }

  def reflect = {
    import scala.tools.nsc._
    import scala.tools.nsc._
    val settings = new Settings
    settings.processArgumentString("-usejavacp")
    val compiler = new Global(settings)
    new compiler.Run

    import compiler._, definitions._

    val pack = rootMirror.getPackageIfDefined("java.util.function")
    println(pack.info.decls.toList.take(10).map(_.fullName).mkString("\n"))

    def wrap(abstractMethod: Symbol): Tree = {
      val name = abstractMethod.name.toTermName
      val params = abstractMethod.info.params
      val result = abstractMethod.info.resultType
      val arity = params.length
      val enclosingClass = abstractMethod.owner
      val enclosingTparams = enclosingClass.typeParams
      val wrapperName = TypeName(enclosingClass.name.encoded + "Wrapper")
      val parent = gen.mkAttributedRef(FunctionClass(arity))
      val wrapperTParams: List[TypeDef] = enclosingTparams.map(_.name.toTypeName).map(TypeDef(NoMods, _, Nil, EmptyTree))
      val selfTargs: List[Tree] = wrapperTParams.map(_.name).map(Ident(_))
      def mkRef(tp: Type): Tree = if (tp.typeSymbol.isTypeParameter) Ident(tp.typeSymbol.name.toTypeName) else tq"$tp"
      val parentTargs: List[Tree] = params.map(_.info).map(mkRef) :+ mkRef(result)
      val wrapperVParams = params.map(p => 
        ValDef(NoMods, p.name.toTermName, if (p.info.typeSymbol.isTypeParameter) Ident(p.info.typeSymbol.name) else gen.mkAttributedRef(p.info.typeSymbol), EmptyTree)
      )
      val wrapperVParamRefs = wrapperVParams.map(_.name).map(Ident(_))
      q"""class ${wrapperName}[..$wrapperTParams](self: ${gen.mkAttributedRef(enclosingClass)}[..$selfTargs]) extends $parent[..$parentTargs] {
        def apply(..$wrapperVParams) = self.$name(..${wrapperVParamRefs})
      }
      """
    }

    {
      val longToIntFunction = pack.info.decl(TypeName("LongToIntFunction"))
      val abstractMethod = longToIntFunction.info.decls.toList.find(_.isAbstract).get
      println(abstractMethod.defString)
      println(showCode(wrap(abstractMethod)))
    }

    {
      val predicate = pack.info.decl(TypeName("Predicate"))
      val abstractMethod = predicate.info.decls.toList.find(_.isAbstract).get
      println(abstractMethod.defString)
      println(showCode(wrap(abstractMethod)))
    }
  }
}

Outputs:

% scalac sandbox/reflect.scala && scala Test
warning: there was one deprecation warning; re-run with -deprecation for details
one warning found
java.util.function.ToDoubleBiFunction
java.util.function.ToDoubleFunction
java.util.function.LongToIntFunction
java.util.function.IntFunction
java.util.function.LongConsumer
java.util.function.LongFunction
java.util.function.BooleanSupplier
java.util.function.ObjDoubleConsumer
java.util.function.Supplier
java.util.function.IntSupplier
def applyAsInt(x$1: Long): Int
class LongToIntFunctionWrapper(self: java.util.function.LongToIntFunction) extends scala.Function1[Long, Int] {
  def apply(x$1: scala.Long) = self.applyAsInt(x$1)
}
def test(x$1: T): Boolean
class PredicateWrapper[T](self: java.util.function.Predicate[T]) extends scala.Function1[T, Boolean] {
  def apply(x$1: T) = self.test(x$1)
}
@retronym retronym added this to the 0.5.0 milestone Jul 28, 2015
@retronym
Copy link
Member Author

Implemented by @Ichoran in #48

@retronym retronym modified the milestones: 0.5.0, 0.6.0 Aug 13, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants