MCPcopy Create free account
hub / github.com/Graphify-Labs/graphify / extract_objc

Function extract_objc

graphify/extract.py:12406–12793  ·  view source on GitHub ↗

Extract interfaces, implementations, protocols, methods, and imports from .m/.mm/.h files.

(path: Path)

Source from the content-addressed store, hash-verified

12404
12405
12406def extract_objc(path: Path) -> dict:
12407 """Extract interfaces, implementations, protocols, methods, and imports from .m/.mm/.h files."""
12408 try:
12409 import tree_sitter_objc as tsobjc
12410 from tree_sitter import Language, Parser
12411 except ImportError:
12412 return {"nodes": [], "edges": [], "error": "tree_sitter_objc not installed"}
12413
12414 try:
12415 language = Language(tsobjc.language())
12416 parser = Parser(language)
12417 source = path.read_bytes()
12418 # tree-sitter-objc cannot expand these argument-less annotation macros (no
12419 # trailing ';'), and their presence before @interface makes the parser fail to
12420 # emit a class_interface node (#1475). Blank them to equal-length spaces so byte
12421 # offsets / line numbers are preserved and the interface parses.
12422 _OBJC_BLANK_MACROS = (b"NS_ASSUME_NONNULL_BEGIN", b"NS_ASSUME_NONNULL_END")
12423 for _m in _OBJC_BLANK_MACROS:
12424 source = source.replace(_m, b" " * len(_m))
12425 tree = parser.parse(source)
12426 root = tree.root_node
12427 except Exception as e:
12428 return {"nodes": [], "edges": [], "error": str(e)}
12429
12430 stem = _file_stem(path)
12431 str_path = str(path)
12432 nodes: list[dict] = []
12433 edges: list[dict] = []
12434 seen_ids: set[str] = set()
12435 method_bodies: list[tuple[str, Any, str]] = []
12436 # #1556: unresolved message sends saved for the cross-file ObjC resolver, plus a
12437 # per-file `var -> ClassName` table from `Foo *f = ...;` local declarations.
12438 raw_calls: list[dict] = []
12439 objc_type_table: dict[str, str] = {}
12440
12441 def add_node(nid: str, label: str, line: int) -> None:
12442 if nid not in seen_ids:
12443 seen_ids.add(nid)
12444 nodes.append({"id": nid, "label": label, "file_type": "code",
12445 "source_file": str_path, "source_location": f"L{line}"})
12446
12447 def add_edge(src: str, tgt: str, relation: str, line: int,
12448 confidence: str = "EXTRACTED", weight: float = 1.0,
12449 context: str | None = None) -> None:
12450 edge = {"source": src, "target": tgt, "relation": relation,
12451 "confidence": confidence, "source_file": str_path,
12452 "source_location": f"L{line}", "weight": weight}
12453 if context:
12454 edge["context"] = context
12455 edges.append(edge)
12456
12457 file_nid = _make_id(str(path))
12458 add_node(file_nid, path.name, 1)
12459
12460 def _read(node) -> str:
12461 return source[node.start_byte:node.end_byte].decode("utf-8", errors="replace")
12462
12463 def _get_name(node, field: str) -> str | None:

Calls 7

_file_stemFunction · 0.90
_make_idFunction · 0.90
_objc_local_var_typesFunction · 0.85
add_nodeFunction · 0.70
walkFunction · 0.70
walk_callsFunction · 0.70
getMethod · 0.45