mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-13 07:29:33 +00:00
fix(pascal): extract enumerated types and their values
(cherry picked from commit 8cf55d37be)
This commit is contained in:
1 parent
67a96aa08f
commit
b46263123a
2 files changed
+78
No files matched your search
@@ -545,11 +545,43 @@ def extract_pascal(path: Path) -> dict:
|
||||
if t == "declType":
|
||||
type_name = None
|
||||
kind_node = None
|
||||
enum_node = None
|
||||
for child in node.children:
|
||||
if child.type == "identifier" and type_name is None:
|
||||
type_name = _read(child)
|
||||
elif child.type in ("declClass", "declIntf", "declHelper") and kind_node is None:
|
||||
kind_node = child
|
||||
elif child.type == "type" and enum_node is None:
|
||||
# An enumerated type (`TColor = (clRed, clGreen);`) nests its
|
||||
# values under type -> declEnum -> declEnumValue.
|
||||
enum_node = next(
|
||||
(gc for gc in child.children if gc.type == "declEnum"), None
|
||||
)
|
||||
if type_name and enum_node is not None:
|
||||
# A Pascal enumerated type is a named type whose values are its
|
||||
# cases. Without this branch declType matched only class/interface/
|
||||
# helper kinds, so the whole enum type AND its values fell through
|
||||
# and were dropped. Emit the type node plus a `case_of` edge per
|
||||
# value — the Pascal parity of Java #1719 / C# / Swift / Scala enums.
|
||||
enum_nid = _make_id(stem, type_name)
|
||||
add_node(enum_nid, type_name, line)
|
||||
add_edge(parent_nid, enum_nid, "contains", line)
|
||||
for value in enum_node.children:
|
||||
if value.type != "declEnumValue":
|
||||
continue
|
||||
value_name_node = next(
|
||||
(c for c in value.children if c.type == "identifier"), None
|
||||
)
|
||||
if value_name_node is None:
|
||||
continue
|
||||
value_name = _read(value_name_node)
|
||||
if not value_name:
|
||||
continue
|
||||
value_line = value.start_point[0] + 1
|
||||
value_nid = _make_id(enum_nid, value_name)
|
||||
add_node(value_nid, value_name, value_line)
|
||||
add_edge(enum_nid, value_nid, "case_of", value_line)
|
||||
return
|
||||
if type_name and kind_node:
|
||||
cls_nid = _make_id(stem, type_name)
|
||||
add_node(cls_nid, type_name, line)
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
"""Tests for the Pascal/Delphi extractor."""
|
||||
from __future__ import annotations
|
||||
import importlib.util as _ilu
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
FIXTURES = Path(__file__).parent / "fixtures"
|
||||
|
||||
_needs_pascal = pytest.mark.skipif(
|
||||
_ilu.find_spec("tree_sitter_pascal") is None,
|
||||
reason="tree-sitter-pascal not installed (enum types need the AST path)",
|
||||
)
|
||||
|
||||
|
||||
def _labels(r):
|
||||
return [n["label"] for n in r["nodes"]]
|
||||
@@ -85,6 +93,44 @@ def test_pascal_inherits_from_base():
|
||||
assert found, "TDataProcessor should have at least one inherits edge"
|
||||
|
||||
|
||||
@_needs_pascal
|
||||
def test_pascal_enum_type_and_values_are_extracted(tmp_path):
|
||||
"""A Pascal enumerated type becomes a node with a `case_of` edge per value.
|
||||
|
||||
`declType` matched only class/interface/helper kinds, so an enumerated type
|
||||
(`TColor = (clRed, clGreen, clBlue);`) and all of its values fell through and
|
||||
were dropped — the whole type vanished. An enum's values are its cases, so
|
||||
each becomes a node with a `case_of` edge to the type, matching every other
|
||||
language with enums (Java #1719 / C# / Swift / Scala).
|
||||
"""
|
||||
from graphify.extract import extract_pascal
|
||||
p = tmp_path / "colors.pas"
|
||||
p.write_text(
|
||||
"unit Colors;\n"
|
||||
"interface\n"
|
||||
"type\n"
|
||||
" TColor = (clRed, clGreen, clBlue);\n"
|
||||
" TNum = Integer;\n"
|
||||
"implementation\n"
|
||||
"end.\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
r = extract_pascal(p)
|
||||
assert "error" not in r
|
||||
labels = {n["label"] for n in r["nodes"]}
|
||||
# Pre-fix the whole `TColor = (...)` declaration vanished.
|
||||
assert {"TColor", "clRed", "clGreen", "clBlue"} <= labels
|
||||
ids = {n["id"]: n["label"] for n in r["nodes"]}
|
||||
case_of = {
|
||||
(ids.get(e["source"]), ids.get(e["target"]))
|
||||
for e in r["edges"]
|
||||
if e["relation"] == "case_of"
|
||||
}
|
||||
assert ("TColor", "clRed") in case_of
|
||||
assert ("TColor", "clGreen") in case_of
|
||||
assert ("TColor", "clBlue") in case_of
|
||||
|
||||
|
||||
def test_pascal_finds_calls():
|
||||
from graphify.extract import extract_pascal
|
||||
r = extract_pascal(FIXTURES / "sample.pas")
|
||||
|
||||
Reference in new issue
Block a user