mirror of
https://github.com/corda/corda.git
synced 2025-03-01 04:16:21 +00:00
Corda-1945 - class-carpenter bugfix (#3969)
This commit is contained in:
parent
a11df32dd6
commit
52b7a798d4
@ -106,8 +106,8 @@ class ClassCarpenter(
|
|||||||
*/
|
*/
|
||||||
fun build(schema: Schema): Class<*> {
|
fun build(schema: Schema): Class<*> {
|
||||||
validateSchema(schema)
|
validateSchema(schema)
|
||||||
// Walk up the inheritance hierarchy and then start walking back down once we either hit the top, or
|
// Walk up the inheritance hierarchy until we hit either the top or a class we've already generated,
|
||||||
// find a class we haven't generated yet.
|
// then walk back down it generating classes.
|
||||||
val hierarchy = ArrayList<Schema>()
|
val hierarchy = ArrayList<Schema>()
|
||||||
hierarchy += schema
|
hierarchy += schema
|
||||||
var cursor = schema.superclass
|
var cursor = schema.superclass
|
||||||
@ -283,16 +283,16 @@ class ClassCarpenter(
|
|||||||
visitInsn(DUP)
|
visitInsn(DUP)
|
||||||
|
|
||||||
var idx = 0
|
var idx = 0
|
||||||
schema.fields.forEach {
|
schema.fields.keys.forEach { key ->
|
||||||
visitInsn(DUP)
|
visitInsn(DUP)
|
||||||
visitIntInsn(BIPUSH, idx)
|
visitIntInsn(BIPUSH, idx)
|
||||||
visitTypeInsn(NEW, schema.jvmName)
|
visitTypeInsn(NEW, schema.jvmName)
|
||||||
visitInsn(DUP)
|
visitInsn(DUP)
|
||||||
visitLdcInsn(it.key)
|
visitLdcInsn(key)
|
||||||
visitIntInsn(BIPUSH, idx++)
|
visitIntInsn(BIPUSH, idx++)
|
||||||
visitMethodInsn(INVOKESPECIAL, schema.jvmName, "<init>", "(L$jlString;I)V", false)
|
visitMethodInsn(INVOKESPECIAL, schema.jvmName, "<init>", "(L$jlString;I)V", false)
|
||||||
visitInsn(DUP)
|
visitInsn(DUP)
|
||||||
visitFieldInsn(PUTSTATIC, schema.jvmName, it.key, "L${schema.jvmName};")
|
visitFieldInsn(PUTSTATIC, schema.jvmName, key, "L${schema.jvmName};")
|
||||||
visitInsn(AASTORE)
|
visitInsn(AASTORE)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,20 +358,18 @@ class ClassCarpenter(
|
|||||||
visitCode()
|
visitCode()
|
||||||
|
|
||||||
// Calculate the super call.
|
// Calculate the super call.
|
||||||
val superclassFields = schema.superclass?.fieldsIncludingSuperclasses() ?: emptyMap()
|
|
||||||
visitVarInsn(ALOAD, 0)
|
visitVarInsn(ALOAD, 0)
|
||||||
val sc = schema.superclass
|
val sc = schema.superclass
|
||||||
|
var slot = 1
|
||||||
if (sc == null) {
|
if (sc == null) {
|
||||||
visitMethodInsn(INVOKESPECIAL, jlObject, "<init>", "()V", false)
|
visitMethodInsn(INVOKESPECIAL, jlObject, "<init>", "()V", false)
|
||||||
} else {
|
} else {
|
||||||
var slot = 1
|
slot = sc.fieldsIncludingSuperclasses().values.fold(slot) { acc, field -> acc + load(acc, field) }
|
||||||
superclassFields.values.forEach { slot += load(slot, it) }
|
|
||||||
val superDesc = sc.descriptorsIncludingSuperclasses().values.joinToString("")
|
val superDesc = sc.descriptorsIncludingSuperclasses().values.joinToString("")
|
||||||
visitMethodInsn(INVOKESPECIAL, sc.name.jvm, "<init>", "($superDesc)V", false)
|
visitMethodInsn(INVOKESPECIAL, sc.name.jvm, "<init>", "($superDesc)V", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign the fields from parameters.
|
// Assign the fields from parameters.
|
||||||
var slot = 1 + superclassFields.size
|
|
||||||
for ((name, field) in schema.fields) {
|
for ((name, field) in schema.fields) {
|
||||||
(field as ClassField).nullTest(this, slot)
|
(field as ClassField).nullTest(this, slot)
|
||||||
|
|
||||||
|
@ -128,6 +128,25 @@ class ClassCarpenterTest {
|
|||||||
assertEquals("B{a=xa, b=xb}", i.toString())
|
assertEquals("B{a=xa, b=xb}", i.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the fix for [Corda-1945](https://r3-cev.atlassian.net/secure/RapidBoard.jspa?rapidView=83&modal=detail&selectedIssue=CORDA-1945)
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
fun `superclasses with double-size primitive constructor parameters`() {
|
||||||
|
val schema1 = ClassSchema(
|
||||||
|
"gen.A",
|
||||||
|
mapOf("a" to NonNullableField(Long::class.javaPrimitiveType!!)))
|
||||||
|
val schema2 = ClassSchema(
|
||||||
|
"gen.B",
|
||||||
|
mapOf("b" to NonNullableField(String::class.java)),
|
||||||
|
schema1)
|
||||||
|
val clazz = cc.build(schema2)
|
||||||
|
val i = clazz.constructors[0].newInstance(1L, "xb") as SimpleFieldAccess
|
||||||
|
assertEquals(1L, i["a"])
|
||||||
|
assertEquals("xb", i["b"])
|
||||||
|
assertEquals("B{a=1, b=xb}", i.toString())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun interfaces() {
|
fun interfaces() {
|
||||||
val schema1 = ClassSchema(
|
val schema1 = ClassSchema(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user