From 377cb993dc5c39f448b630b0f8a795b1c075fa26 Mon Sep 17 00:00:00 2001 From: anjiaqi Date: Tue, 27 May 2025 17:26:17 +0800 Subject: [PATCH 1/5] check api consistency --- ets2panda/BUILD.gn | 9 ++ ets2panda/CMakeLists.txt | 12 ++ ets2panda/scripts/check_api_consistency.py | 125 +++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 ets2panda/scripts/check_api_consistency.py diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 63d89774f9..51699805b1 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -31,6 +31,10 @@ config("libes2panda_public_config") { ] } +action("check_api_consistency") { + script = "./scripts/check_api_consistency.py" +} + libes2panda_sources = [ "ast_verifier/ASTVerifier.cpp", "ast_verifier/helpers.cpp", @@ -490,6 +494,7 @@ libes2panda_sources = [ "util/path.cpp", "util/plugin.cpp", "util/ustring.cpp", + "test/utils/panda_executable_path_getter.cpp", "varbinder/ASBinder.cpp", "varbinder/ETSBinder.cpp", "varbinder/JSBinder.cpp", @@ -770,6 +775,8 @@ HEADERS_TO_BE_PARSED = [ "es2panda.h", "ast_verifier/ASTVerifier.h", "util/importPathManager.h", + "util/path.h", + "util/arktsconfig.h" ] ES2PANDA_API_GENERATED = [ @@ -1037,6 +1044,8 @@ ES2PANDA_API_GENERATED = [ "$LIBGEN_DIR/gen/headers/parser/program/program.yaml", "$LIBGEN_DIR/gen/headers/ast_verifier/ASTVerifier.yaml", "$LIBGEN_DIR/gen/headers/util/importPathManager.yaml", + "$LIBGEN_DIR/gen/headers/util/path.yaml", + "$LIBGEN_DIR/gen/headers/util/arktsconfig.yaml" ] ES2PANDA_API = [ diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 5747b4a45f..7b6756dddc 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -187,6 +187,16 @@ panda_gen( DESTINATION ${GENERATED_DIR} ) +find_package(Python3 REQUIRED) +execute_process( + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/check_api_consistency.py + RESULT_VARIABLE result + OUTPUT_VARIABLE output +) +if(NOT result EQUAL 0) + message(FATAL_ERROR "Python script execution failed: ${output}") +endif() + set(ES2PANDA_LIB_SRC ast_verifier/ASTVerifier.cpp ast_verifier/helpers.cpp @@ -642,6 +652,7 @@ set(ES2PANDA_LIB_SRC util/helpers.cpp util/importPathManager.cpp util/path.cpp + util/plugin.cpp util/ustring.cpp test/utils/panda_executable_path_getter.cpp evaluate/debugInfoDeserialization/debugInfoDeserializer.cpp @@ -728,6 +739,7 @@ if(PANDA_TARGET_LINUX OR PANDA_TARGET_WINDOWS) add_subdirectory(${ES2PANDA_NAPI_LIB_DIR}) endif() + if(PANDA_WITH_TESTS) add_subdirectory(test) endif() diff --git a/ets2panda/scripts/check_api_consistency.py b/ets2panda/scripts/check_api_consistency.py new file mode 100644 index 0000000000..65936aee87 --- /dev/null +++ b/ets2panda/scripts/check_api_consistency.py @@ -0,0 +1,125 @@ +import os +import re +import fnmatch +from pathlib import Path + +def parse_cmake_file_list(text, patterns): + file_list = [] + file_dict = {} + for match in re.finditer(r'([^\'"]*\.[a-zA-Z]+)', text): + filename = match.group(0) + filename = filename.split('\n') + + for file in filename: + if(file.endswith(patterns)): + file_list.append(file.strip().split('/')[-1]) + file_dict[file.strip().split('/')[-1]] = file.strip() + return file_list, file_dict + +def parse_gn_file_list(text, patterns): + file_list = [] + file_dict = {} + for match in re.finditer(r'[\"]([^\'"]*\.[a-zA-Z]+)[\"]', text): + filename = match.group(1) + if any(fnmatch.fnmatch(filename, pat) for pat in patterns): + file_list.append(os.path.basename(filename)) + file_dict[os.path.basename(filename)] = filename + return file_list, file_dict + +def parse_cmake(file_path): + patterns = ('.cpp') + sources = [] + sources_dict = {} + + with open(file_path, 'r') as f: + content = f.read() + for match in re.finditer(r'set\s*\(\s*\w+\s+(.*?)\s*\)', content, re.DOTALL): + files, files_dict = parse_cmake_file_list(match.group(1), patterns) + for file in files: + if file.endswith('.cpp'): + sources.append(file) + sources_dict[file] = files_dict[file] + return sources, sources_dict + +def parse_public_cmake(file_path): + patterns = ('.h', '.yaml') + headers, yamls = [], [] + headers_dict, yamls_dict = {}, {} + + with open(file_path, 'r') as f: + content = f.read() + for match in re.finditer(r'set\s*\(\s*\w+\s+(.*?)\s*\)', content, re.DOTALL): + files, files_dict = parse_cmake_file_list(match.group(1), patterns) + for file in files: + if file.endswith('.h'): + headers.append(file) + headers_dict[file] = files_dict[file] + elif file.endswith('.yaml'): + yamls.append(file) + yamls_dict[file] = files_dict[file] + return headers, yamls, headers_dict, yamls_dict + +def parse_gn(file_path): + patterns = ['*.cpp', '*.h', '*.yaml'] + sources, headers, yamls = [], [], [] + sources_dict, headers_dict, yamls_dict = {}, {}, {} + + with open(file_path, 'r') as f: + content = f.read() + for match in re.finditer(r'(libes2panda_sources|HEADERS_TO_BE_PARSED|ES2PANDA_API_GENERATED|ES2PANDA_API|generated_headers)\s*=\s*\[(.*?)\]', content, re.DOTALL): + files, files_dict = parse_gn_file_list(match.group(2), patterns) + for file in files: + if file.endswith('.cpp'): + sources.append(file) + sources_dict[file] = files_dict[file] + elif file.endswith('.h'): + headers.append(file) + headers_dict[file] = files_dict[file] + elif file.endswith('.yaml'): + yamls.append(file) + yamls_dict[file] = files_dict[file] + return sources, sources_dict, headers, headers_dict, yamls, yamls_dict + +def compare_file_lists(cmake_files, cmake_files_dict, gn_files, gn_files_dict, file_type): + cmake_set = set(cmake_files) + gn_set = set(gn_files) + + only_in_cmake = cmake_set - gn_set + only_in_gn = gn_set - cmake_set + + if only_in_cmake: + only_in_cmake_path = [] + for file in only_in_cmake: + only_in_cmake_path.append(cmake_files_dict[file]) + print(f"{file_type} only exist in CMake file:", sorted(only_in_cmake_path)) + if only_in_gn: + only_in_gn_path = [] + for file in only_in_gn: + only_in_gn_path.append(gn_files_dict[file]) + print(f"{file_type} only exist in GN file:", sorted(only_in_gn_path)) + + return len(only_in_cmake) == 0 and len(only_in_gn) == 0 + +def main(): + current_dir = os.path.dirname(os.path.abspath(__file__)) + cmake_dir = os.path.join(current_dir, '../../../tools/es2panda/CMakeLists.txt') + public_cmake_dir = os.path.join(cmake_dir, '../public/CMakeLists.txt') + cmake_src, cmake_src_dict = parse_cmake(os.path.abspath(cmake_dir)) + cmake_hdr, cmake_yaml, cmake_hdr_dict, cmake_yaml_dict = parse_public_cmake(os.path.abspath(public_cmake_dir)) + + gn_dir = os.path.join(current_dir, '../../../tools/es2panda/BUILD.gn') + gn_src, gn_src_dict, gn_hdr, gn_hdr_dict, gn_yaml, gn_yaml_dict = parse_gn(os.path.abspath(gn_dir)) + + src_consistent = compare_file_lists(cmake_src, cmake_src_dict, gn_src, gn_src_dict, "source file(.cpp)") + hdr_consistent = compare_file_lists(cmake_hdr, cmake_hdr_dict, gn_hdr, gn_hdr_dict, "header file(.h)") + yaml_consistent = compare_file_lists(cmake_yaml, cmake_yaml_dict, gn_yaml, gn_yaml_dict, "YAML file(.yaml)") + + if src_consistent and hdr_consistent and yaml_consistent: + print("all file types are identical beetween CMake and GN") + return 0 + else: + print("Warning! inconsistent file found beetween CMake and GN") + return 1 + +if __name__ == "__main__": + exit(main()) \ No newline at end of file -- Gitee From 43e54c8b97879a1985ac3b426dc6a2775b1ae918 Mon Sep 17 00:00:00 2001 From: anjiaqi Date: Tue, 27 May 2025 19:13:38 +0800 Subject: [PATCH 2/5] modified BUILD.gn --- ets2panda/BUILD.gn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 51699805b1..b116f3e1e2 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -31,8 +31,8 @@ config("libes2panda_public_config") { ] } -action("check_api_consistency") { - script = "./scripts/check_api_consistency.py" +action("check_build_system_consistency") { + script = "./scripts/check_build_system_consistency.py" } libes2panda_sources = [ -- Gitee From 8b4c2d767348e2a707c5925effd7b41bc995a8d0 Mon Sep 17 00:00:00 2001 From: anjiaqi Date: Tue, 27 May 2025 19:14:14 +0800 Subject: [PATCH 3/5] modified CMakeList.txt --- ets2panda/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 7b6756dddc..7fb91b9fd4 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -189,7 +189,7 @@ panda_gen( find_package(Python3 REQUIRED) execute_process( - COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/check_api_consistency.py + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/check_build_system_consistency.py RESULT_VARIABLE result OUTPUT_VARIABLE output ) -- Gitee From 31a8cf7ad53169c811a93d3b03bbc98d10a26072 Mon Sep 17 00:00:00 2001 From: anjiaqi Date: Tue, 27 May 2025 19:15:00 +0800 Subject: [PATCH 4/5] rename check_api_consistency.py to check_build_system_consistency.py --- .../scripts/check_build_system_consistency.py | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 ets2panda/scripts/check_build_system_consistency.py diff --git a/ets2panda/scripts/check_build_system_consistency.py b/ets2panda/scripts/check_build_system_consistency.py new file mode 100644 index 0000000000..8a40c7e72a --- /dev/null +++ b/ets2panda/scripts/check_build_system_consistency.py @@ -0,0 +1,125 @@ +import os +import re +import fnmatch +from pathlib import Path + +def parse_cmake_file_list(text, patterns): + file_list = [] + file_dict = {} + for match in re.finditer(r'([^\'"]*\.[a-zA-Z]+)', text): + filename = match.group(0) + filename = filename.split('\n') + + for file in filename: + if(file.endswith(patterns)): + file_list.append(file.strip().split('/')[-1]) + file_dict[file.strip().split('/')[-1]] = file.strip() + return file_list, file_dict + +def parse_gn_file_list(text, patterns): + file_list = [] + file_dict = {} + for match in re.finditer(r'[\"]([^\'"]*\.[a-zA-Z]+)[\"]', text): + filename = match.group(1) + if any(fnmatch.fnmatch(filename, pat) for pat in patterns): + file_list.append(os.path.basename(filename)) + file_dict[os.path.basename(filename)] = filename + return file_list, file_dict + +def parse_cmake(file_path): + patterns = ('.cpp') + sources = [] + sources_dict = {} + + with open(file_path, 'r') as f: + content = f.read() + for match in re.finditer(r'set\s*\(\s*\w+\s+(.*?)\s*\)', content, re.DOTALL): + files, files_dict = parse_cmake_file_list(match.group(1), patterns) + for file in files: + if file.endswith('.cpp'): + sources.append(file) + sources_dict[file] = files_dict[file] + return sources, sources_dict + +def parse_public_cmake(file_path): + patterns = ('.h', '.yaml') + headers, yamls = [], [] + headers_dict, yamls_dict = {}, {} + + with open(file_path, 'r') as f: + content = f.read() + for match in re.finditer(r'set\s*\(\s*\w+\s+(.*?)\s*\)', content, re.DOTALL): + files, files_dict = parse_cmake_file_list(match.group(1), patterns) + for file in files: + if file.endswith('.h'): + headers.append(file) + headers_dict[file] = files_dict[file] + elif file.endswith('.yaml'): + yamls.append(file) + yamls_dict[file] = files_dict[file] + return headers, yamls, headers_dict, yamls_dict + +def parse_gn(file_path): + patterns = ['*.cpp', '*.h', '*.yaml'] + sources, headers, yamls = [], [], [] + sources_dict, headers_dict, yamls_dict = {}, {}, {} + + with open(file_path, 'r') as f: + content = f.read() + for match in re.finditer(r'(libes2panda_sources|HEADERS_TO_BE_PARSED|ES2PANDA_API_GENERATED|ES2PANDA_API|generated_headers)\s*=\s*\[(.*?)\]', content, re.DOTALL): + files, files_dict = parse_gn_file_list(match.group(2), patterns) + for file in files: + if file.endswith('.cpp'): + sources.append(file) + sources_dict[file] = files_dict[file] + elif file.endswith('.h'): + headers.append(file) + headers_dict[file] = files_dict[file] + elif file.endswith('.yaml'): + yamls.append(file) + yamls_dict[file] = files_dict[file] + return sources, sources_dict, headers, headers_dict, yamls, yamls_dict + +def compare_file_lists(cmake_files, cmake_files_dict, gn_files, gn_files_dict, file_type): + cmake_set = set(cmake_files) + gn_set = set(gn_files) + + only_in_cmake = cmake_set - gn_set + only_in_gn = gn_set - cmake_set + + if only_in_cmake: + only_in_cmake_path = [] + for file in only_in_cmake: + only_in_cmake_path.append(cmake_files_dict[file]) + print(f"{file_type} only exist in CMake file:", sorted(only_in_cmake_path)) + if only_in_gn: + only_in_gn_path = [] + for file in only_in_gn: + only_in_gn_path.append(gn_files_dict[file]) + print(f"{file_type} only exist in GN file:", sorted(only_in_gn_path)) + + return len(only_in_cmake) == 0 and len(only_in_gn) == 0 + +def main(): + current_dir = os.path.dirname(os.path.abspath(__file__)) + cmake_dir = os.path.join(current_dir, '../../../tools/es2panda/CMakeLists.txt') + public_cmake_dir = os.path.join(cmake_dir, '../public/CMakeLists.txt') + cmake_src, cmake_src_dict = parse_cmake(os.path.abspath(cmake_dir)) + cmake_hdr, cmake_yaml, cmake_hdr_dict, cmake_yaml_dict = parse_public_cmake(os.path.abspath(public_cmake_dir)) + + gn_dir = os.path.join(current_dir, '../../../tools/es2panda/BUILD.gn') + gn_src, gn_src_dict, gn_hdr, gn_hdr_dict, gn_yaml, gn_yaml_dict = parse_gn(os.path.abspath(gn_dir)) + + src_consistent = compare_file_lists(cmake_src, cmake_src_dict, gn_src, gn_src_dict, "source file(.cpp)") + hdr_consistent = compare_file_lists(cmake_hdr, cmake_hdr_dict, gn_hdr, gn_hdr_dict, "header file(.h)") + yaml_consistent = compare_file_lists(cmake_yaml, cmake_yaml_dict, gn_yaml, gn_yaml_dict, "YAML file(.yaml)") + + if src_consistent and hdr_consistent and yaml_consistent: + print("all file types are consistent beetween CMake and GN") + return 0 + else: + print("Warning! inconsistent file found beetween CMake and GN") + return 1 + +if __name__ == "__main__": + exit(main()) \ No newline at end of file -- Gitee From 83fb077367613a031f2f4754e7d5095ecc42134c Mon Sep 17 00:00:00 2001 From: anjiaqi Date: Tue, 27 May 2025 19:15:28 +0800 Subject: [PATCH 5/5] delete check_api_consistency.py --- ets2panda/scripts/check_api_consistency.py | 125 --------------------- 1 file changed, 125 deletions(-) delete mode 100644 ets2panda/scripts/check_api_consistency.py diff --git a/ets2panda/scripts/check_api_consistency.py b/ets2panda/scripts/check_api_consistency.py deleted file mode 100644 index 65936aee87..0000000000 --- a/ets2panda/scripts/check_api_consistency.py +++ /dev/null @@ -1,125 +0,0 @@ -import os -import re -import fnmatch -from pathlib import Path - -def parse_cmake_file_list(text, patterns): - file_list = [] - file_dict = {} - for match in re.finditer(r'([^\'"]*\.[a-zA-Z]+)', text): - filename = match.group(0) - filename = filename.split('\n') - - for file in filename: - if(file.endswith(patterns)): - file_list.append(file.strip().split('/')[-1]) - file_dict[file.strip().split('/')[-1]] = file.strip() - return file_list, file_dict - -def parse_gn_file_list(text, patterns): - file_list = [] - file_dict = {} - for match in re.finditer(r'[\"]([^\'"]*\.[a-zA-Z]+)[\"]', text): - filename = match.group(1) - if any(fnmatch.fnmatch(filename, pat) for pat in patterns): - file_list.append(os.path.basename(filename)) - file_dict[os.path.basename(filename)] = filename - return file_list, file_dict - -def parse_cmake(file_path): - patterns = ('.cpp') - sources = [] - sources_dict = {} - - with open(file_path, 'r') as f: - content = f.read() - for match in re.finditer(r'set\s*\(\s*\w+\s+(.*?)\s*\)', content, re.DOTALL): - files, files_dict = parse_cmake_file_list(match.group(1), patterns) - for file in files: - if file.endswith('.cpp'): - sources.append(file) - sources_dict[file] = files_dict[file] - return sources, sources_dict - -def parse_public_cmake(file_path): - patterns = ('.h', '.yaml') - headers, yamls = [], [] - headers_dict, yamls_dict = {}, {} - - with open(file_path, 'r') as f: - content = f.read() - for match in re.finditer(r'set\s*\(\s*\w+\s+(.*?)\s*\)', content, re.DOTALL): - files, files_dict = parse_cmake_file_list(match.group(1), patterns) - for file in files: - if file.endswith('.h'): - headers.append(file) - headers_dict[file] = files_dict[file] - elif file.endswith('.yaml'): - yamls.append(file) - yamls_dict[file] = files_dict[file] - return headers, yamls, headers_dict, yamls_dict - -def parse_gn(file_path): - patterns = ['*.cpp', '*.h', '*.yaml'] - sources, headers, yamls = [], [], [] - sources_dict, headers_dict, yamls_dict = {}, {}, {} - - with open(file_path, 'r') as f: - content = f.read() - for match in re.finditer(r'(libes2panda_sources|HEADERS_TO_BE_PARSED|ES2PANDA_API_GENERATED|ES2PANDA_API|generated_headers)\s*=\s*\[(.*?)\]', content, re.DOTALL): - files, files_dict = parse_gn_file_list(match.group(2), patterns) - for file in files: - if file.endswith('.cpp'): - sources.append(file) - sources_dict[file] = files_dict[file] - elif file.endswith('.h'): - headers.append(file) - headers_dict[file] = files_dict[file] - elif file.endswith('.yaml'): - yamls.append(file) - yamls_dict[file] = files_dict[file] - return sources, sources_dict, headers, headers_dict, yamls, yamls_dict - -def compare_file_lists(cmake_files, cmake_files_dict, gn_files, gn_files_dict, file_type): - cmake_set = set(cmake_files) - gn_set = set(gn_files) - - only_in_cmake = cmake_set - gn_set - only_in_gn = gn_set - cmake_set - - if only_in_cmake: - only_in_cmake_path = [] - for file in only_in_cmake: - only_in_cmake_path.append(cmake_files_dict[file]) - print(f"{file_type} only exist in CMake file:", sorted(only_in_cmake_path)) - if only_in_gn: - only_in_gn_path = [] - for file in only_in_gn: - only_in_gn_path.append(gn_files_dict[file]) - print(f"{file_type} only exist in GN file:", sorted(only_in_gn_path)) - - return len(only_in_cmake) == 0 and len(only_in_gn) == 0 - -def main(): - current_dir = os.path.dirname(os.path.abspath(__file__)) - cmake_dir = os.path.join(current_dir, '../../../tools/es2panda/CMakeLists.txt') - public_cmake_dir = os.path.join(cmake_dir, '../public/CMakeLists.txt') - cmake_src, cmake_src_dict = parse_cmake(os.path.abspath(cmake_dir)) - cmake_hdr, cmake_yaml, cmake_hdr_dict, cmake_yaml_dict = parse_public_cmake(os.path.abspath(public_cmake_dir)) - - gn_dir = os.path.join(current_dir, '../../../tools/es2panda/BUILD.gn') - gn_src, gn_src_dict, gn_hdr, gn_hdr_dict, gn_yaml, gn_yaml_dict = parse_gn(os.path.abspath(gn_dir)) - - src_consistent = compare_file_lists(cmake_src, cmake_src_dict, gn_src, gn_src_dict, "source file(.cpp)") - hdr_consistent = compare_file_lists(cmake_hdr, cmake_hdr_dict, gn_hdr, gn_hdr_dict, "header file(.h)") - yaml_consistent = compare_file_lists(cmake_yaml, cmake_yaml_dict, gn_yaml, gn_yaml_dict, "YAML file(.yaml)") - - if src_consistent and hdr_consistent and yaml_consistent: - print("all file types are identical beetween CMake and GN") - return 0 - else: - print("Warning! inconsistent file found beetween CMake and GN") - return 1 - -if __name__ == "__main__": - exit(main()) \ No newline at end of file -- Gitee