Skip to content

Commit a36793a

Browse files
committed
Fix JSON parsing of source_locationt
The JSON output of a `source_locationt` is different from generic `irept`. Also, make `try_get_{bool,string}` publicly available for subsequent re-use.
1 parent 29051b4 commit a36793a

File tree

3 files changed

+130
-21
lines changed

3 files changed

+130
-21
lines changed

src/goto-programs/show_symbol_table.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ static void show_symbol_table_json_ui(
177177

178178
{"type", irep_converter.convert_from_irep(symbol.type)},
179179
{"value", irep_converter.convert_from_irep(symbol.value)},
180-
{"location", irep_converter.convert_from_irep(symbol.location)},
180+
{"location", json(symbol.location)},
181181

182182
{"isType", jsont::json_boolean(symbol.is_type)},
183183
{"isMacro", jsont::json_boolean(symbol.is_macro)},

src/json-symtab-language/json_symbol.cpp

Lines changed: 112 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,34 +11,129 @@ Author: Chris Smowton, [email protected]
1111
#include <util/exception_utils.h>
1212
#include <util/expr.h>
1313
#include <util/json_irep.h>
14-
#include <util/source_location.h>
1514
#include <util/type.h>
1615

17-
/// Return string value for a given key if present in the json object.
18-
/// \param in: The json object that is getting fetched as a string.
19-
/// \param key: The key for the json value to be fetched.
20-
/// \return A string value for the corresponding key.
21-
static const std::string &
22-
try_get_string(const jsont &in, const std::string &key)
16+
const std::string &try_get_string(const jsont &in, const std::string &key)
2317
{
2418
if(!in.is_string())
25-
throw deserialization_exceptiont(
26-
"symbol_from_json: expected string for key '" + key + "'");
19+
{
20+
throw deserialization_exceptiont{"expected string for key '" + key + "'"};
21+
}
2722
return in.value;
2823
}
2924

30-
/// Return boolean value for a given key if present in the json object.
31-
/// \param in: The json object that is getting fetched as a boolean.
32-
/// \param key: The key for the json value to be fetched.
33-
/// \return A boolean value for the corresponding key.
34-
static bool try_get_bool(const jsont &in, const std::string &key)
25+
bool try_get_bool(const jsont &in, const std::string &key)
3526
{
3627
if(!(in.is_true() || in.is_false()))
37-
throw deserialization_exceptiont(
38-
"symbol_from_json: expected bool for key '" + key + "'");
28+
{
29+
throw deserialization_exceptiont{"expected bool for key '" + key + "'"};
30+
}
3931
return in.is_true();
4032
}
4133

34+
source_locationt try_get_source_location(const jsont &json)
35+
{
36+
if(!json.is_object())
37+
{
38+
throw deserialization_exceptiont{
39+
"source location should be encoded as an object"};
40+
}
41+
42+
const json_objectt &json_object = to_json_object(json);
43+
44+
if(json_object.size() == 0)
45+
{
46+
return source_locationt::nil();
47+
}
48+
else if(json_object.find("id") != json_object.end())
49+
{
50+
json_irept json2irep{true};
51+
irept irep = json2irep.convert_from_json(json_object);
52+
return static_cast<source_locationt &>(irep);
53+
}
54+
55+
source_locationt result;
56+
for(const auto &kv : json_object)
57+
{
58+
if(kv.first == "workingDirectory")
59+
{
60+
result.set_working_directory(
61+
try_get_string(kv.second, "workingDirectory"));
62+
}
63+
else if(kv.first == "file")
64+
{
65+
result.set_file(try_get_string(kv.second, "file"));
66+
}
67+
else if(kv.first == "line")
68+
{
69+
result.set_line(try_get_string(kv.second, "line"));
70+
}
71+
else if(kv.first == "column")
72+
{
73+
result.set_column(try_get_string(kv.second, "column"));
74+
}
75+
else if(kv.first == "function")
76+
{
77+
result.set_function(try_get_string(kv.second, "function"));
78+
}
79+
else if(kv.first == "bytecodeIndex")
80+
{
81+
result.set_java_bytecode_index(
82+
try_get_string(kv.second, "bytecodeIndex"));
83+
}
84+
else if(kv.first == "propertyId")
85+
{
86+
result.set_property_id(try_get_string(kv.second, "propertyId"));
87+
}
88+
else if(kv.first == "propertyClass")
89+
{
90+
result.set_property_class(try_get_string(kv.second, "propertyClass"));
91+
}
92+
else if(kv.first == "comment")
93+
{
94+
result.set_comment(try_get_string(kv.second, "comment"));
95+
}
96+
else if(kv.first == "caseNumber")
97+
{
98+
result.set_case_number(try_get_string(kv.second, "caseNumber"));
99+
}
100+
else if(kv.first == "basicBlockSourceLines")
101+
{
102+
json_irept json2irep{true};
103+
irept irep = json2irep.convert_from_json(kv.second);
104+
result.set_basic_block_source_lines(irep);
105+
}
106+
else if(kv.first == "propertyFatal")
107+
{
108+
result.property_fatal(try_get_bool(kv.second, "propertyFatal"));
109+
}
110+
else if(kv.first == "hide")
111+
{
112+
if(try_get_bool(kv.second, "hide"))
113+
result.set_hide();
114+
}
115+
else if(kv.first == "pragma")
116+
{
117+
if(!kv.second.is_array())
118+
throw deserialization_exceptiont{"pragmas must be an array"};
119+
120+
for(const auto &pragma : to_json_array(kv.second))
121+
{
122+
if(!pragma.is_string())
123+
throw deserialization_exceptiont{"pragma must be a string"};
124+
result.add_pragma(pragma.value);
125+
}
126+
}
127+
else
128+
{
129+
throw deserialization_exceptiont{
130+
"try_get_source_location: unexpected key '" + kv.first + "'"};
131+
}
132+
}
133+
134+
return result;
135+
}
136+
42137
/// Deserialise a json object to a symbolt.
43138
/// \param in: The json object that is getting fetched as an object.
44139
/// \return A symbolt representing the json object.
@@ -61,10 +156,7 @@ symbolt symbol_from_json(const jsont &in)
61156
result.value = static_cast<exprt &>(irep);
62157
}
63158
else if(kv.first == "location")
64-
{
65-
irept irep = json2irep.convert_from_json(kv.second);
66-
result.location = static_cast<source_locationt &>(irep);
67-
}
159+
result.location = try_get_source_location(kv.second);
68160
else if(kv.first == "name")
69161
result.name = try_get_string(kv.second, "name");
70162
else if(kv.first == "module")

src/json-symtab-language/json_symbol.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,21 @@ class jsont;
1515

1616
symbolt symbol_from_json(const jsont &);
1717

18+
/// Return string value for a given key if present in the json object.
19+
/// \param in: The json object that is getting fetched as a string.
20+
/// \param key: The key for the json value to be fetched.
21+
/// \return A string value for the corresponding key.
22+
const std::string &try_get_string(const jsont &in, const std::string &key);
23+
24+
/// Return boolean value for a given key if present in the json object.
25+
/// \param in: The json object that is getting fetched as a boolean.
26+
/// \param key: The key for the json value to be fetched.
27+
/// \return A boolean value for the corresponding key.
28+
bool try_get_bool(const jsont &in, const std::string &key);
29+
30+
/// Return a `source_locationt` from the given JSON object.
31+
/// \param json: The json object that represents a source location.
32+
/// \return A source location, unless an exception was thrown before.
33+
source_locationt try_get_source_location(const jsont &json);
34+
1835
#endif

0 commit comments

Comments
 (0)