mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-14 16:09:26 +00:00
fix: reject incomplete Objective-C enum macro parses
Validate both complete argument spans and reject unsupported body children instead of emitting partial enum graphs. AI-Assistance: OpenAI Codex
This commit is contained in:
1 parent
d6a74da475
commit
7c09b4d360
2 files changed
+40
No files matched your search
@@ -322,6 +322,19 @@ def extract_objc(path: Path) -> dict:
|
||||
"identifier", "type_identifier"
|
||||
):
|
||||
continue
|
||||
# Valid headers also have grammar ERROR wrappers. Check complete
|
||||
# argument spans rather than ignoring extra tokens inside them.
|
||||
underlying_type = outer_types[0]
|
||||
if any(token.is_missing for token in tokens) or any(
|
||||
opening.end_byte <= token.start_byte < comma.start_byte
|
||||
and not (underlying_type.start_byte <= token.start_byte
|
||||
and token.end_byte <= underlying_type.end_byte)
|
||||
or comma.end_byte <= token.start_byte < closing.start_byte
|
||||
and not (names[0].start_byte <= token.start_byte
|
||||
and token.end_byte <= names[0].end_byte)
|
||||
for token in tokens
|
||||
):
|
||||
continue
|
||||
|
||||
following = [token for token in source_leaves
|
||||
if token.start_byte >= macro.end_byte]
|
||||
@@ -363,6 +376,11 @@ def extract_objc(path: Path) -> dict:
|
||||
or body.has_error or body.start_byte != len(prefix)
|
||||
or body.end_byte != len(prefix) + len(body_bytes)):
|
||||
continue
|
||||
# Conditional members need preprocessor handling. Do not emit a
|
||||
# partial enum when a clean body contains unsupported child nodes.
|
||||
if any(child.type not in {"{", "}", ",", "comment", "enumerator"}
|
||||
for child in body.children):
|
||||
continue
|
||||
|
||||
members: list[tuple[str, int]] = []
|
||||
previous_member_end = None
|
||||
|
||||
@@ -210,3 +210,25 @@ def test_objc_macro_enums_preserve_siblings_and_unrelated_parser_errors(tmp_path
|
||||
("Direction", "North"), ("Direction", "South"),
|
||||
("Kind", "First"), ("Kind", "Second"), ("Mask", "Enabled"),
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"declaration",
|
||||
[
|
||||
"typedef NS_ENUM(NSInteger = 1, Broken) { Bad };",
|
||||
"typedef NS_ENUM(NSInteger, *Broken) { Bad };",
|
||||
"typedef NS_ENUM(NSInteger, Broken[2]) { Bad };",
|
||||
"typedef NS_OPTIONS(NSUInteger, Broken) {\n"
|
||||
"#ifdef FEATURE\n Bad = 1 << 0,\n#endif\n Other = 1 << 1,\n};",
|
||||
],
|
||||
)
|
||||
def test_objc_macro_enum_unsupported_parts_do_not_emit_partial_enums(tmp_path, declaration):
|
||||
source = tmp_path / "Partial.h"
|
||||
source.write_text(
|
||||
"#import <Foundation/Foundation.h>\n" + declaration + "\n"
|
||||
"typedef NS_ENUM(NSInteger, Good) { Kept };\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
result = extract([source], cache_root=tmp_path)
|
||||
assert {n["label"] for n in result["nodes"]}.isdisjoint({"Broken", "Bad", "Other"})
|
||||
assert _edge_labels(result, "case_of") == {("Good", "Kept")}
|
||||
Reference in new issue
Block a user