Skip to content

Commit

Permalink
[JsonGen] Add @default tag for OptionalType (#100)
Browse files Browse the repository at this point in the history
* [JsonGen] Add @default tag for OptionalType

* fix wrong parameter dereference

* Change error code

---------

Co-authored-by: Pierre Wielders <[email protected]>
  • Loading branch information
sebaszm and pwielders authored Jun 25, 2024
1 parent 246cd14 commit b31323f
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 30 deletions.
12 changes: 6 additions & 6 deletions JsonGenerator/source/class_emitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def __EmitAssignment(json_obj, other, optional_type=False, conv=False):
optional_or_opaque = IsObjectOptionalOrOpaque(prop)
_prop_name = prop.actual_name if conv else prop.cpp_name

if prop.optional:
if (prop.optional and not prop.default_value):
emit.Line("if (%s.%s.IsSet() == true) {" % (other, prop.actual_name))
emit.Indent()

Expand All @@ -249,7 +249,7 @@ def __EmitAssignment(json_obj, other, optional_type=False, conv=False):

emit.Line("%s = %s.%s;" % (prop.cpp_name, other, _prop_name + prop.convert_rhs))

if prop.optional or optional_or_opaque:
if (prop.optional and not prop.default_value) or optional_or_opaque:
emit.Unindent()
emit.Line("}")

Expand All @@ -275,8 +275,8 @@ def __EmitCtor(json_obj, no_init_code=False, copy_ctor=False, conversion_ctor=Fa
for prop in json_obj.properties:
if copy_ctor:
emit.Line(", %s(%s.%s)" % (prop.cpp_name, _other, prop.cpp_name))
elif (prop.cpp_def_value != '""') and (prop.cpp_def_value != ""):
emit.Line(", %s(%s)" % (prop.cpp_name, prop.cpp_def_value))
elif prop.default_value:
emit.Line(", %s(%s)" % (prop.cpp_name, prop.default_value))

emit.Unindent()
emit.Line("{")
Expand Down Expand Up @@ -335,14 +335,14 @@ def _EmitConversionOperator(json_obj):
emit.Line("%s _value{};" % (json_obj.cpp_native_type))

for prop in json_obj.properties:
if prop.optional:
if (prop.optional and not prop.default_value):
emit.Line("if (%s.IsSet() == true) {" % (prop.cpp_name))
emit.Indent()

conv = (prop.convert if prop.convert else "%s = %s")
emit.Line((conv + ";") % ( ("_value." + prop.actual_name), prop.cpp_name))

if prop.optional:
if (prop.optional and not prop.default_value):
emit.Unindent()
emit.Line("}")

Expand Down
2 changes: 1 addition & 1 deletion JsonGenerator/source/documentation_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def _TableObj(name, obj, parentName="", parent=None, prefix="", parentOptional=F
if row.endswith('.'):
row = row[:-1]

if optional and "default" in obj:
if "default" in obj:
row += " (default: " + (italics("%s") % str(obj["default"]) + ")")

if obj["type"] == "number":
Expand Down
37 changes: 37 additions & 0 deletions JsonGenerator/source/header_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,34 @@ def GenerateObject(ctype, was_typdef):
result[1]["@optionaltype"] = True
result[1]["@originaltype"] = StripFrameworkNamespace(cppType.optional)

if var.meta.default:
try:
if result[1].get("float"):
result[1]["@default"] = float(var.meta.default[0])
result[1]["default"] = float(var.meta.default[0])
elif result[0] == "integer":
result[1]["@default"] = int(var.meta.default[0])
result[1]["default"] = int(var.meta.default[0])
elif result[0] == "boolean":
result[1]["@default"] = "true" if var.meta.default[0] == "true" else "false"
result[1]["default"] = (var.meta.default[0] == "true")
elif result[1].get("enum"):
if var.meta.default[0] not in result[1].get("ids"):
raise CppParseError(var, "default value for enumerator type is not an enum value")
else:
result[1]["@default"] = result[1]["@originaltype"]+ "::" + str(var.meta.default[0])
result[1]["default"] = str(var.meta.default[0])
else:
if not var.meta.default[0].startswith('"') or not var.meta.default[0].endswith('"'):
raise CppParseError(var, "default value for string type must be a quoted string literal %s" % result[1].get("type"))

result[1]["@default"] = '_T(' + str(var.meta.default[0]) + ')'
result[1]["default"] = str(var.meta.default[0])
except CppParseError as err:
raise err
except:
raise CppParseError(var, "OptionalType and default value type mismatch (expected %s, got '%s')" % (result[1].get("@originaltype"), var.meta.default[0]))

# All other types are not supported
else:
raise CppParseError(var, "unable to convert this C++ type to JSON type: %s" % cppType.type)
Expand All @@ -342,6 +370,14 @@ def GenerateObject(ctype, was_typdef):
if var.meta.range:
result[1]["range"] = var.meta.range

if var.meta.default[0]:
if result[0] == "integer" or result[0] == "number":
if float(var.meta.default[0]) < var.meta.range[0] or (float(var.meta.default[0]) > var.meta.range[1]):
raise CppParseError(var, "default value is outside of restrict range")
elif result[0] == "string" and not result[1].get("enum"):
if len(var.meta.default[0]) - 2 < var.meta.range[0] or (len(var.meta.default[0]) -2 > var.meta.range[1]):
raise CppParseError(var, "default value string length is outside of restrict range")

return result

def ExtractExample(var):
Expand Down Expand Up @@ -374,6 +410,7 @@ def ConvertParameter(var):
else:
properties["description"] = var.meta.brief.strip()


return properties

def EventParameters(vars):
Expand Down
4 changes: 2 additions & 2 deletions JsonGenerator/source/json_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ def is_void(self):
return (self.cpp_type == "void")

@property
def cpp_def_value(self): # Value to initialize with in C++
return ""
def default_value(self): # Value to initialize with in C++
return self.schema.get("@default")

@property
def root(self):
Expand Down
33 changes: 19 additions & 14 deletions JsonGenerator/source/rpc_emitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,27 +101,27 @@ def EmitEvent(emit, root, event, params_type, legacy = False):

if params.properties and params.do_create:
for p in params.properties:
if p.optional and (params_type == "native"):
if p.optional and (params_type == "native") and not p.default_value:
emit.Line("if (%s.IsSet() == true) {" % (p.local_name))
emit.Indent()

emit.Line("%s.%s = %s;" % (names.params, p.cpp_name, p.local_name))
if p.schema.get("opaque"):
emit.Line("%s.%s.SetQuoted(false);" % (names.params, p.cpp_name))

if p.optional and (params_type == "native"):
if p.optional and (params_type == "native") and not p.default_value:
emit.Unindent()
emit.Line("}")
else:
if params.optional and (params_type == "native"):
if params.optional and (params_type == "native") and not params.default_value:
emit.Line("if (%s.IsSet() == true) {" % (params.local_name))
emit.Indent()

emit.Line("%s = %s;" % (names.params, params.local_name))
if params.schema.get("opaque"):
emit.Line("%s.SetQuoted(false);" % names.params)

if params.optional and (params_type == "native"):
if params.optional and (params_type == "native") and not params.default_value:
emit.Unindent()
emit.Line("}")

Expand Down Expand Up @@ -535,7 +535,7 @@ def _Invoke(params, response, parent="", repsonse_parent="", const_cast=False):
emit.Line()
emit.Line("if (%s) {" % restrictions.join())
emit.Indent()
emit.Line("%s = %s;" % (error_code.temp_name, CoreError("invalid_range")))
emit.Line("%s = %s;" % (error_code.temp_name, CoreError("bad_request")))
emit.Unindent()
emit.Line("} else {")
emit.Indent()
Expand Down Expand Up @@ -607,7 +607,7 @@ def _Invoke(params, response, parent="", repsonse_parent="", const_cast=False):
emit.Line("}")
emit.Line("else {")
emit.Indent()
emit.Line("%s = %s;" % (error_code.temp_name, CoreError("invalid_range")))
emit.Line("%s = %s;" % (error_code.temp_name, CoreError("bad_request")))
emit.Unindent()
emit.Line("}")

Expand All @@ -619,10 +619,11 @@ def _Invoke(params, response, parent="", repsonse_parent="", const_cast=False):

# Special case for iterators
elif isinstance(arg, JsonArray):
if arg.optional:
raise RPCEmitterError("OptionalType iterators are not supported, use @optional tag (see %s)" % arg.cpp_native_type_opt)

if arg.iterator:
if arg.optional:
raise RPCEmitterError("OptionalType iterators are not supported, use @optional tag (see %s)" % arg.cpp_native_type_opt)

face_name = "_" + arg.items.local_name.capitalize() + "IteratorType"
emit.Line("using %s = %s;" % (face_name, arg.iterator))

Expand Down Expand Up @@ -678,13 +679,17 @@ def _Invoke(params, response, parent="", repsonse_parent="", const_cast=False):
else:
initializer = (("(%s)" if isinstance(arg, JsonObject) else "{%s}") % cpp_name) if is_readable and not arg.convert else "{}"

if arg.optional and is_readable:
# Have to go through assignment...
if arg.optional and is_readable and (arg.default_value == None or not parent):
emit.Line("%s %s{};" % (arg.cpp_native_type_opt, arg.temp_name))
emit.Line("if (%s.IsSet() == true) {" % (cpp_name))
emit.Indent()
emit.Line("%s = %s;" % (arg.temp_name, cpp_name))
emit.Unindent()
if arg.default_value:
emit.Line("} else {")
emit.Indent()
emit.Line("%s = %s;" % (arg.temp_name, arg.default_value))
emit.Unindent()
emit.Line("}")
emit.Line()
else:
Expand Down Expand Up @@ -759,7 +764,7 @@ def _Invoke(params, response, parent="", repsonse_parent="", const_cast=False):
emit.Line("}")
emit.Line("else {")
emit.Indent()
emit.Line("%s = %s;" % (error_code.temp_name, CoreError("unknown_key")))
emit.Line("%s = %s;" % (error_code.temp_name, CoreError("bad_request")))
emit.Unindent()
emit.Line("}")

Expand Down Expand Up @@ -964,7 +969,7 @@ def _Invoke(params, response, parent="", repsonse_parent="", const_cast=False):
emit.Line("if ((%s.empty() == true) || (Core::FromString(%s, %s) == false)) {" % (index_name, index_name, index_name_converted))
emit.Indent()

emit.Line("%s = %s;" % (error_code.temp_name, CoreError("unknown_key")))
emit.Line("%s = %s;" % (error_code.temp_name, CoreError("bad_request")))

if is_read_write:
emit.Line("%s%s.Null(true);" % ("// " if isinstance(response, (JsonArray, JsonObject)) else "", response.local_name)) # FIXME
Expand All @@ -985,7 +990,7 @@ def _Invoke(params, response, parent="", repsonse_parent="", const_cast=False):
emit.Line("if (%s.IsSet() == false) {" % index_name_converted)
emit.Indent()

emit.Line("%s = %s;" % (error_code.temp_name, CoreError("unknown_key")))
emit.Line("%s = %s;" % (error_code.temp_name, CoreError("bad_request")))

if is_read_write:
emit.Line("%s%s.Null(true);" % ("// " if isinstance(response, (JsonArray, JsonObject)) else "", response.local_name)) # FIXME
Expand All @@ -1004,7 +1009,7 @@ def _Invoke(params, response, parent="", repsonse_parent="", const_cast=False):
emit.Line("if (%s.empty() == true) {" % index_name)
emit.Indent()

emit.Line("%s = %s;" % (error_code.temp_name, CoreError("unknown_key")))
emit.Line("%s = %s;" % (error_code.temp_name, CoreError("bad_request")))

if is_read_write:
emit.Line("%s%s.Null(true);" % ("// " if isinstance(response, (JsonArray, JsonObject)) else "", response.local_name)) # FIXME
Expand Down
20 changes: 13 additions & 7 deletions ProxyStubGenerator/CppParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,23 @@ def __init__(self):
self.details = ""
self.input = False
self.output = False
self.is_property = False
self.is_deprecated = False
self.is_obsolete = False
self.is_index = False
self.decorators = []
self.length = None
self.maxlength = None
self.interface = None
self.lookup = None
self.default = None
self.alt = None
self.alt_is_deprecated = None
self.alt_is_obsolete = None
self.text = None
self.range = []
self.decorators = []
self.param = OrderedDict()
self.retval = OrderedDict()
self.is_property = False
self.is_deprecated = False
self.is_obsolete = False
self.is_index = False
self.alt_is_deprecated = None
self.alt_is_obsolete = None

@property
def is_input(self):
Expand Down Expand Up @@ -385,6 +386,9 @@ def __init__(self, parent_block, parent, string, valid_specifiers, tags_allowed=
elif tag == "INTERFACE":
self.meta.interface = string[i + 1]
skip = 1
elif tag == "DEFAULT":
self.meta.default = string[i + 1]
skip = 1
elif tag == "OPAQUE":
self.meta.decorators.append("opaque")
elif tag == "OPTIONAL":
Expand Down Expand Up @@ -1721,6 +1725,8 @@ def _find(word, string):
tagtokens.append("@OPAQUE")
if _find("@optional", token):
tagtokens.append("@OPTIONAL")
if _find("@default", token):
tagtokens.append(__ParseParameterValue(token, "@default"))
if _find("@extract", token):
tagtokens.append("@EXTRACT")
if _find("@sourcelocation", token):
Expand Down

0 comments on commit b31323f

Please sign in to comment.