Skip to content

Commit 1db0af4

Browse files
committed
Define inverse function of convert_annotations
This function can be used to retrieve annotations from a symbol table. A unit test is added for this functionality.
1 parent 4b7a195 commit 1db0af4

12 files changed

+122
-0
lines changed

jbmc/src/java_bytecode/java_bytecode_convert_class.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,31 @@ void convert_annotations(
10321032
}
10331033
}
10341034

1035+
/// Convert java annotations, e.g. as retrieved from the symbol table, back
1036+
/// to type annotationt (inverse of convert_annotations())
1037+
/// \param java_annotations: The java_annotationt collection to convert
1038+
/// \param annotations: The annotationt collection to populate
1039+
void convert_java_annotations(
1040+
const std::vector<java_annotationt> &java_annotations,
1041+
java_bytecode_parse_treet::annotationst &annotations)
1042+
{
1043+
for(const auto &java_annotation : java_annotations)
1044+
{
1045+
annotations.emplace_back(java_bytecode_parse_treet::annotationt());
1046+
auto &annotation = annotations.back();
1047+
annotation.type = java_annotation.get_type();
1048+
1049+
std::transform(
1050+
java_annotation.get_values().begin(),
1051+
java_annotation.get_values().end(),
1052+
std::back_inserter(annotation.element_value_pairs),
1053+
[](const java_annotationt::valuet &value)
1054+
-> java_bytecode_parse_treet::annotationt::element_value_pairt {
1055+
return {value.get_name(), value.get_value()};
1056+
});
1057+
}
1058+
}
1059+
10351060
/// Checks if the class is implicitly generic, i.e., it is an inner class of
10361061
/// any generic class. All uses of the implicit generic type parameters within
10371062
/// the inner class are updated to point to the type parameters of the

jbmc/src/java_bytecode/java_bytecode_convert_class.h

+4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ void convert_annotations(
3333
const java_bytecode_parse_treet::annotationst &parsed_annotations,
3434
std::vector<java_annotationt> &annotations);
3535

36+
void convert_java_annotations(
37+
const std::vector<java_annotationt> &java_annotations,
38+
java_bytecode_parse_treet::annotationst &annotations);
39+
3640
void mark_java_implicitly_generic_class_type(
3741
const irep_idt &class_name,
3842
symbol_tablet &symbol_table);

jbmc/unit/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ SRC += java_bytecode/goto-programs/class_hierarchy_output.cpp \
99
java_bytecode/goto-programs/class_hierarchy_graph.cpp \
1010
java_bytecode/goto-programs/remove_virtual_functions_without_fallback.cpp \
1111
java_bytecode/java_bytecode_convert_class/convert_abstract_class.cpp \
12+
java_bytecode/java_bytecode_convert_class/convert_java_annotations.cpp \
1213
java_bytecode/java_bytecode_convert_method/convert_invoke_dynamic.cpp \
1314
java_bytecode/java_bytecode_parse_generics/parse_generic_class.cpp \
1415
java_bytecode/java_object_factory/gen_nondet_string_init.cpp \
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@MyClassAnnotation(6)
2+
public class ClassWithClassAnnotation {
3+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public class ClassWithMethodAnnotation {
2+
3+
@MyMethodAnnotation(methodValue = 11)
4+
public void myMethod() {
5+
}
6+
7+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public @interface MyClassAnnotation {
2+
int value();
3+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public @interface MyMethodAnnotation {
2+
int methodValue();
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for converting annotations
4+
5+
Author: Diffblue Ltd.
6+
7+
\*******************************************************************/
8+
9+
#include <java-testing-utils/load_java_class.h>
10+
#include <java_bytecode/java_bytecode_convert_class.h>
11+
#include <java_bytecode/java_bytecode_parse_tree.h>
12+
#include <java_bytecode/java_types.h>
13+
#include <testing-utils/catch.hpp>
14+
15+
SCENARIO(
16+
"java_bytecode_convert_annotations",
17+
"[core][java_bytecode][java_bytecode_convert_class]")
18+
{
19+
GIVEN("Some class files in the class path")
20+
{
21+
WHEN("Parsing a class with class-level annotation MyClassAnnotation(6)")
22+
{
23+
const symbol_tablet &new_symbol_table = load_java_class(
24+
"ClassWithClassAnnotation",
25+
"./java_bytecode/java_bytecode_convert_class");
26+
27+
THEN("The annotation should have the correct structure")
28+
{
29+
const symbolt &class_symbol =
30+
*new_symbol_table.lookup("java::ClassWithClassAnnotation");
31+
const std::vector<java_annotationt> &java_annotations =
32+
to_annotated_type(class_symbol.type).get_annotations();
33+
java_bytecode_parse_treet::annotationst annotations;
34+
convert_java_annotations(java_annotations, annotations);
35+
REQUIRE(annotations.size() == 1);
36+
const auto &annotation = annotations.front();
37+
const auto &identifier =
38+
to_symbol_type(annotation.type.subtype()).get_identifier();
39+
REQUIRE(id2string(identifier) == "java::MyClassAnnotation");
40+
const auto &element_value_pair = annotation.element_value_pairs.front();
41+
const auto &element_name = element_value_pair.element_name;
42+
REQUIRE(id2string(element_name) == "value");
43+
const auto &expr = element_value_pair.value;
44+
const auto comp_expr = from_integer(6, java_int_type());
45+
REQUIRE(expr == comp_expr);
46+
}
47+
}
48+
WHEN("Parsing a class with method-level annotation MyMethodAnnotation(11)")
49+
{
50+
const symbol_tablet &new_symbol_table = load_java_class(
51+
"ClassWithMethodAnnotation",
52+
"./java_bytecode/java_bytecode_convert_class");
53+
54+
THEN("The annotation should have the correct structure")
55+
{
56+
const symbolt &method_symbol = *new_symbol_table.lookup(
57+
"java::ClassWithMethodAnnotation.myMethod:()V");
58+
const std::vector<java_annotationt> &java_annotations =
59+
to_annotated_type(method_symbol.type).get_annotations();
60+
java_bytecode_parse_treet::annotationst annotations;
61+
convert_java_annotations(java_annotations, annotations);
62+
REQUIRE(annotations.size() == 1);
63+
const auto &annotation = annotations.front();
64+
const auto &identifier =
65+
to_symbol_type(annotation.type.subtype()).get_identifier();
66+
REQUIRE(id2string(identifier) == "java::MyMethodAnnotation");
67+
const auto &element_value_pair = annotation.element_value_pairs.front();
68+
const auto &element_name = element_value_pair.element_name;
69+
REQUIRE(id2string(element_name) == "methodValue");
70+
const auto &expr = element_value_pair.value;
71+
const auto &comp_expr = from_integer(11, java_int_type());
72+
REQUIRE(expr == comp_expr);
73+
}
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)