From 1e848458f9df16fc961e01bf9b5ba0979d02ea12 Mon Sep 17 00:00:00 2001 From: Safi Date: Sat, 2 May 2026 17:02:24 +0100 Subject: [PATCH] remove VB.NET support: tree-sitter-vbnet only has Windows wheels, no Linux/macOS Co-Authored-By: Claude Sonnet 4.6 --- graphify/detect.py | 2 +- graphify/extract.py | 108 --------------------------------------- pyproject.toml | 3 +- tests/fixtures/sample.vb | 59 --------------------- tests/test_languages.py | 95 +--------------------------------- 5 files changed, 4 insertions(+), 263 deletions(-) delete mode 100644 tests/fixtures/sample.vb diff --git a/graphify/detect.py b/graphify/detect.py index b1c9d7f..30de00e 100644 --- a/graphify/detect.py +++ b/graphify/detect.py @@ -18,7 +18,7 @@ class FileType(str, Enum): _MANIFEST_PATH = "graphify-out/manifest.json" -CODE_EXTENSIONS = {'.py', '.ts', '.js', '.jsx', '.tsx', '.mjs', '.ejs', '.go', '.rs', '.java', '.cpp', '.cc', '.cxx', '.c', '.h', '.hpp', '.rb', '.swift', '.kt', '.kts', '.cs', '.scala', '.php', '.lua', '.toc', '.zig', '.ps1', '.ex', '.exs', '.m', '.mm', '.jl', '.vue', '.svelte', '.dart', '.v', '.sv', '.sql', '.r', '.vb'} +CODE_EXTENSIONS = {'.py', '.ts', '.js', '.jsx', '.tsx', '.mjs', '.ejs', '.go', '.rs', '.java', '.cpp', '.cc', '.cxx', '.c', '.h', '.hpp', '.rb', '.swift', '.kt', '.kts', '.cs', '.scala', '.php', '.lua', '.toc', '.zig', '.ps1', '.ex', '.exs', '.m', '.mm', '.jl', '.vue', '.svelte', '.dart', '.v', '.sv', '.sql', '.r'} DOC_EXTENSIONS = {'.md', '.mdx', '.txt', '.rst', '.html', '.yaml', '.yml'} PAPER_EXTENSIONS = {'.pdf'} IMAGE_EXTENSIONS = {'.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'} diff --git a/graphify/extract.py b/graphify/extract.py index 0e1c86c..d99d4b1 100644 --- a/graphify/extract.py +++ b/graphify/extract.py @@ -591,25 +591,6 @@ def _swift_extra_walk(node, source: bytes, file_nid: str, stem: str, str_path: s return False -def _vbnet_extra_walk(node, source: bytes, file_nid: str, stem: str, str_path: str, - nodes: list, edges: list, seen_ids: set, function_bodies: list, - parent_class_nid: str | None, add_node_fn, add_edge_fn, - walk_fn) -> bool: - """Handle namespace_block for VB.NET. Returns True if handled.""" - if node.type == "namespace_block": - name_node = node.child_by_field_name("name") - if name_node: - ns_name = _read_text(name_node, source) - ns_nid = _make_id(stem, ns_name) - line = node.start_point[0] + 1 - add_node_fn(ns_nid, ns_name, line) - add_edge_fn(file_nid, ns_nid, "contains", line) - for child in node.children: - walk_fn(child, parent_class_nid) - return True - return False - - # ── Language configs ────────────────────────────────────────────────────────── _PYTHON_CONFIG = LanguageConfig( @@ -830,24 +811,6 @@ def _import_swift(node, source: bytes, file_nid: str, stem: str, edges: list, st break -def _import_vbnet(node, source: bytes, file_nid: str, stem: str, edges: list, str_path: str) -> None: - """Handle VB.NET 'Imports System.Collections.Generic' statements.""" - for child in node.children: - if child.type == "namespace_name": - raw = _read_text(child, source).strip() - if raw: - tgt_nid = _make_id(raw) - edges.append({ - "source": file_nid, - "target": tgt_nid, - "relation": "imports", - "confidence": "EXTRACTED", - "source_file": str_path, - "source_location": f"L{node.start_point[0] + 1}", - "weight": 1.0, - }) - - def _read_csharp_type_name(node, source: bytes) -> str | None: """Resolve a readable C# type name from a field/type node.""" if node is None: @@ -884,21 +847,6 @@ _SWIFT_CONFIG = LanguageConfig( import_handler=_import_swift, ) -_VBNET_CONFIG = LanguageConfig( - ts_module="tree_sitter_vbnet", - ts_language_fn="language", - class_types=frozenset({"class_block", "module_block", "structure_block", "interface_block"}), - function_types=frozenset({"method_declaration", "constructor_declaration", "property_declaration"}), - import_types=frozenset({"imports_statement"}), - call_types=frozenset({"invocation"}), - call_function_field="target", - call_accessor_node_types=frozenset({"member_access"}), - call_accessor_field="member", - function_boundary_types=frozenset({"method_declaration", "constructor_declaration", "property_declaration"}), - import_handler=_import_vbnet, -) - - # ── Generic extractor ───────────────────────────────────────────────────────── def _extract_generic(path: Path, config: LanguageConfig) -> dict: @@ -1114,43 +1062,6 @@ def _extract_generic(path: Path, config: LanguageConfig) -> dict: if body: for child in body.children: walk(child, parent_class_nid=class_nid) - elif config.ts_module == "tree_sitter_vbnet": - # VB.NET class/module/structure/interface have no separate body node — - # inherits/implements appear as named fields, members are inline children. - def _emit_vbnet_parent(clause_node, rel: str) -> None: - for child in clause_node.children: - if not child.is_named: - continue - raw = _read_text(child, source).strip() - if not raw: - continue - # Strip generic args e.g. IList(Of T) → IList - base_name = raw.split("(")[0].strip().split(".")[-1] - if not base_name: - continue - base_nid = _make_id(stem, base_name) - if base_nid not in seen_ids: - base_nid = _make_id(base_name) - if base_nid not in seen_ids: - nodes.append({ - "id": base_nid, - "label": base_name, - "file_type": "code", - "source_file": "", - "source_location": "", - }) - seen_ids.add(base_nid) - add_edge(class_nid, base_nid, rel, line) - - inherits_node = node.child_by_field_name("inherits") - if inherits_node: - _emit_vbnet_parent(inherits_node, "inherits") - implements_node = node.child_by_field_name("implements") - if implements_node: - _emit_vbnet_parent(implements_node, "implements") - - for child in node.children: - walk(child, parent_class_nid=class_nid) return # Event listener property arrays: $listen = [Event::class => [Listener::class]] @@ -1228,9 +1139,6 @@ def _extract_generic(path: Path, config: LanguageConfig) -> dict: func_name: str | None = "deinit" elif t == "subscript_declaration": func_name = "subscript" - elif config.ts_module == "tree_sitter_vbnet" and t == "constructor_declaration": - # VB.NET Sub New has no 'name' field — always named "New" - func_name = "New" elif config.resolve_function_name_fn is not None: # C/C++ style: use declarator declarator = node.child_by_field_name("declarator") @@ -1262,10 +1170,6 @@ def _extract_generic(path: Path, config: LanguageConfig) -> dict: body = _find_body(node, config) if body: function_bodies.append((func_nid, body)) - elif config.ts_module == "tree_sitter_vbnet": - # VB.NET method/property/constructor bodies have no wrapper node — - # use the declaration node itself so walk_calls can find invocations. - function_bodies.append((func_nid, node)) return # JS/TS arrow functions and C# namespaces — language-specific extra handling @@ -1287,12 +1191,6 @@ def _extract_generic(path: Path, config: LanguageConfig) -> dict: parent_class_nid, add_node, add_edge): return - if config.ts_module == "tree_sitter_vbnet": - if _vbnet_extra_walk(node, source, file_nid, stem, str_path, - nodes, edges, seen_ids, function_bodies, - parent_class_nid, add_node, add_edge, walk): - return - # Default: recurse for child in node.children: walk(child, parent_class_nid=None) @@ -1744,11 +1642,6 @@ def _extract_python_rationale(path: Path, result: dict) -> None: # ── Public API ──────────────────────────────────────────────────────────────── -def extract_vbnet(path: Path) -> dict: - """Extract classes, modules, functions, and imports from a .vb file.""" - return _extract_generic(path, _VBNET_CONFIG) - - def extract_python(path: Path) -> dict: """Extract classes, functions, and imports from a .py file via tree-sitter AST.""" result = _extract_generic(path, _PYTHON_CONFIG) @@ -3831,7 +3724,6 @@ def extract(paths: list[Path], cache_root: Path | None = None) -> dict: ".v": extract_verilog, ".sv": extract_verilog, ".sql": extract_sql, - ".vb": extract_vbnet, } total = len(paths) diff --git a/pyproject.toml b/pyproject.toml index e47a6c6..27deb45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,8 +52,7 @@ office = ["python-docx", "openpyxl"] video = ["faster-whisper", "yt-dlp"] kimi = ["openai", "tiktoken"] sql = ["tree-sitter-sql"] -vbnet = ["tree-sitter-vbnet"] -all = ["mcp", "neo4j", "pypdf", "markdownify", "watchdog", "graspologic; python_version < '3.13'", "python-docx", "openpyxl", "faster-whisper", "yt-dlp", "matplotlib", "openai", "tiktoken", "tree-sitter-sql", "tree-sitter-vbnet"] +all = ["mcp", "neo4j", "pypdf", "markdownify", "watchdog", "graspologic; python_version < '3.13'", "python-docx", "openpyxl", "faster-whisper", "yt-dlp", "matplotlib", "openai", "tiktoken", "tree-sitter-sql"] [project.scripts] graphify = "graphify.__main__:main" diff --git a/tests/fixtures/sample.vb b/tests/fixtures/sample.vb deleted file mode 100644 index 999c155..0000000 --- a/tests/fixtures/sample.vb +++ /dev/null @@ -1,59 +0,0 @@ -Imports System -Imports System.Collections.Generic -Imports System.Net.Http - -Namespace GraphifyDemo - - Public Interface IProcessor - Function Process(items As List(Of String)) As List(Of String) - End Interface - - Public Class DataProcessor - Inherits BaseProcessor - Implements IProcessor - - Private ReadOnly _client As HttpClient - - Public Sub New() - _client = New HttpClient() - End Sub - - Public Function Process(items As List(Of String)) As List(Of String) - Return Validate(items) - End Function - - Private Function Validate(items As List(Of String)) As List(Of String) - Dim result As New List(Of String) - For Each item In items - If Not String.IsNullOrEmpty(item) Then - result.Add(item.Trim()) - End If - Next - Return result - End Function - - End Class - - Public Module AppHelper - - Public Sub Run(processor As IProcessor) - Dim data As New List(Of String) - data.Add("hello") - processor.Process(data) - End Sub - - End Module - - Public Structure Point - Implements IComparable - - Public X As Double - Public Y As Double - - Public Function CompareTo(obj As Object) As Integer - Return 0 - End Function - - End Structure - -End Namespace diff --git a/tests/test_languages.py b/tests/test_languages.py index 240265f..96c38ec 100644 --- a/tests/test_languages.py +++ b/tests/test_languages.py @@ -1,21 +1,15 @@ -"""Tests for language extractors: Java, C, C++, Ruby, C#, Kotlin, Scala, PHP, Swift, Go, Julia, VB.NET, JS/TS.""" +"""Tests for language extractors: Java, C, C++, Ruby, C#, Kotlin, Scala, PHP, Swift, Go, Julia, JS/TS.""" from __future__ import annotations from pathlib import Path import pytest from graphify.extract import ( extract_java, extract_c, extract_cpp, extract_ruby, extract_csharp, extract_kotlin, extract_scala, extract_php, - extract_swift, extract_go, extract_julia, extract_vbnet, extract_js, + extract_swift, extract_go, extract_julia, extract_js, ) FIXTURES = Path(__file__).parent / "fixtures" -import importlib.util -vbnet_available = pytest.mark.skipif( - importlib.util.find_spec("tree_sitter_vbnet") is None, - reason="tree-sitter-vbnet not on PyPI yet" -) - def _labels(r): return [n["label"] for n in r["nodes"]] @@ -529,91 +523,6 @@ def test_swift_emits_calls(): calls = _calls(r) assert any("process" in src and "validate" in tgt for src, tgt in calls) -# ── VB.NET ───────────────────────────────────────────────────────────────────────── - -@vbnet_available -def test_vbnet_no_error(): - r = extract_vbnet(FIXTURES / "sample.vb") - assert "error" not in r - -@vbnet_available -def test_vbnet_finds_class(): - r = extract_vbnet(FIXTURES / "sample.vb") - assert any("DataProcessor" in l for l in _labels(r)) - -@vbnet_available -def test_vbnet_finds_interface(): - r = extract_vbnet(FIXTURES / "sample.vb") - assert any("IProcessor" in l for l in _labels(r)) - -@vbnet_available -def test_vbnet_finds_module(): - r = extract_vbnet(FIXTURES / "sample.vb") - assert any("AppHelper" in l for l in _labels(r)) - -@vbnet_available -def test_vbnet_finds_structure(): - r = extract_vbnet(FIXTURES / "sample.vb") - assert any("Point" in l for l in _labels(r)) - -@vbnet_available -def test_vbnet_finds_methods(): - r = extract_vbnet(FIXTURES / "sample.vb") - labels = _labels(r) - assert any("Process" in l for l in labels) - assert any("Validate" in l for l in labels) - -@vbnet_available -def test_vbnet_finds_sub(): - r = extract_vbnet(FIXTURES / "sample.vb") - assert any("Run" in l for l in _labels(r)) - -@vbnet_available -def test_vbnet_finds_imports(): - r = extract_vbnet(FIXTURES / "sample.vb") - assert "imports" in _relations(r) - -@vbnet_available -def test_vbnet_inherits_edge(): - r = extract_vbnet(FIXTURES / "sample.vb") - inherits = [e for e in r["edges"] if e["relation"] == "inherits"] - assert len(inherits) >= 1 - -@vbnet_available -def test_vbnet_inherits_baseprovessor(): - r = extract_vbnet(FIXTURES / "sample.vb") - node_by_id = {n["id"]: n["label"] for n in r["nodes"]} - found = any( - "DataProcessor" in node_by_id.get(e["source"], "") and - "BaseProcessor" in node_by_id.get(e["target"], "") - for e in r["edges"] if e["relation"] == "inherits" - ) - assert found, "DataProcessor should have inherits edge to BaseProcessor" - -@vbnet_available -def test_vbnet_implements_edge(): - r = extract_vbnet(FIXTURES / "sample.vb") - implements = [e for e in r["edges"] if e["relation"] == "implements"] - assert len(implements) >= 1 - -@vbnet_available -def test_vbnet_implements_iprocessor(): - r = extract_vbnet(FIXTURES / "sample.vb") - node_by_id = {n["id"]: n["label"] for n in r["nodes"]} - found = any( - "DataProcessor" in node_by_id.get(e["source"], "") and - "IProcessor" in node_by_id.get(e["target"], "") - for e in r["edges"] if e["relation"] == "implements" - ) - assert found, "DataProcessor should have implements edge to IProcessor" - -@vbnet_available -def test_vbnet_no_dangling_edges(): - r = extract_vbnet(FIXTURES / "sample.vb") - node_ids = {n["id"] for n in r["nodes"]} - for e in r["edges"]: - assert e["source"] in node_ids - def test_swift_call_edges_have_call_context(): r = extract_swift(FIXTURES / "sample.swift") call_edges = _edges_with_relation(r, "calls")