in source/Frame.cpp [248:391]
Frame Frame::from_json(const Json::Value& value, Context& context) {
JsonValidation::validate_object(value);
const Kind* kind = Kind::from_json(value, context);
auto callee_port = AccessPath(Root(Root::Kind::Leaf));
if (value.isMember("callee_port")) {
JsonValidation::string(value, /* field */ "callee_port");
callee_port = AccessPath::from_json(value["callee_port"]);
}
const Method* callee = nullptr;
if (value.isMember("callee")) {
callee = Method::from_json(
JsonValidation::object_or_string(value, /* field */ "callee"), context);
}
const Position* call_position = nullptr;
if (value.isMember("call_position")) {
call_position = Position::from_json(
JsonValidation::object(value, /* field */ "call_position"), context);
}
int distance = 0;
if (value.isMember("distance")) {
distance = JsonValidation::integer(value, /* field */ "distance");
}
JsonValidation::null_or_array(value, /* field */ "origins");
auto origins = MethodSet::from_json(value["origins"], context);
JsonValidation::null_or_array(value, /* field */ "field_origins");
auto field_origins = FieldSet::from_json(value["field_origins"], context);
// Inferred may_features and always_features. Technically, user-specified
// features should go under "user_features", but this gives a way to override
// that behavior and specify "may/always" features. Note that local inferred
// features cannot be user-specified.
auto inferred_features = FeatureMayAlwaysSet::from_json(value, context);
// User specified always-features.
FeatureSet user_features;
if (value.isMember("features")) {
JsonValidation::null_or_array(value, /* field */ "features");
user_features = FeatureSet::from_json(value["features"], context);
}
RootSetAbstractDomain via_type_of_ports;
if (value.isMember("via_type_of")) {
for (const auto& root :
JsonValidation::null_or_array(value, /* field */ "via_type_of")) {
via_type_of_ports.add(Root::from_json(root));
}
}
RootSetAbstractDomain via_value_of_ports;
if (value.isMember("via_value_of")) {
for (const auto& root :
JsonValidation::null_or_array(value, /* field */ "via_value_of")) {
via_value_of_ports.add(Root::from_json(root));
}
}
LocalPositionSet local_positions;
if (value.isMember("local_positions")) {
JsonValidation::null_or_array(value, /* field */ "local_positions");
local_positions =
LocalPositionSet::from_json(value["local_positions"], context);
}
CanonicalNameSetAbstractDomain canonical_names;
if (value.isMember("canonical_names")) {
for (const auto& canonical_name :
JsonValidation::nonempty_array(value, /* field */ "canonical_names")) {
canonical_names.add(CanonicalName::from_json(canonical_name));
}
}
if (canonical_names.is_value() && !canonical_names.elements().empty()) {
callee_port = validate_and_infer_crtex_callee_port(
value, callee_port, canonical_names, via_type_of_ports);
} else if (
callee_port.root().is_anchor() || callee_port.root().is_producer()) {
throw JsonValidationError(
value,
/* field */ std::nullopt,
"canonical_names to be specified with `Anchor` or `Producer` callee_port.");
}
// Sanity checks.
if (callee == nullptr) {
if (!callee_port.root().is_leaf_port()) {
throw JsonValidationError(
value,
/* field */ "callee_port",
/* expected */ "`Leaf`, `Anchor` or `Producer`");
} else if (call_position != nullptr) {
throw JsonValidationError(
value,
/* field */ "call_position",
/* expected */ "unspecified position for leaf taint");
} else if (distance != 0) {
throw JsonValidationError(
value,
/* field */ "distance",
/* expected */ "a value of 0");
}
} else {
if (callee_port.root().is_leaf_port()) {
throw JsonValidationError(
value,
/* field */ "callee_port",
/* expected */ "`Argument(x)` or `Return`");
} else if (call_position == nullptr) {
throw JsonValidationError(
value,
/* field */ "call_position",
/* expected */ "non-null position");
} else if (distance == 0) {
throw JsonValidationError(
value,
/* field */ "distance",
/* expected */ "non-zero distance");
}
}
return Frame(
kind,
std::move(callee_port),
callee,
/* field_callee */ nullptr, // A field callee can never be set from a json
// model generator
call_position,
distance,
std::move(origins),
std::move(field_origins),
std::move(inferred_features),
/* locally_inferred_features */ FeatureMayAlwaysSet::bottom(),
std::move(user_features),
std::move(via_type_of_ports),
std::move(via_value_of_ports),
std::move(local_positions),
std::move(canonical_names));
}