Skip to content

Commit 19809c2

Browse files
szegedijenkins
authored andcommitted
scrooge-core: Define union field info getter for union class
Problem Some code in Schemer and Scalacheck is using reflection to retrieve the fieldInfo field from union member classes. Solution Add a supported API, `ThriftUnion.fieldInfoForUnionClass` that works the same as `unionStructFieldInfo` method on an instance, but it takes the class as a parameter and thus doesn't require instantiation of the class. JIRA Issues: CSL-11926 Differential Revision: https://phabricator.twitter.biz/D871986
1 parent 7d78ea6 commit 19809c2

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

CHANGELOG.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ Note that ``PHAB_ID=#`` and ``RB_ID=#`` correspond to associated messages in com
77
Unreleased
88
----------
99

10+
New Features
11+
~~~~~~~~~~~~
12+
13+
* scrooge-core: `c.t.scrooge.ThriftUnion.fieldInfoForUnionClass` API for retrieving
14+
`ThriftStructFieldInfo` for a `ThriftUnion` member class without having to instantiate
15+
it. ``PHAB_ID=D871986``
16+
1017
22.4.0
1118
------
1219

scrooge-core/src/main/scala/com/twitter/scrooge/ThriftUnion.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.twitter.scrooge
22

3+
import com.twitter.util.Memoize
4+
35
/**
46
* Unions are tagged with this trait.
57
*/
@@ -28,3 +30,27 @@ trait ThriftUnion extends ThriftStruct {
2830
*/
2931
def unionStructFieldInfo: Option[ThriftStructFieldInfo]
3032
}
33+
34+
object ThriftUnion {
35+
private[this] val fieldInfos = Memoize.classValue { c =>
36+
if (!classOf[ThriftUnion].isAssignableFrom(c)) {
37+
throw new IllegalArgumentException(s"${c.getName} does not extend ThriftUnion")
38+
}
39+
ThriftStructMetaData
40+
.forStructClass(c.asInstanceOf[Class[ThriftUnion]])
41+
.unionFields
42+
.collectFirst {
43+
case f if f.fieldClassTag.runtimeClass == c => f.structFieldInfo
44+
}
45+
}
46+
47+
/**
48+
* Given a specific union member class, returns the struct field info for it.
49+
* It returns the same value as invoking `unionStructFieldInfo` on an instance
50+
* of the class, without having to create an instance of it.
51+
* @param c the union member class
52+
* @return the struct field info for the class, or None
53+
*/
54+
def fieldInfoForUnionClass(c: Class[_ <: ThriftUnion]): Option[ThriftStructFieldInfo] =
55+
fieldInfos(c)
56+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.twitter.scrooge.backend
2+
3+
import com.twitter.scrooge._
4+
import com.twitter.scrooge.testutil.EvalHelper
5+
import com.twitter.scrooge.testutil.JMockSpec
6+
import includes.a.thriftscala._
7+
8+
class UnionFieldRetrievalSpec extends JMockSpec with EvalHelper {
9+
"UnionFieldRetrievalSpec" should {
10+
"retrieve field info for a union member class" in { _ =>
11+
ThriftUnion.fieldInfoForUnionClass(classOf[City.CityState]) must be(
12+
Some(City.CityState.fieldInfo))
13+
ThriftUnion.fieldInfoForUnionClass(classOf[City.Zipcode]) must be(
14+
Some(City.Zipcode.fieldInfo))
15+
}
16+
17+
"retrieve no field info for a top-level union class" in { _ =>
18+
ThriftUnion.fieldInfoForUnionClass(classOf[City]) must be(None)
19+
}
20+
21+
"fail to retrieve field info for a non-union class" in { _ =>
22+
assertThrows[IllegalArgumentException] {
23+
ThriftUnion.fieldInfoForUnionClass(classOf[Address].asInstanceOf[Class[ThriftUnion]])
24+
}
25+
}
26+
}
27+
}

0 commit comments

Comments
 (0)