Skip to content

Commit 6fea32a

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 1385950 commit 6fea32a

11 files changed

+121
-0
lines changed

jbmc/src/java_bytecode/java_bytecode_convert_class.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,32 @@ void convert_annotations(
10331033
}
10341034
}
10351035

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

jbmc/src/java_bytecode/java_bytecode_convert_class.h

Lines changed: 4 additions & 0 deletions
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);
Binary file not shown.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@MyClassAnnotation(6)
2+
public class ClassWithClassAnnotation {
3+
}
Binary file not shown.
Lines changed: 7 additions & 0 deletions
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.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public @interface MyClassAnnotation {
2+
int value();
3+
}
Binary file not shown.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public @interface MyMethodAnnotation {
2+
int methodValue();
3+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for converting annotations
4+
5+
Author: Diffblue Ltd.
6+
7+
\*******************************************************************/
8+
9+
#include <testing-utils/catch.hpp>
10+
#include <java-testing-utils/load_java_class.h>
11+
#include <java_bytecode/java_types.h>
12+
#include <java_bytecode/java_bytecode_parse_tree.h>
13+
#include <java_bytecode/java_bytecode_convert_class.h>
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 a class-level annotation")
22+
{
23+
const symbol_tablet &new_symbol_table = load_java_class(
24+
"ClassWithClassAnnotation", "./java_bytecode/convert_java_annotations");
25+
26+
THEN("The annotation should have the correct structure")
27+
{
28+
const symbolt &class_symbol =
29+
*new_symbol_table.lookup("java::ClassWithClassAnnotation");
30+
const std::vector<java_annotationt> &java_annotations =
31+
to_annotated_type(class_symbol.type).get_annotations();
32+
java_bytecode_parse_treet::annotationst annotations;
33+
convert_java_annotations(java_annotations, annotations);
34+
REQUIRE(annotations.size() == 1);
35+
const auto &annotation = annotations.front();
36+
const auto &identifier =
37+
to_symbol_type(annotation.type.subtype()).get_identifier();
38+
REQUIRE(id2string(identifier) == "java::MyClassAnnotation");
39+
const auto &element_value_pair = annotation.element_value_pairs.front();
40+
const auto &element_name = element_value_pair.element_name;
41+
REQUIRE(id2string(element_name) == "value");
42+
const auto &expr = element_value_pair.value;
43+
const auto comp_expr = from_integer(6, java_int_type());
44+
REQUIRE(expr == comp_expr);
45+
}
46+
}
47+
WHEN("Parsing a class with a method-level annotation")
48+
{
49+
const symbol_tablet &new_symbol_table = load_java_class(
50+
"ClassWithMethodAnnotation",
51+
"./java_bytecode/convert_java_annotations");
52+
53+
THEN("The annotation should have the correct structure")
54+
{
55+
const symbolt &method_symbol = *new_symbol_table.lookup(
56+
"java::ClassWithMethodAnnotation.myMethod:()V");
57+
const std::vector<java_annotationt> &java_annotations =
58+
to_annotated_type(method_symbol.type).get_annotations();
59+
java_bytecode_parse_treet::annotationst annotations;
60+
convert_java_annotations(java_annotations, annotations);
61+
REQUIRE(annotations.size() == 1);
62+
const auto &annotation = annotations.front();
63+
const auto &identifier =
64+
to_symbol_type(annotation.type.subtype()).get_identifier();
65+
REQUIRE(id2string(identifier) == "java::MyMethodAnnotation");
66+
const auto &element_value_pair = annotation.element_value_pairs.front();
67+
const auto &element_name = element_value_pair.element_name;
68+
REQUIRE(id2string(element_name) == "methodValue");
69+
const auto &expr = element_value_pair.value;
70+
const auto &comp_expr = from_integer(11, java_int_type());
71+
REQUIRE(expr == comp_expr);
72+
}
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)