Skip to content

Converters for java.util.function #32

Closed
@retronym

Description

@retronym

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)
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions