@@ -10,9 +10,9 @@ object WrapFnGen {
1010 | * This file auto-generated by WrapFnGen.scala. Do not modify directly.
1111 | */
1212 | """ .stripMargin
13-
13+
1414 val packaging = " package scala.compat.java8"
15-
15+
1616 import scala .tools .nsc ._
1717 import scala .reflect .internal ._
1818 val settings = new Settings (msg => sys.error(msg))
@@ -21,12 +21,12 @@ object WrapFnGen {
2121 val run = new compiler.Run
2222
2323 import compiler ._ , definitions ._
24-
25-
24+
25+
2626 implicit class IndentMe (v : Vector [String ]) {
2727 def indent : Vector [String ] = v.map(" " + _)
2828 }
29-
29+
3030 implicit class FlattenMe (v : Vector [Vector [String ]]) {
3131 def mkVec (join : String = " " ): Vector [String ] = {
3232 val vb = Vector .newBuilder[String ]
@@ -39,7 +39,7 @@ object WrapFnGen {
3939 vb.result()
4040 }
4141 }
42-
42+
4343 implicit class DoubleFlattenMe (v : Vector [Vector [Vector [String ]]]) {
4444 def mkVecVec (join : String = " " ): Vector [String ] = {
4545 val vb = Vector .newBuilder[String ]
@@ -57,39 +57,39 @@ object WrapFnGen {
5757 vb.result()
5858 }
5959 }
60-
60+
6161 implicit class SplitMyLinesAndStuff (s : String ) {
6262 def toVec = s.linesIterator.toVector
6363 def nonBlank = s.trim.length > 0
6464 }
65-
65+
6666 implicit class TreeToText (t : Tree ) {
6767 def text = showCode(t).replace(" $" , " " ).linesIterator.toVector
6868 }
69-
69+
7070 case class Prioritized (lines : Vector [String ], priority : Int ) {
7171 def withPriority (i : Int ) = copy(priority = i)
7272 }
73-
73+
7474 case class SamConversionCode (
7575 base : String ,
7676 wrappedAsScala : Vector [String ],
77+ asScalaAnyVal : Vector [String ],
7778 implicitToScala : Vector [String ],
7879 asScalaDef : Vector [String ],
7980 wrappedAsJava : Vector [String ],
8081 asJavaAnyVal : Vector [String ],
8182 implicitToJava : Prioritized ,
8283 asJavaDef : Vector [String ]
8384 ) {
84- def impls : Vector [Vector [String ]] = Vector (wrappedAsScala, wrappedAsJava, asJavaAnyVal)
85+ def impls : Vector [Vector [String ]] = Vector (wrappedAsScala, asScalaAnyVal, wrappedAsJava, asJavaAnyVal)
8586 def defs : Vector [Vector [String ]] = Vector (asScalaDef, asJavaDef)
86- def convs : Vector [Vector [String ]] = Vector (implicitToScala, implicitToJava.lines)
8787 def withPriority (i : Int ): SamConversionCode = copy(implicitToJava = implicitToJava.withPriority(i))
8888 }
8989 object SamConversionCode {
9090 def apply (scc : SamConversionCode * ): (Vector [String ], Vector [Vector [String ]]) = {
9191 val sccDepthSet = scc.map(_.implicitToJava.priority).toSet
92- val codes =
92+ val codes =
9393 {
9494 if (sccDepthSet != (0 to sccDepthSet.max).toSet) {
9595 val sccDepthMap = sccDepthSet.toList.sorted.zipWithIndex.toMap
@@ -98,43 +98,46 @@ object WrapFnGen {
9898 else scc
9999 }.toVector.sortBy(_.base)
100100 def priorityName (n : Int , pure : Boolean = false ): String = {
101- val pre =
101+ val pre =
102102 if (n <= 0 )
103- if (pure) " functionConverters "
103+ if (pure) " FunctionConverters "
104104 else s " package object ${priorityName(n, pure = true )}"
105105 else
106106 if (pure) s " Priority ${n}FunctionConverters "
107107 else s " trait ${priorityName(n, pure = true )}"
108- if (! pure && n < sccDepthSet.size) s " $pre extends ${priorityName(n+ 1 , pure = true )}" else pre
108+ if (! pure && n < ( sccDepthSet.size- 1 ) ) s " $pre extends ${priorityName(n+ 1 , pure = true )}" else pre
109109 }
110- val impls =
110+ val impls =
111111 " package functionConverterImpls {" +: {
112112 codes.map(_.impls).mkVecVec().indent
113113 } :+ " }"
114114 val traits = codes.filter(_.implicitToJava.priority > 0 ).groupBy(_.implicitToJava.priority).toVector.sortBy(- _._1).map{ case (k,vs) =>
115- s " trait Priority ${k} FunctionConverters {" +:
115+ s " ${priorityName(k)} { " +:
116116 s " import functionConverterImpls._ " +:
117117 s " " +:
118118 vs.map(_.implicitToJava.lines).mkVec().indent :+
119119 s " } "
120120 }
121121 val explicitDefs = codes.map(_.defs).mkVecVec()
122122 val packageObj =
123- s " ${priorityName(0 )} { " +:
123+ s " ${priorityName(0 )} { " +:
124124 s " import functionConverterImpls._ " +:
125125 s " " +:
126126 {
127127 explicitDefs.indent ++
128- codes.filter(_.implicitToJava.priority == 0 ).map(_.convs).mkVecVec().indent
128+ Vector .fill(3 )(" " ) ++
129+ codes.filter(_.implicitToJava.priority == 0 ).map(_.implicitToJava.lines).mkVec().indent ++
130+ Vector .fill(3 )(" " ) ++
131+ codes.map(_.implicitToScala).mkVec().indent
129132 } :+ " }"
130133 (impls, traits :+ packageObj)
131134 }
132135 }
133-
136+
134137 private def buildWrappersViaReflection : Seq [SamConversionCode ] = {
135138
136139 val pack : Symbol = rootMirror.getPackageIfDefined(TermName (" java.util.function" ))
137-
140+
138141 case class Jfn (iface : Symbol , sam : Symbol ) {
139142 lazy val genericCount = iface.typeParams.length
140143 lazy val name = sam.name.toTermName
@@ -145,77 +148,81 @@ object WrapFnGen {
145148 lazy val rType = sig.resultType
146149 def arity = params.length
147150 }
148-
151+
149152 val sams = pack.info.decls.
150153 map(d => (d, d.typeSignature.members.filter(_.isAbstract).toList)).
151154 collect{ case (d, m :: Nil ) if d.isAbstract => Jfn (d, m) }
152-
155+
153156 def generate (jfn : Jfn ): SamConversionCode = {
154157 def mkRef (tp : Type ): Tree = if (tp.typeSymbol.isTypeParameter) Ident (tp.typeSymbol.name.toTypeName) else tq " $tp"
155-
158+
156159 // Types for the Java SAM and the corresponding Scala function, plus all type parameters
157160 val scalaType = gen.mkAttributedRef(FunctionClass (jfn.arity))
158161 val javaType = gen.mkAttributedRef(jfn.iface)
159162 val tnParams : List [TypeName ] = jfn.iface.typeParams.map(_.name.toTypeName)
160163 val tdParams : List [TypeDef ] = tnParams.map(TypeDef (NoMods , _, Nil , EmptyTree ))
161164 val javaTargs : List [Tree ] = tdParams.map(_.name).map(Ident (_))
162165 val scalaTargs : List [Tree ] = jfn.pTypes.map(mkRef) :+ mkRef(jfn.rType)
163-
166+
164167 // Conversion wrappers have three or four components that we need to name
165168 // (1) The wrapper class that wraps a Java SAM as Scala function, or vice versa (ClassN)
166169 // (2) A value class that provides .asJava or .asScala to request the conversion (ValCN)
167170 // (3) A name for an explicit conversion method (DefN)
168- // (4) If nested-trait lookup is needed to pick types, an implicit conversion method name (ImpN)
169-
171+ // (4) An implicit conversion method name (ImpN) that invokes the value class
172+
170173 // Names for Java conversions to Scala
171174 val j2sClassN = TypeName (" FromJava" + jfn.title)
172175 val j2sValCN = TypeName (" Rich" + jfn.title + " As" + scalaType.name.encoded)
173176 val j2sDefN = TermName (" asScalaFrom" + jfn.title)
174-
177+ val j2sImpN = TermName (" enrichAsScalaFrom" + jfn.title)
178+
175179 // Names for Scala conversions to Java
176180 val s2jClassN = TypeName (" AsJava" + jfn.title)
177181 val s2jValCN = TypeName (" Rich" + scalaType.name.encoded + " As" + jfn.title)
178182 val s2jDefN = TermName (" asJava" + jfn.title)
179183 val s2jImpN = TermName (" enrichAsJava" + jfn.title)
180-
184+
181185 // Argument lists for the function / SAM
182- val vParams = (jfn.params zip jfn.pTypes).map{ case (p,t) =>
186+ val vParams = (jfn.params zip jfn.pTypes).map{ case (p,t) =>
183187 ValDef (NoMods , p.name.toTermName, if (t.typeSymbol.isTypeParameter) Ident (t.typeSymbol.name) else gen.mkAttributedRef(t.typeSymbol), EmptyTree )
184188 }
185189 val vParamRefs = vParams.map(_.name).map(Ident (_))
186-
187- val j2sClassTree =
190+
191+ val j2sClassTree =
188192 q """ class $j2sClassN[.. $tdParams](jf: $javaType[.. $javaTargs]) extends $scalaType[.. $scalaTargs] {
189193 def apply(.. $vParams) = jf. ${jfn.name}(.. $vParamRefs)
190194 } """
191-
195+
192196 val j2sValCTree =
193- q """ implicit class $j2sValCN[.. $tdParams](private val underlying: $javaType[.. $javaTargs]) extends AnyVal {
197+ q """ class $j2sValCN[.. $tdParams](private val underlying: $javaType[.. $javaTargs]) extends AnyVal {
194198 @inline def asScala: $scalaType[.. $scalaTargs] = new $j2sClassN[.. $tnParams](underlying)
195199 } """
196-
200+
197201 val j2sDefTree =
198- q """ def $j2sDefN[.. $tdParams](jf: $javaType[.. $javaTargs]): $scalaType[.. $scalaTargs] = new $j2sClassN[.. $tnParams](jf) """
199-
202+ q """ @inline def $j2sDefN[.. $tdParams](jf: $javaType[.. $javaTargs]): $scalaType[.. $scalaTargs] = new $j2sClassN[.. $tnParams](jf) """
203+
204+ val j2sImpTree =
205+ q """ @inline implicit def $j2sImpN[.. $tdParams](jf: $javaType[.. $javaTargs]): $j2sValCN[.. $tnParams] = new $j2sValCN[.. $tnParams](jf) """
206+
200207 val s2jClassTree =
201208 q """ class $s2jClassN[.. $tdParams](sf: $scalaType[.. $scalaTargs]) extends $javaType[.. $javaTargs] {
202209 def ${jfn.name}(.. $vParams) = sf.apply(.. $vParamRefs)
203210 } """
204-
211+
205212 val s2jValCTree =
206213 q """ class $s2jValCN[.. $tdParams](private val underlying: $scalaType[.. $scalaTargs]) extends AnyVal {
207214 @inline def asJava: $javaType[.. $javaTargs] = new $s2jClassN[.. $tnParams](underlying)
208215 } """
209-
216+
210217 val s2jDefTree =
211- q """ def $s2jDefN[.. $tdParams](sf: $scalaType[.. $scalaTargs]): $javaType[.. $javaTargs] = new $s2jClassN[.. $tnParams](sf) """
212-
218+ q """ @inline def $s2jDefN[.. $tdParams](sf: $scalaType[.. $scalaTargs]): $javaType[.. $javaTargs] = new $s2jClassN[.. $tnParams](sf) """
219+
213220 // This is especially tricky because functions are contravariant in their arguments
214221 // Need to prevent e.g. Any => String from "downcasting" itself to Int => String; we want the more exact conversion
215222 val s2jImpTree : (Tree , Int ) =
216223 if (jfn.pTypes.forall(! _.isFinalType) && jfn.sig == jfn.sam.typeSignature)
217224 (
218- q """ implicit def $s2jImpN[.. $tdParams](sf: $scalaType[.. $scalaTargs]): $s2jValCN[.. $tnParams] = new $s2jValCN[.. $tnParams](sf) """ ,
225+ q """ @inline implicit def $s2jImpN[.. $tdParams](sf: $scalaType[.. $scalaTargs]): $s2jValCN[.. $tnParams] = new $s2jValCN[.. $tnParams](sf) """ ,
219226 tdParams.length
220227 )
221228 else {
@@ -242,29 +249,30 @@ object WrapFnGen {
242249 map(TypeDef (NoMods , _, Nil , EmptyTree )).
243250 dropRight(if (jfn.rType.isFinalType) 1 else 0 )
244251 val evs = evidences.map{ case (generic, specific) => ValDef (NoMods , TermName (" ev" + generic.toString), tq " $generic =:= $specific" , EmptyTree ) }
245- val tree =
246- q """ implicit def $s2jImpN[.. $scalafnTdefs](sf: $scalaType[.. $scalafnTnames])(implicit .. $evs): $s2jValCN[.. $tnParams] =
252+ val tree =
253+ q """ @inline implicit def $s2jImpN[.. $scalafnTdefs](sf: $scalaType[.. $scalafnTnames])(implicit .. $evs): $s2jValCN[.. $tnParams] =
247254 new $s2jValCN[.. $tnParams](sf.asInstanceOf[ $scalaType[.. $scalaTargs]])
248255 """
249256 val depth = numberedA.size
250257 (tree, tdParams.length)
251258 }
252-
259+
253260 SamConversionCode (
254261 base = jfn.title,
255262 wrappedAsScala = j2sClassTree.text,
256- implicitToScala = j2sValCTree.text,
263+ asScalaAnyVal = j2sValCTree.text,
264+ implicitToScala = j2sImpTree.text,
257265 asScalaDef = j2sDefTree.text,
258266 wrappedAsJava = s2jClassTree.text,
259267 asJavaAnyVal = s2jValCTree.text,
260268 implicitToJava = s2jImpTree match { case (t,d) => Prioritized (t.text, d) },
261269 asJavaDef = s2jDefTree.text
262270 )
263271 }
264-
272+
265273 sams.toSeq.map(generate)
266274 }
267-
275+
268276 lazy val converterContents =
269277 s """
270278 | $copyright
@@ -278,21 +286,21 @@ object WrapFnGen {
278286 (SamConversionCode (buildWrappersViaReflection : _* ) match {
279287 case (impls, defs) => impls.mkString(" \n " ) + " \n\n\n\n " + defs.map(_.mkString(" \n " )).mkString(" \n\n\n\n " )
280288 })
281-
289+
282290 def sameText (f : java.io.File , text : String ): Boolean = {
283291 val x = scala.io.Source .fromFile(f)
284292 val lines = try { x.getLines.toVector } finally { x.close }
285293 lines.iterator.filter(_.nonBlank) == text.linesIterator.filter(_.nonBlank)
286294 }
287-
295+
288296 def write (f : java.io.File , text : String ) {
289297 if (! f.exists || ! sameText(f, text)) {
290298 val p = new java.io.PrintWriter (f)
291299 try { p.println(text) }
292300 finally { p.close() }
293301 }
294302 }
295-
303+
296304 def main (args : Array [String ]) {
297305 val names = args.iterator.map(x => new java.io.File (x))
298306 write(names.next, converterContents)
0 commit comments