Skip to content

Instantly share code, notes, and snippets.

@mulle-nat
Created September 21, 2024 23:15
Show Gist options
  • Save mulle-nat/c3ce96f5a8cbb4dd52030a7ffc1884ad to your computer and use it in GitHub Desktop.
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
#!/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