Skip to content

Instantly share code, notes, and snippets.

@thesamprice
Created May 21, 2023 03:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thesamprice/d4a19102aa4fe11fb96a75df57b9fcfe to your computer and use it in GitHub Desktop.
Save thesamprice/d4a19102aa4fe11fb96a75df57b9fcfe to your computer and use it in GitHub Desktop.
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