optimize output information

Signed-off-by: bayanxing <bayanxing@kaihongdigi.com>
This commit is contained in:
bayanxing
2022-02-18 09:09:24 +08:00
parent 3abf43faee
commit a707b1bbf5
4 changed files with 199 additions and 81 deletions
+34 -13
View File
@@ -94,7 +94,7 @@ class HeaderParser:
def _checkout_function_pointer_param(self, params):
if params == '':
return []
tt = re.match("(typedef )* *\\w+ \\( \\* \\) \\(( .* )\\)", params)
tt = re.match(r"(typedef )* *\w+ \( \* \) \(( .* )\)", params)
if tt:
params = tt[2].strip() + ","
else:
@@ -105,7 +105,7 @@ class HeaderParser:
tt = re.match(" *(const )*(struct |enum |union )* *", params)
if tt: # 去掉结构类型头
params = params[tt.regs[0][1]:]
tt = re.match("((unsigned )*[a-zA-Z0-9_:]+( *\\** *\\**)) *", params)
tt = re.match(r"((unsigned )*[a-zA-Z0-9_:]+( *\** *\**)) *", params)
if tt:
param_type = params[tt.regs[1][0]:tt.regs[1][1]] # 参数类型
params = params[tt.regs[0][1]:]
@@ -150,11 +150,11 @@ class HeaderParser:
for value in enm["values"]:
v_value = value["value"]
if not isinstance(v_value, int):
tt = re.match("0x|0X|\\(|-", v_value)
tt = re.match(r"0x|0X|\(|-", v_value)
if tt:
errmsg = "unexpected '%s'" % tt[0]
v_value = v_value + " // " + errmsg
print("[Parser]: %s[line %d] " % (enm["filename"], enm["line_number"]), errmsg)
print("[HeaderParser]: %s[line %d] " % (enm["filename"], enm["line_number"]), errmsg)
enum_dict["members"].append({"name": value["name"], "value": v_value})
self._header_dict["enum"].append(enum_dict)
@@ -167,8 +167,11 @@ class HeaderParser:
union_dict["name"] = stack["name"].split(" ")[-1]
union_dict["type"] = "union"
union_dict["members"] = []
file_name = self._header_dict["path"] + "/" + self._header_dict["name"]
for mb in stack["members"]:
union_dict["members"].append({"name": mb["name"], "type": mb["type"]})
union_dict["members"].append({"file_name": file_name,
"line_number": mb["line_number"],
"name": mb["name"], "type": mb["type"]})
self._header_dict["union"].append(union_dict)
def _extract_struct(self, stack):
@@ -179,17 +182,26 @@ class HeaderParser:
if stack["declaration_method"] in ["struct", "class"]:
if len(stack["methods"]["public"]) == 0: # 不带函数
if not self._has_function_pointer(stack["properties"]["public"]): # 变量中没有函数指针
# print(cs["name"], "转换到struct")
struct_dict["name"] = stack["name"]
struct_dict["type"] = "struct"
struct_dict["members"] = []
file_name = self._header_dict["path"] + "/" + self._header_dict["name"]
for mb in stack["properties"]["public"]:
if "enum_type" in mb:
struct_dict["members"].append({"name": mb["name"], "type": mb["enum_type"]["name"]})
struct_dict["members"].append({"file_name": file_name,
"line_number": mb["line_number"],
"name": mb["name"],
"type": mb["enum_type"]["name"]})
elif mb["array"] == 1:
struct_dict["members"].append({"name": mb["name"], "type": mb["type"] + " *"})
struct_dict["members"].append({"file_name": file_name,
"line_number": mb["line_number"],
"name": mb["name"],
"type": mb["type"] + " *"})
else:
struct_dict["members"].append({"name": mb["name"], "type": mb["type"]})
struct_dict["members"].append({"file_name": file_name,
"line_number": mb["line_number"],
"name": mb["name"],
"type": mb["type"]})
self._header_dict["struct"].append(struct_dict)
def _extract_interface(self, stack):
@@ -200,10 +212,11 @@ class HeaderParser:
if stack["declaration_method"] in ["struct", "class"]:
# 带函数,或变量中包含函数指针
if len(stack["methods"]["public"]) > 0 or self._has_function_pointer(stack["properties"]["public"]):
# print(cs["name"], "转换到class")
interface_dict["name"] = stack["name"]
interface_dict["members"] = []
for mb in stack["methods"]["public"]:
if mb["name"] in (stack["name"], "DECLARE_INTERFACE_DESCRIPTOR"):
continue
params = []
for param in mb["parameters"]:
para_name = param["name"]
@@ -211,14 +224,22 @@ class HeaderParser:
para_name = "rand_name_%d" % self._rand_name_count
self._rand_name_count += 1
params.append({"name": para_name, "type": param["type"]})
interface_dict["members"].append({"name": mb["name"], "params": params})
interface_dict["members"].append({"name": mb["name"],
"params": params,
"file_name":
self._header_dict["path"] + "/" + self._header_dict["name"],
"line_number": mb["line_number"]})
for mb in stack["properties"]["public"]:
if mb["function_pointer"] > 0:
interface_dict["members"].append({"name": mb["name"],
"params": self._checkout_function_pointer_param(
mb["type"])})
"params": self._checkout_function_pointer_param(mb["type"]),
"file_name":
self._header_dict["path"] + "/" + self._header_dict[
"name"],
"line_number": mb["line_number"]})
self._header_dict["interface"].append(interface_dict)
def _extract_typedef(self, typedefs):
"""
Extract typedef from global typedefs
+23 -14
View File
@@ -118,7 +118,7 @@ class IDLGenerator:
def _generate_type(self, header):
if self._has_user_define_type(header):
self._install_package(header["path"])
self._install_import(header)
self._install_import(header, "/Types.idl")
self._install_enum(header["enum"])
self._install_stack(header["union"])
self._install_stack(header["struct"])
@@ -128,7 +128,7 @@ class IDLGenerator:
def _generate_interface(self, header):
for iface in header["interface"]:
self._install_package(header["path"])
self._install_import(header)
self._install_import(header, iface["name"])
self._install_interface(iface)
self._write_file(header["path"], iface["name"] + ".idl")
@@ -136,7 +136,7 @@ class IDLGenerator:
def _install_package(self, file_path):
self._idl += "package " + self._get_package(file_path) + ";\n\n"
def _install_import(self, header):
def _install_import(self, header, idl_file):
original_idl = self._idl
for file_name in header["import"]:
if file_name in self._parse_results:
@@ -151,6 +151,8 @@ class IDLGenerator:
self._idl += "import " + self._get_package(include_file['path']) + ".%s;\n" % cb["name"]
else:
self._idl += "// can't import %s\n" % file_name
print("[IDLGenerator]: %s[line ?] can't find %s"
% (os.path.normpath(header["path"] + "/" + header["name"]), file_name))
for cb in header['callback']:
self._idl += "import " + self._get_package(header['path']) + ".%s;\n" % cb["name"]
@@ -169,7 +171,11 @@ class IDLGenerator:
for stack in stacks:
self._idl += stack["type"] + " %s {\n" % stack["name"]
for member in stack["members"]:
self._idl += " %s %s;\n" % (self._swap_type_c2idl(member["type"]), member["name"])
param_type = self._swap_type_c2idl(member["type"])
if "unknown type" in param_type:
print("[IDLGenerator]: %s[line %d] %s" % (
os.path.normpath(member["file_name"]), member["line_number"], param_type))
self._idl += " %s %s;\n" % (param_type, member["name"])
self._idl += "};\n"
def _install_interface(self, iface):
@@ -180,15 +186,19 @@ class IDLGenerator:
self._install_function(iface["name"], member)
self._idl += "};\n"
def _install_function(self, iface_name, func):
self._idl += " %s(" % func["name"]
for i, param in enumerate(func["params"]):
tt = re.fullmatch("(enum)*(union)*(struct)* *%s *\\** * *\\**" % iface_name, param["type"])
def _install_function(self, iface_name, member):
self._idl += " %s(" % member["name"]
for i, param in enumerate(member["params"]):
tt = re.fullmatch(r"(enum)*(union)*(struct)* *%s *\** * *\**" % iface_name, param["type"])
if tt:
continue
param_type = self._swap_type_c2idl(param["type"])
if "unknown type" in param_type:
print("[IDLGenerator]: %s[line %d] %s" % (
os.path.normpath(member["file_name"]), member["line_number"], param_type))
self._idl += "%s %s %s," % (
'* *' in param["type"] and "[out]" or "[in]",
self._swap_type_c2idl(param["type"]),
param_type,
param["name"])
if self._idl.endswith(','):
self._idl = self._idl[:-1] + ");\n"
@@ -214,7 +224,7 @@ class IDLGenerator:
]
for cti in type_c2idl:
for ct in cti[0]:
tt = re.match("(const )* *%s *(\\**) *" % ct, c_type)
tt = re.match(r"(const )* *%s *(\**) *" % ct, c_type)
if tt:
idl_type = cti[1]
if c_type.count('*') == 1:
@@ -226,7 +236,7 @@ class IDLGenerator:
for type_name in self._key_list:
if "_ENUM_POINTER" in c_type:
c_type = c_type.replace("_ENUM_POINTER", " * ")
tt = re.fullmatch("(enum)*(union)*(struct)* *%s *\\** * *\\**" % type_name, c_type)
tt = re.fullmatch(r"(const )* *(enum)*(union)*(struct)* *%s *[*&]* * *[*&]*" % type_name, c_type)
if tt:
if len(self._key_list[type_name]) > 0:
idl_type = self._key_list[type_name] + ' ' + type_name
@@ -239,7 +249,7 @@ class IDLGenerator:
def _convert_typedef(self, c_type):
for type_name in self._typedef_list:
tt = re.match("(const )* *%s *(\\**) *" % type_name, c_type)
tt = re.match(r"(const )* *%s *\** *" % type_name, c_type)
if tt:
if self._typedef_list[type_name].count('*') == 1:
idl_type = self._typedef_list[type_name].split(' ')[0] + '[]'
@@ -280,14 +290,13 @@ class IDLGenerator:
return idl_type
idl_type = "/* unknown type: [%s] */" % c_type
print(">>>error:", idl_type)
return idl_type
def _write_file(self, file_path, file_name):
file = os.path.join(self._make_output_dir(file_path), file_name).replace('\\', '/')
with open(file, "w", encoding="utf8") as fp:
fp.write(self._idl)
print("[Generate]: ", file)
print("Generate: --------------------- %s ---------------------\n" % os.path.normpath(file))
self._idl = ""
@staticmethod
+120 -47
View File
@@ -134,8 +134,10 @@ class HeaderParserTestCase(unittest.TestCase):
self.assertSequenceEqual(parser._header_dict["union"], [{'name': 'SceneDesc',
'type': 'union',
'members': [
{'name': 'id', 'type': 'uint32_t'},
{'name': 'desc', 'type': 'const char *'}
{'file_name': '/', 'line_number': 3,
'name': 'id', 'type': 'uint32_t'},
{'file_name': '/', 'line_number': 4,
'name': 'desc', 'type': 'const char *'}
]}])
def test_extract_union_without_name(self):
@@ -156,14 +158,18 @@ class HeaderParserTestCase(unittest.TestCase):
self.assertSequenceEqual(parser._header_dict["union"], [{'name': '<anon-union-1>',
'type': 'union',
'members': [
{'name': 'id', 'type': 'uint32_t'},
{'name': 'desc', 'type': 'const char *'}
{'file_name': '/', 'line_number': 3,
'name': 'id', 'type': 'uint32_t'},
{'file_name': '/', 'line_number': 4,
'name': 'desc', 'type': 'const char *'}
]},
{'name': '<anon-union-2>',
'type': 'union',
'members': [
{'name': 'id2', 'type': 'uint32_t'},
{'name': 'desc2', 'type': 'const char *'}
{'file_name': '/', 'line_number': 7,
'name': 'id2', 'type': 'uint32_t'},
{'file_name': '/', 'line_number': 8,
'name': 'desc2', 'type': 'const char *'}
]}
])
@@ -182,17 +188,21 @@ class HeaderParserTestCase(unittest.TestCase):
self.assertSequenceEqual(parser._header_dict["union"], [{'name': 'SceneDesc',
'type': 'union',
'members': [
{'name': 'id', 'type': 'uint32_t'},
{'name': 'desc', 'type': 'const char *'}
{'file_name': '/', 'line_number': 4,
'name': 'id', 'type': 'uint32_t'},
{'file_name': '/', 'line_number': 5,
'name': 'desc', 'type': 'const char *'}
]}])
parser._extract_struct(hjson["classes"]["AudioSceneDescriptor"])
self.assertSequenceEqual(parser._header_dict["struct"], [{'name': 'AudioSceneDescriptor',
'type': 'struct',
'members': [
{'name': 'scene', 'type': 'SceneDesc'}
{'file_name': '/', 'line_number': 6,
'name': 'scene', 'type': 'SceneDesc'}
]}])
def test_extract_struct(self):
self.maxDiff = None
header_file = """
typedef struct {
bool succeed;
@@ -216,26 +226,40 @@ class HeaderParserTestCase(unittest.TestCase):
parser = HeaderParser()
hjson = json.loads(CppHeaderParser.CppHeader(header_file, "string").toJSON())
parser._extract_struct(hjson["classes"]["DevAbility"])
self.assertSequenceEqual(parser._header_dict["struct"], [{'name': 'DevAbility',
'type': 'struct',
'members': [
{'name': 'succeed', 'type': 'bool'},
{'name': 'end', 'type': 'int8_t'},
{'name': 'rate', 'type': 'float'},
{'name': 'rate2', 'type': 'double'},
{'name': 'desc', 'type': 'cstring'},
{'name': 'location', 'type': 'std::string'},
{'name': 'status', 'type': 'uint8_t'},
{'name': 'busType', 'type': 'uint16_t'},
{'name': 'num', 'type': 'int32_t'},
{'name': 'count', 'type': 'uint32_t'},
{'name': 'timestamp', 'type': 'uint64_t'},
{'name': 'path', 'type': 'void'},
{'name': 'chipInfo', 'type': 'char *'},
{'name': 'status', 'type': 'RetStatus'},
{'name': 'package', 'type': 'struct EvtPack'},
{'name': 'pkgPtr', 'type': 'struct EvtPack *'}
]}])
self.assertSequenceEqual(
parser._header_dict["struct"], [{'name': 'DevAbility',
'type': 'struct',
'members': [
{'file_name': '/', 'line_number': 3, 'name': 'succeed',
'type': 'bool'},
{'file_name': '/', 'line_number': 4, 'name': 'end', 'type': 'int8_t'},
{'file_name': '/', 'line_number': 5, 'name': 'rate', 'type': 'float'},
{'file_name': '/', 'line_number': 6, 'name': 'rate2',
'type': 'double'},
{'file_name': '/', 'line_number': 7, 'name': 'desc',
'type': 'cstring'},
{'file_name': '/', 'line_number': 8, 'name': 'location',
'type': 'std::string'},
{'file_name': '/', 'line_number': 9, 'name': 'status',
'type': 'uint8_t'},
{'file_name': '/', 'line_number': 10, 'name': 'busType',
'type': 'uint16_t'},
{'file_name': '/', 'line_number': 11, 'name': 'num',
'type': 'int32_t'},
{'file_name': '/', 'line_number': 12, 'name': 'count',
'type': 'uint32_t'},
{'file_name': '/', 'line_number': 13, 'name': 'timestamp',
'type': 'uint64_t'},
{'file_name': '/', 'line_number': 14, 'name': 'path', 'type': 'void'},
{'file_name': '/', 'line_number': 15, 'name': 'chipInfo',
'type': 'char *'},
{'file_name': '/', 'line_number': 16, 'name': 'status',
'type': 'RetStatus'},
{'file_name': '/', 'line_number': 17, 'name': 'package',
'type': 'struct EvtPack'},
{'file_name': '/', 'line_number': 18, 'name': 'pkgPtr',
'type': 'struct EvtPack *'}
]}])
def test_extract_struct_with_enum_pointer(self):
header_file = """
@@ -257,8 +281,10 @@ class HeaderParserTestCase(unittest.TestCase):
self.assertSequenceEqual(parser._header_dict["struct"], [{'name': 'DevAbility',
'type': 'struct',
'members': [
{'name': 'staPtr', 'type': 'Status_ENUM_POINTER'},
{'name': 'testPtr', 'type': 'Test_ENUM_POINTER'}
{'file_name': '/', 'line_number': 3,
'name': 'staPtr', 'type': 'Status_ENUM_POINTER'},
{'file_name': '/', 'line_number': 4,
'name': 'testPtr', 'type': 'Test_ENUM_POINTER'}
]}])
def test_extract_struct_with_macro(self):
@@ -286,7 +312,8 @@ class HeaderParserTestCase(unittest.TestCase):
self.assertSequenceEqual(parser._header_dict["struct"], [{'name': 'DevAbility',
'type': 'struct',
'members': [
{'name': 'absCode', 'type': 'unsigned long *'}
{'file_name': '/', 'line_number': 8,
'name': 'absCode', 'type': 'unsigned long *'}
]}])
def test_extract_struct_include_union_without_name(self):
@@ -304,14 +331,17 @@ class HeaderParserTestCase(unittest.TestCase):
self.assertSequenceEqual(parser._header_dict["union"], [{'name': '<anon-union-1>',
'type': 'union',
'members': [
{'name': 'id', 'type': 'uint32_t'},
{'name': 'desc', 'type': 'const char *'}
{'file_name': '/', 'line_number': 4,
'name': 'id', 'type': 'uint32_t'},
{'file_name': '/', 'line_number': 5,
'name': 'desc', 'type': 'const char *'}
]}])
parser._extract_struct(hjson["classes"]["AudioSceneDescriptor"])
self.assertSequenceEqual(parser._header_dict["struct"], [{'name': 'AudioSceneDescriptor',
'type': 'struct',
'members': [
{'name': '', 'type': '<anon-union-1>'}
{'file_name': '/', 'line_number': 6,
'name': '', 'type': '<anon-union-1>'}
]}])
def test_extract_interface_with_method(self):
@@ -328,13 +358,18 @@ class HeaderParserTestCase(unittest.TestCase):
'members': [
{'name': 'SetPowerStatus',
'params': [{'name': 'devIndex',
'type': 'uint32_t'}]},
'type': 'uint32_t'}],
'file_name': '/',
'line_number': 3},
{'name': 'RunExtraCommand',
'params': [{'name': 'rand_name_0',
'type': 'uint32_t'},
{'name': 'rand_name_1',
'type': 'InputExtraCmd *'}
]}]}])
],
'file_name': '/',
'line_number': 4
}]}])
def test_extract_interface_with_function_point(self):
header_file = """
@@ -352,28 +387,66 @@ class HeaderParserTestCase(unittest.TestCase):
'members': [
{'name': 'SetPowerStatus',
'params': [{'name': 'devIndex',
'type': 'uint32_t'}]},
'type': 'uint32_t'}],
'file_name': '/',
'line_number': 3
},
{'name': 'RunExtraCommand',
'params': [{'name': 'rand_name_0',
'type': 'uint32_t'},
{'name': 'rand_name_1',
'type': 'InputExtraCmd *'}
]},
],
'file_name': '/',
'line_number': 4
},
{'name': 'RunCapacitanceTest',
'params': [{'name': 'devIndex',
'type': 'uint32_t'},
{'name': 'testType',
'type': 'uint32_t'}
]}
],
'file_name': '/',
'line_number': 5
}
]}])
def test_extract_interface_callback(self):
# todo
pass
def test_extract_interface_with_function_pointer_and_properties(self):
# todo
pass
def test_extract_interface_for_class(self):
header_file = """
class ICameraDevice{
public:
DECLARE_INTERFACE_DESCRIPTOR(u"HDI.Camera.V1_0.Device");
virtual ~ICameraDevice() {}
virtual CamRetCode ICamera();
virtual CamRetCode GetEnabledResults(std::vector<MetaType> &results) = 0;
virtual CamRetCode SetResultMode(const CallbackMode &mode) = 0;
};
"""
parser = HeaderParser()
hjson = json.loads(CppHeaderParser.CppHeader(header_file, "string").toJSON())
parser._extract_interface(hjson["classes"]["ICameraDevice"])
self.assertSequenceEqual(parser._header_dict["interface"], [{'name': 'ICameraDevice',
'members': [
{'name': 'ICamera',
'params': [],
'file_name': '/',
'line_number': 6
},
{'name': 'GetEnabledResults',
'params': [{'name': 'results',
'type': 'std::vector<MetaType> &'}
],
'file_name': '/',
'line_number': 7
},
{'name': 'SetResultMode',
'params': [{'name': 'mode',
'type': 'const CallbackMode &'}
],
'file_name': '/',
'line_number': 8
}
]}])
def test_extract_typedef(self):
header_file = """
+22 -7
View File
@@ -48,7 +48,7 @@ class IDLGeneratorTestCase(unittest.TestCase):
}
}
header = generator._parse_results['audio_test.h']
generator._install_import(header)
generator._install_import(header, "test.h")
self.assertEqual(generator._idl, "import include.audio.AudioRender;\n\n")
def test_install_import_interfaces(self):
@@ -77,7 +77,7 @@ class IDLGeneratorTestCase(unittest.TestCase):
}
}
header = generator._parse_results['audio_test.h']
generator._install_import(header)
generator._install_import(header, "test.h")
self.assertEqual(generator._idl, "import include.audio.AudioRender;\n"
"import include.audio.adapter.AudioAdapter;\n\n")
@@ -103,7 +103,7 @@ class IDLGeneratorTestCase(unittest.TestCase):
}
}
header = generator._parse_results['audio_test.h']
generator._install_import(header)
generator._install_import(header, "test.h")
self.assertEqual(generator._idl, "import include.AudioInterfaceOne;\nimport include.AudioInterfaceTwo;\n\n")
def test_install_import_types(self):
@@ -125,7 +125,7 @@ class IDLGeneratorTestCase(unittest.TestCase):
}
}
header = generator._parse_results["audio_test.h"]
generator._install_import(header)
generator._install_import(header, "test.h")
self.assertEqual(generator._idl, "import include.Types;\n\n")
def test_install_import_merge_types(self):
@@ -154,7 +154,7 @@ class IDLGeneratorTestCase(unittest.TestCase):
}
}
header = generator._parse_results['audio_test.h']
generator._install_import(header)
generator._install_import(header, "test.h")
self.assertEqual(generator._idl, "import include.Types;\n\n")
def test_install_import_types_and_interfaces(self):
@@ -183,7 +183,7 @@ class IDLGeneratorTestCase(unittest.TestCase):
}
}
header = generator._parse_results['audio_test.h']
generator._install_import(header)
generator._install_import(header, "test.h")
self.assertEqual(generator._idl, "import include.Types;\nimport include.audio.adapter.AudioAdapter;\n\n")
def test_install_import_callback(self):
@@ -201,7 +201,7 @@ class IDLGeneratorTestCase(unittest.TestCase):
}
}
header = generator._parse_results['audio_test.h']
generator._install_import(header)
generator._install_import(header, "test.h")
self.assertEqual(generator._idl, "import include.audio.HotPlugCallback;\n"
"import include.audio.VBlankCallback;\n\n")
@@ -267,6 +267,21 @@ class IDLGeneratorTestCase(unittest.TestCase):
" RunExtra([in] struct InputControllerDesc desc);\n"
"};\n")
def test_install_interface_with_unknown_type(self):
header_file = """
typedef struct {
int32_t (*RunExtra)(struct InputControllerDesc desc);
} InputController;
"""
parser = HeaderParser()
hjson = json.loads(CppHeaderParser.CppHeader(header_file, "string").toJSON())
parser._extract_interface(hjson["classes"]["InputController"])
generator = IDLGenerator()
generator._install_interface(parser._header_dict["interface"][0])
self.assertEqual(generator._idl, "interface InputController {\n"
" RunExtra([in] /* unknown type: [InputControllerDesc] */ desc);\n"
"};\n")
def test_install_interface_callback(self):
header_file = """
struct IFooCallback {