Skip to content

Commit 85fb438

Browse files
committed
Update util methods to work with fields of exact classes
Instead of searching the class hierarchy bottom to top until a field with a specified name is found we now search the field in its actual declaring class directly. That means that now we will not be able to access the wrong field by stopping too soon in the bottom to top search as we could before.
1 parent dfcf0bd commit 85fb438

File tree

6 files changed

+35
-69
lines changed

6 files changed

+35
-69
lines changed

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/ReflectionBuiltins.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ import java.lang.reflect.InvocationTargetException
2121

2222
internal val reflectionBuiltins: Set<MethodId>
2323
get() = setOf(
24-
setAccessible, invoke, newInstance, get, forName,
24+
setAccessible, invoke, newInstance, getMethodId, forName,
2525
getDeclaredMethod, getDeclaredConstructor, allocateInstance,
2626
getClass, getDeclaredField, isEnumConstant, getFieldName,
27-
equals, getSuperclass, set, newArrayInstance,
27+
equals, getSuperclass, setMethodId, newArrayInstance,
2828
setArrayElement, getArrayElement, getTargetException,
2929
)
3030

@@ -49,7 +49,7 @@ internal val newInstance = methodId(
4949
arguments = arrayOf(Array<Any>::class.id)
5050
)
5151

52-
internal val get = methodId(
52+
internal val getMethodId = methodId(
5353
classId = Field::class.id,
5454
name = "get",
5555
returnType = objectClassId,
@@ -132,7 +132,7 @@ internal val getSuperclass = methodId(
132132
returnType = Class::class.id
133133
)
134134

135-
internal val set = methodId(
135+
internal val setMethodId = methodId(
136136
classId = Field::class.id,
137137
name = "set",
138138
returnType = voidClassId,

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ internal val ClassId.setFieldMethodId: MethodId
6666
get() = utilMethodId(
6767
name = "setField",
6868
returnType = voidClassId,
69-
arguments = arrayOf(objectClassId, stringClassId, objectClassId)
69+
arguments = arrayOf(objectClassId, stringClassId, stringClassId, objectClassId)
7070
)
7171

7272
internal val ClassId.setStaticFieldMethodId: MethodId
@@ -80,7 +80,7 @@ internal val ClassId.getFieldValueMethodId: MethodId
8080
get() = utilMethodId(
8181
name = "getFieldValue",
8282
returnType = objectClassId,
83-
arguments = arrayOf(objectClassId, stringClassId)
83+
arguments = arrayOf(objectClassId, stringClassId, stringClassId)
8484
)
8585

8686
internal val ClassId.getStaticFieldValueMethodId: MethodId

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgFieldStateManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ internal class CgFieldStateManagerImpl(val context: CgContext)
229229
val name = if (index == path.lastIndex) customName else getFieldVariableName(prev, passedPath)
230230
val expression = when (val newElement = path[index++]) {
231231
is FieldAccess -> {
232-
val field = newElement.field
233-
testClassThisInstance[getFieldValue](prev, stringLiteral(field.name))
232+
val fieldId = newElement.field
233+
testClassThisInstance[getFieldValue](prev, fieldId.declaringClass.name, fieldId.name)
234234
}
235235
is ArrayElementAccess -> {
236236
Array::class.id[getArrayElement](prev, newElement.index)

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ import org.utbot.framework.codegen.model.util.length
7373
import org.utbot.framework.codegen.model.util.lessThan
7474
import org.utbot.framework.codegen.model.util.nullLiteral
7575
import org.utbot.framework.codegen.model.util.resolve
76-
import org.utbot.framework.codegen.model.util.stringLiteral
7776
import org.utbot.framework.fields.ExecutionStateAnalyzer
7877
import org.utbot.framework.fields.FieldPath
7978
import org.utbot.framework.plugin.api.BuiltinClassId
@@ -1047,7 +1046,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
10471046
if (variable.type.hasField(this) && isAccessibleFrom(testClassPackageName)) {
10481047
if (jField.isStatic) CgStaticFieldAccess(this) else CgFieldAccess(variable, this)
10491048
} else {
1050-
testClassThisInstance[getFieldValue](variable, stringLiteral(name))
1049+
testClassThisInstance[getFieldValue](variable, this.declaringClass.name, this.name)
10511050
}
10521051

10531052
/**

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgVariableConstructor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ internal class CgVariableConstructor(val context: CgContext) :
145145
fieldAccess `=` variableForField
146146
} else {
147147
// composite models must not have info about static fields, hence only non-static fields are set here
148-
+testClassThisInstance[setField](obj, fieldId.name, variableForField)
148+
+testClassThisInstance[setField](obj, fieldId.declaringClass.name, fieldId.name, variableForField)
149149
}
150150
}
151151
return obj

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/visitor/UtilMethods.kt

Lines changed: 25 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -143,47 +143,31 @@ fun getFieldValue(language: CodegenLanguage): String =
143143
when (language) {
144144
CodegenLanguage.JAVA -> {
145145
"""
146-
private static Object getFieldValue(Object obj, String fieldName) throws IllegalAccessException, NoSuchFieldException {
147-
Class<?> clazz = obj.getClass();
148-
java.lang.reflect.Field field;
149-
do {
150-
try {
151-
field = clazz.getDeclaredField(fieldName);
152-
field.setAccessible(true);
153-
java.lang.reflect.Field modifiersField = java.lang.reflect.Field.class.getDeclaredField("modifiers");
154-
modifiersField.setAccessible(true);
155-
modifiersField.setInt(field, field.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
156-
157-
return field.get(obj);
158-
} catch (NoSuchFieldException e) {
159-
clazz = clazz.getSuperclass();
160-
}
161-
} while (clazz != null);
162-
163-
throw new NoSuchFieldException("Field '" + fieldName + "' not found on class " + obj.getClass());
146+
private static Object getFieldValue(Object obj, String fieldClassName, String fieldName) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
147+
Class<?> clazz = Class.forName(fieldClassName);
148+
java.lang.reflect.Field field = clazz.getDeclaredField(fieldName);
149+
150+
field.setAccessible(true);
151+
java.lang.reflect.Field modifiersField = java.lang.reflect.Field.class.getDeclaredField("modifiers");
152+
modifiersField.setAccessible(true);
153+
modifiersField.setInt(field, field.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
154+
155+
return field.get(obj);
164156
}
165157
"""
166158
}
167159
CodegenLanguage.KOTLIN -> {
168160
"""
169-
private fun getFieldValue(any: kotlin.Any, fieldName: String): kotlin.Any? {
170-
var clazz: Class<*>? = any.javaClass
171-
var field: java.lang.reflect.Field
172-
do {
173-
try {
174-
field = clazz!!.getDeclaredField(fieldName)
175-
field.isAccessible = true
176-
val modifiersField: java.lang.reflect.Field = java.lang.reflect.Field::class.java.getDeclaredField("modifiers")
177-
modifiersField.isAccessible = true
178-
modifiersField.setInt(field, field.modifiers and java.lang.reflect.Modifier.FINAL.inv())
179-
180-
return field.get(any)
181-
} catch (e: NoSuchFieldException) {
182-
clazz = clazz!!.superclass
183-
}
184-
} while (clazz != null)
161+
private fun getFieldValue(any: kotlin.Any, fieldClassName: String, fieldName: String): kotlin.Any? {
162+
val clazz: Class<*>? = Class.forName(fieldClassName)
163+
val field: java.lang.reflect.Field = clazz.getDeclaredField(fieldName)
164+
165+
field.isAccessible = true
166+
val modifiersField: java.lang.reflect.Field = java.lang.reflect.Field::class.java.getDeclaredField("modifiers")
167+
modifiersField.isAccessible = true
168+
modifiersField.setInt(field, field.modifiers and java.lang.reflect.Modifier.FINAL.inv())
185169
186-
throw NoSuchFieldException("Field '" + fieldName + "' not found on class " + any.javaClass)
170+
return field.get(any)
187171
}
188172
"""
189173
}
@@ -244,18 +228,9 @@ fun setField(language: CodegenLanguage): String =
244228
when (language) {
245229
CodegenLanguage.JAVA -> {
246230
"""
247-
private static void setField(Object object, String fieldName, Object fieldValue) throws NoSuchFieldException, IllegalAccessException {
248-
Class<?> clazz = object.getClass();
249-
java.lang.reflect.Field field;
250-
251-
do {
252-
try {
253-
field = clazz.getDeclaredField(fieldName);
254-
} catch (Exception e) {
255-
clazz = clazz.getSuperclass();
256-
field = null;
257-
}
258-
} while (field == null);
231+
private static void setField(Object object, String fieldClassName, String fieldName, Object fieldValue) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
232+
Class<?> clazz = Class.forName(fieldClassName);
233+
java.lang.reflect.Field field = clazz.getDeclaredField(fieldName);
259234
260235
java.lang.reflect.Field modifiersField = java.lang.reflect.Field.class.getDeclaredField("modifiers");
261236
modifiersField.setAccessible(true);
@@ -268,17 +243,9 @@ fun setField(language: CodegenLanguage): String =
268243
}
269244
CodegenLanguage.KOTLIN -> {
270245
"""
271-
private fun setField(any: kotlin.Any, fieldName: String, fieldValue: kotlin.Any?) {
272-
var clazz: Class<*> = any.javaClass
273-
var field: java.lang.reflect.Field?
274-
do {
275-
try {
276-
field = clazz.getDeclaredField(fieldName)
277-
} catch (e: Exception) {
278-
clazz = clazz.superclass
279-
field = null
280-
}
281-
} while (field == null)
246+
private fun setField(any: kotlin.Any, fieldClassName: String, fieldName: String, fieldValue: kotlin.Any?) {
247+
val clazz: Class<*> = Class.forName(fieldClassName)
248+
val field: java.lang.reflect.Field = clazz.getDeclaredField(fieldName)
282249
283250
val modifiersField: java.lang.reflect.Field = java.lang.reflect.Field::class.java.getDeclaredField("modifiers")
284251
modifiersField.isAccessible = true

0 commit comments

Comments
 (0)