Created
May 21, 2023 03:47
-
-
Save thesamprice/d4a19102aa4fe11fb96a75df57b9fcfe to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import clang.cindex | |
import collections | |
import os | |
import regex as re | |
import copy | |
filename = 'compile_commands.json' | |
with open(filename,'r') as fid: | |
compile_db = json.load(fid) | |
def fix_paths(json_data): | |
# iterate over arguments | |
for i, arg in enumerate(json_data['arguments']): | |
# if argument is an include path (-I) | |
if arg.startswith('-I'): | |
# split the argument into flag and path | |
flag, rel_path = arg.split('-', 1) | |
# create absolute path by joining the directory and the relative path | |
abs_path = os.path.abspath(os.path.join(json_data['directory'], rel_path)) | |
# replace the argument with the new absolute path argument | |
json_data['arguments'][i] = '-I' + flag + abs_path | |
# Also correcting the relative file path | |
json_data['file'] = os.path.abspath(os.path.join(json_data['directory'], json_data['file'])) | |
# Regex taken from | |
# https://github.com/llvm-mirror/clang-tools-extra/blob/master/clang-tidy/readability/IdentifierNamingCheck.cpp#L255 | |
is_aNy_CasE = re.compile("^.*$") | |
is_lower_case = re.compile("^[a-z][a-z0-9_]*$") | |
is_UPPER_CASE = re.compile("^[a-z][a-zA-Z0-9]*$") | |
is_camelBack = re.compile("^[A-Z][A-Z0-9_]*$") | |
is_CamelCase = re.compile("^[A-Z][a-zA-Z0-9]*$") | |
is_Camel_Snake_Case = re.compile("^[A-Z]([a-z0-9]*(_[A-Z])?)*") | |
is_camel_Snake_Back = re.compile("^[a-z]([a-z0-9]*(_[A-Z])?)*") | |
regex_map = { | |
"is_aNy_CasE ":is_aNy_CasE , | |
"is_lower_case ":is_lower_case , | |
"is_UPPER_CASE ":is_UPPER_CASE , | |
"is_camelBack ":is_camelBack , | |
"is_CamelCase ":is_CamelCase , | |
"is_Camel_Snake_Case":is_Camel_Snake_Case, | |
"is_camel_Snake_Back":is_camel_Snake_Back, | |
} | |
case_types = [ | |
{"name":"is_aNy_CasE ","count":0}, | |
{"name":"is_lower_case ","count":0}, | |
{"name":"is_UPPER_CASE ","count":0}, | |
{"name":"is_camelBack ","count":0}, | |
{"name":"is_CamelCase ","count":0}, | |
{"name":"is_Camel_Snake_Case","count":0}, | |
{"name":"is_camel_Snake_Back","count":0}, | |
] | |
files_parsed = [] | |
cursor_counts = {} | |
for kind in clang.cindex.CursorKind.get_all_kinds(): | |
if not kind.is_declaration(): | |
continue | |
cursor_counts[kind] = copy.deepcopy(case_types) | |
def count_cases(node, c_filename, basepath): | |
global cursor_counts, regex_map, files_parsed | |
""" Recursive function to traverse AST """ | |
if node.kind.is_declaration(): | |
counter = cursor_counts[node.kind] | |
name = node.spelling | |
for c in counter: | |
if regex_map[c["name"]].match(name): | |
c["count"] += 1 | |
# recurse for children of this node | |
for child in node.get_children(): | |
if child.location.file and base_path in child.location.file.name : | |
loc = f"{child.location.file.name}:{child.location.offset}" | |
if loc in files_parsed: | |
continue | |
files_parsed.append(loc) | |
count_cases(child,c_filename,basepath) | |
# Dictionary to hold case statistics | |
results = collections.defaultdict(int) | |
base_path = os.getcwd() | |
for json_data in compile_db: | |
fix_paths(json_data) | |
c_filename = json_data['file'] | |
print(c_filename) | |
index = clang.cindex.Index.create() | |
tu = index.parse(c_filename) #, args=json_data['arguments']) | |
count_cases(tu.cursor,c_filename,base_path) | |
print(cursor_counts) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment