diff --git a/JsonGenerator/source/header_loader.py b/JsonGenerator/source/header_loader.py index 17b15cd..7e0500e 100644 --- a/JsonGenerator/source/header_loader.py +++ b/JsonGenerator/source/header_loader.py @@ -66,6 +66,8 @@ def _EvaluateRpcFormat(obj): return rpc_format + log.Info("Parsing interface %s in file %s" % (face.obj.full_name, file)) + schema = OrderedDict() methods = OrderedDict() properties = OrderedDict() @@ -84,12 +86,29 @@ def _EvaluateRpcFormat(obj): verify = face.obj.is_json or face.obj.is_event + _case_format = face.obj.meta.text if face.obj.meta.text else "lower" + + def compute_name(obj, relay = None): + if not relay: + relay = obj + + _default_name = relay.name if _case_format == "keep" else relay.name.lower() + + if obj.meta.text == _default_name: + log.WarnLine(method, "'%s': overriden name is same as default ('%s')" % (obj.meta.text, _default_name)) + + _name = obj.meta.text if obj.meta.text else _default_name + + return (_name) + schema["@interfaceonly"] = True schema["configuration"] = { "nodefault" : True } info = dict() info["format"] = rpc_format.value + log.Info("JSON-RPC format is %s" % rpc_format.value) + if not face.obj.parent.full_name.endswith(ns): info["namespace"] = face.obj.parent.name[1:] if (face.obj.parent.name[0] == "I" and face.obj.parent.name[1].isupper()) else face.obj.parent.name @@ -110,6 +129,11 @@ def _EvaluateRpcFormat(obj): info["title"] = info["class"] + " API" info["description"] = info["class"] + " JSON-RPC interface" + + if _case_format == "keep": + info["legacy"] = True # suppress case warnings + log.Info("@text:keep is used!") + schema["info"] = info clash_msg = "JSON-RPC name clash detected" @@ -217,7 +241,10 @@ def ConvertType(var): #if autos != 0 and (autos != len(cppType.items)): # raise CppParseError(var, "enumerator values in an enum must all be explicit or all be implied") - enum_spec = { "enum": [e.meta.text if e.meta.text else e.name.replace("_"," ").title().replace(" ","") for e in cppType.items], "scoped": var_type.Type().scoped } + if _case_format == "keep": + enum_spec = { "enum": [e.meta.text if e.meta.text else e.name for e in cppType.items] } + else: + enum_spec = { "enum": [e.meta.text if e.meta.text else e.name.replace("_"," ").title().replace(" ","") for e in cppType.items] } enum_spec["ids"] = [e.name for e in cppType.items] enum_spec["hint"] = var.type.Type().name @@ -250,7 +277,7 @@ def GenerateObject(ctype, was_typdef): required = [] for p in kind.vars: - name = p.meta.text if p.meta.text else p.name.lower() + name = compute_name(p) if isinstance(p.type, list): raise CppParseError(p, "%s: undefined type" % " ".join(p.type)) @@ -368,7 +395,7 @@ def BuildParameters(vars, rpc_format, is_property=False, test=False): elif not var.meta.output: log.WarnLine(var, "'%s': non-const parameter marked with @in tag (forgot 'const'?)" % var.name) - var_name = "value" if is_property else (var.meta.text if var.meta.text else var.name.lower()) + var_name = "value" if (is_property and _case_format == "lower") else compute_name(var) if var_name.startswith("__unnamed") and not test: raise CppParseError(var, "unnamed parameter, can't deduce parameter name (*1)") @@ -426,7 +453,7 @@ def BuildResult(vars, is_property=False): if var_type.IsConst(): raise CppParseError(var, "parameter marked with @out tag must not be const") - var_name = "value" if is_property else (var.meta.text if var.meta.text else var.name.lower()) + var_name = "value" if (is_property and _case_format == "lower") else compute_name(var) if var_name.startswith("__unnamed"): raise CppParseError(var, "unnamed parameter, can't deduce parameter name (*2)") @@ -470,9 +497,6 @@ def BuildResult(vars, is_property=False): continue - if method.retval.meta.text == method.name.lower(): - log.WarnLine(method, "'%s': overriden method name is same as default ('%s')" % (method.name, method.retval.meta.text)) - # Copy over @text tag to the other method of a property if method.retval.meta.text and method.retval.meta.is_property: for mm in face.obj.methods: @@ -487,7 +511,7 @@ def BuildResult(vars, is_property=False): mm.retval.meta.alt = method.retval.meta.alt break - method_name = method.retval.meta.text if method.retval.meta.text else method.name.lower() + method_name = compute_name(method.retval, method) if method.retval.meta.alt == method_name: log.WarnLine(method, "%s': alternative name is same as original name ('%s')" % (method.name, method.retval.meta.text)) @@ -546,8 +570,7 @@ def BuildResult(vars, is_property=False): obj["index"] = BuildIndex(method.vars[0]) if obj["index"]: - obj["index"]["name"] = method.vars[0].name - + obj["index"]["name"] = (method.vars[0].name if _case_format == "keep" else method.vars[0].name.capitalize()) if "enum" in obj["index"]: obj["index"]["example"] = obj["index"]["enum"][0] @@ -782,10 +805,7 @@ def BuildResult(vars, is_property=False): if params: obj["params"] = params - if method.retval.meta.text == method.name.lower(): - log.WarnLine(method, "'%s': overriden notification name is same as default ('%s')" % (method.name, method.retval.meta.text)) - - method_name = method.retval.meta.text if method.retval.meta.text else method.name.lower() + method_name = compute_name(method.retval, method) if method.parent.is_event: # excludes .json inlcusion of C++ headers for mm in events: diff --git a/ProxyStubGenerator/CppParser.py b/ProxyStubGenerator/CppParser.py index cc7da1e..64e9f66 100755 --- a/ProxyStubGenerator/CppParser.py +++ b/ProxyStubGenerator/CppParser.py @@ -58,7 +58,7 @@ def ASSERT_ISVALID(token): def ASSERT_ISEXPECTED(token, list): if token not in list: - raise ParserError("unexpected identifier: '" + token + "', expected one of " + str(list)) + raise ParserError("unexpected identifier: '" + str(token) + "', expected one of " + str(list)) # ------------------------------------------------------------------------- @@ -1547,7 +1547,7 @@ def __Tokenize(contents,log = None): else: continue - def __ParseParameterValue(string, tag, mandatory = True, append = True): + def __ParseParameterValue(string, tag, mandatory=True, append=True, relay=None): formula = (r"(\"[^\"]+\")" r"|(\'[^\']+\')" r"|(\*/)|(::)|(==)|(!=)|(>=)|(<=)|(&&)|(\|\|)" @@ -1556,7 +1556,7 @@ def __ParseParameterValue(string, tag, mandatory = True, append = True): r"|([\r\n\t ])") if append: - tagtokens.append(tag.upper()) + tagtokens.append(relay.upper() if relay else tag.upper()) length_str = string[string.index(tag) + len(tag):] length_tokens = [s.strip() for s in re.split(formula, length_str, flags=re.MULTILINE) if isinstance(s, str) and len(s.strip())] @@ -1693,7 +1693,9 @@ def _find(word, string): tagtokens.append(__ParseParameterValue(token, "@alt:obsolete")) if _find("@alt-obsolete", token): tagtokens.append(__ParseParameterValue(token, "@alt-obsolete")) - if _find("@text", token): + if _find("@text:keep", token): + tagtokens.append(__ParseParameterValue(token, "@text", True, True, "@text-global")) + elif _find("@text", token): tagtokens.append(__ParseParameterValue(token, "@text")) if _find("@length", token): tagtokens.append(__ParseParameterValue(token, "@length")) @@ -1846,6 +1848,7 @@ def Parse(contents,log = None): compliant_next = False iterator_next = False sourcelocation_next = False + text_next = None in_typedef = False @@ -1894,6 +1897,11 @@ def Parse(contents,log = None): json_next = False tokens[i] = ";" i += 1 + elif tokens[i] == "@TEXT-GLOBAL": + text_next = tokens[i + 1][0] + tokens[i] = ";" + tokens[i+1] = ";" + i += 2 elif tokens[i] == "@EXTENDED": extended_next = True tokens[i] = ";" @@ -1933,6 +1941,7 @@ def Parse(contents,log = None): compliant_next = False iterator_next = False sourcelocation_next = False + text_next = None in_typedef = False tokens[i] = ";" i += 1 @@ -2078,6 +2087,9 @@ def Parse(contents,log = None): raise ParserError("@compliant and @uncompliant used together") if exclude_next: raise ParserError("@json:omit is invalid here (applies to methods only)") + if text_next: + new_class.meta.text = text_next + text_next = None json_next = False json_version = "" diff --git a/ProxyStubGenerator/StubGenerator.py b/ProxyStubGenerator/StubGenerator.py index d9dda5c..3a1d79f 100755 --- a/ProxyStubGenerator/StubGenerator.py +++ b/ProxyStubGenerator/StubGenerator.py @@ -2136,21 +2136,24 @@ def GenerateIdentification(name): print(" @length:void - length is the size of one element") print("") print("JSON-RPC-related parameters:") - print(" @json - takes a C++ class in for JSON-RPC generation") + print(" @json [version] - takes a C++ class in for JSON-RPC generation (with optional version specification)") print(" @json:omit - leaves out a method, property or notification from a class intended for JSON-RPC generation") print(" @compliant - tags a class to be generated in JSON-RPC compliant format (default)") print(" @uncompliant:extended - tags a class to be generated in the obsolete 'extended' format") print(" @uncompliant:collapsed - tags a class to be generated in the obsolete 'collapsed' format") + print(" @text:keep - keeps original C++ names for all JSON names in an interface") print(" @event - takes a class in to be generated as an JSON-RPC notification") - print(" @property - tags C++ method to be generated as a JSON-RPC property") print(" @iterator - tags a C++ class to be generated as an JSON-RPC interator") + print(" @property - tags C++ method to be generated as a JSON-RPC property") + print(" @lookup [prefix] - use the method as a lookup function to import another C++ interface by an instance ID (with optional prefix override)") + print(" @statuslistener - emits registration/unregistration status listeners for an event") print(" @bitmask - indicates that enumerator lists should be packed into into a bit mask") print(" @index - indicates that a parameter in a JSON-RPC property or notification is an index") print(" @opaque - indicates that a string parameter is an opaque JSON object") print(" @extract - indicates that that if only one element is present in the array it shall be taken out of it") print(" @optional - indicates that a parameter, struct member or property index is optional") print(" @prefix {name} - prefixes all JSON-RPC methods, properties and notifications names in an interface with a string") - print(" @text {name} - sets a different name for a parameter, enumerator, struct or JSON-RPC method, property or notification") + print(" @text {name} - sets a different name for a parameter, enumerator, struct or JSON-RPC method, struct members, property or notification") print(" @alt {name} - provides an alternative name a JSON-RPC method or property can by called by") print(" (for a notification it provides an additional name to send out)") print(" @alt:deprecated {name} - provides an alternative deprecated name a JSON-RPC method can by called by") @@ -2164,7 +2167,7 @@ def GenerateIdentification(name): print(" @details {desc} - sets a detailed description for a JSON-RPC method, property or notification") print(" @param {name} {desc} - sets a description for a parameter of a JSON-RPC method or notification") print(" @retval {desc} - sets a description for a return value of a JSON-RPC method") - print(" @end - indicates end of the enumerator list (don't document further)") + print(" @end - indicates end of the enumerator list (meaning don't document further)") print("") print("Tags shall be placed inside C++ comments.") sys.exit()