Created
September 21, 2024 23:15
-
-
Save mulle-nat/c3ce96f5a8cbb4dd52030a7ffc1884ad to your computer and use it in GitHub Desktop.
Extract the names of protocols, classes, variables, methods of an Objective-C header
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
#!/usr/bin/env python3 | |
# sudo apt-get install libclang-dev python3-pip | |
# sudo pip3 install clang --break-system-packages | |
# sudo apt-get install -y libclang-17-dev | |
import sys | |
import clang.cindex | |
def parse_objc_header(file_path): | |
index = clang.cindex.Index.create() | |
translation_unit = index.parse(file_path, args=['-x', 'objective-c']) | |
def visit_children(cursor, depth=0): | |
for child in cursor.get_children(): | |
# print(f"{' ' * depth}DEBUG: {child.kind}: {child.spelling}") | |
if child.kind == clang.cindex.CursorKind.OBJC_INTERFACE_DECL: | |
print(f"class: {child.spelling}") | |
elif child.kind == clang.cindex.CursorKind.OBJC_PROTOCOL_DECL: | |
print(f"protocol: {child.spelling}") | |
elif child.kind == clang.cindex.CursorKind.OBJC_INSTANCE_METHOD_DECL: | |
print(f"method: {child.semantic_parent.spelling},{child.spelling}") | |
elif child.kind == clang.cindex.CursorKind.OBJC_CLASS_METHOD_DECL: | |
print(f"method: {child.semantic_parent.spelling},+{child.spelling}") | |
elif child.kind == clang.cindex.CursorKind.OBJC_PROPERTY_DECL: | |
print(f"property: {child.semantic_parent.spelling},{child.spelling}") | |
elif child.kind == clang.cindex.CursorKind.VAR_DECL: | |
if child.storage_class == clang.cindex.StorageClass.EXTERN: | |
print(f"extern: {child.spelling}") | |
else: | |
print(f"constant: {child.spelling}") | |
elif child.kind == clang.cindex.CursorKind.FUNCTION_DECL and child.spelling == "NS_ENUM": | |
enum_name = None | |
for param in child.get_children(): | |
if param.kind == clang.cindex.CursorKind.PARM_DECL and param.spelling != "NSInteger": | |
enum_name = param.spelling | |
break | |
if enum_name: | |
print(f"enum: {enum_name}") | |
# Now we need to find the compound statement containing the enum constants | |
for stmt in child.get_children(): | |
if stmt.kind == clang.cindex.CursorKind.COMPOUND_STMT: | |
for const in stmt.get_children(): | |
if const.kind == clang.cindex.CursorKind.ENUM_CONSTANT_DECL: | |
print(f"enumvalue: {enum_name},{const.spelling}") | |
visit_children(child, depth + 1) | |
visit_children(translation_unit.cursor) | |
if __name__ == "__main__": | |
if len(sys.argv) != 2: | |
print(f"Usage: {sys.argv[0]} <path_to_objc_header>") | |
sys.exit(1) | |
parse_objc_header(sys.argv[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment