mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-13 07:29:33 +00:00
fix(cpp): extract union specifiers as class-like type nodes
(cherry picked from commit b6c9c34359)
This commit is contained in:
1 parent
11736158a4
commit
9ca6298761
2 files changed
+46
-2
No files matched your search
+7
-2
@@ -1359,8 +1359,13 @@ _CPP_CONFIG = LanguageConfig(
|
||||
# set of enumerators. Its name and body sit on the same `name`/`body` fields
|
||||
# as struct_specifier (type_identifier + enumerator_list), so it gets a node
|
||||
# and a body walk; the enumerators are emitted by _cpp_extra_walk (the C++
|
||||
# parity of Java #1719 / Swift / Scala enums).
|
||||
class_types=frozenset({"class_specifier", "struct_specifier", "enum_specifier"}),
|
||||
# parity of Java #1719 / Swift / Scala enums). union_specifier is likewise a
|
||||
# class-like container with the identical name/body fields (type_identifier +
|
||||
# field_declaration_list), so a `union { ... }` becomes a type node with its
|
||||
# data members instead of being dropped along with everything it declares.
|
||||
class_types=frozenset({
|
||||
"class_specifier", "struct_specifier", "enum_specifier", "union_specifier",
|
||||
}),
|
||||
function_types=frozenset({"function_definition"}),
|
||||
import_types=frozenset({"preproc_include"}),
|
||||
call_types=frozenset({"call_expression"}),
|
||||
|
||||
@@ -84,6 +84,45 @@ def test_cpp_enum_nested_in_class_and_namespace_is_extracted(tmp_path):
|
||||
assert ("Proto", "Udp") in case_of
|
||||
|
||||
|
||||
def test_cpp_union_specifier_is_extracted(tmp_path):
|
||||
"""A named `union` is a class-like container whose type node and data members
|
||||
must survive. `union_specifier` was missing from the C++ class_types, so a
|
||||
`union { ... }` and everything it declared produced no nodes at all — the whole
|
||||
type vanished. It shares struct_specifier's name/body fields (type_identifier +
|
||||
field_declaration_list), so it must get a type node and its members, like a
|
||||
struct. An anonymous union has no type name and is skipped, like an anonymous
|
||||
enum.
|
||||
"""
|
||||
p = tmp_path / "value.hpp"
|
||||
p.write_text(
|
||||
"union Value { int i; float f; };\n"
|
||||
"struct Point { int x; };\n"
|
||||
"typedef union { int a; char b; } Anon;\n"
|
||||
)
|
||||
result = extract_cpp(p)
|
||||
assert result.get("parse_errors") is None
|
||||
ids = {n["id"]: n["label"] for n in result["nodes"]}
|
||||
labels = set(ids.values())
|
||||
# Pre-fix the whole `union Value { ... }` declaration vanished.
|
||||
assert {"Value", "i", "f"} <= labels
|
||||
contains = {
|
||||
(ids.get(e["source"]), ids.get(e["target"]))
|
||||
for e in result["edges"]
|
||||
if e["relation"] == "contains"
|
||||
}
|
||||
defines = {
|
||||
(ids.get(e["source"]), ids.get(e["target"]))
|
||||
for e in result["edges"]
|
||||
if e["relation"] == "defines"
|
||||
}
|
||||
assert ("value.hpp", "Value") in contains
|
||||
assert ("Value", "i") in defines
|
||||
assert ("Value", "f") in defines
|
||||
# An anonymous union (`typedef union { ... } Anon`) has no type name, so it is
|
||||
# skipped rather than emitting a nameless node, like an anonymous enum.
|
||||
assert "Anon" not in labels
|
||||
|
||||
|
||||
def test_nested_cpp_class_is_extracted(tmp_path):
|
||||
# A nested type is a field_declaration whose `type` field IS the
|
||||
# class_specifier; the member-variable branch used to consume it and return
|
||||
|
||||
Reference in new issue
Block a user