Skip to content

Commit c990e80

Browse files
committed
fix: restore rust parser compatibility and typing
1 parent 717a50d commit c990e80

2 files changed

Lines changed: 50 additions & 48 deletions

File tree

src/knowcode/parsers/rust_parser.py

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,16 @@ def _extract_entities(
4747
enum_entity, enum_rels = self._parse_enum(
4848
child, file_path, parent_id, source_code, source_lines
4949
)
50-
entities.append(enum_entity)
50+
if enum_entity:
51+
entities.append(enum_entity)
5152
relationships.extend(enum_rels)
5253

5354
elif child_type == "trait_item":
5455
trait_entity, trait_rels = self._parse_trait(
5556
child, file_path, parent_id, source_code, source_lines
5657
)
57-
entities.append(trait_entity)
58+
if trait_entity:
59+
entities.append(trait_entity)
5860
relationships.extend(trait_rels)
5961

6062
elif child_type == "impl_item":
@@ -68,36 +70,36 @@ def _extract_entities(
6870
func_entity, func_rels = self._parse_function(
6971
child, file_path, parent_id, source_code, source_lines
7072
)
71-
entities.append(func_entity)
73+
if func_entity:
74+
entities.append(func_entity)
7275
relationships.extend(func_rels)
7376

7477
elif child_type == "const_item":
7578
const_entity = self._parse_const(
7679
child, file_path, parent_id, source_code, source_lines
7780
)
78-
entities.append(const_entity)
81+
if const_entity:
82+
entities.append(const_entity)
7983

8084
elif child_type == "static_item":
8185
static_entity = self._parse_static(
8286
child, file_path, parent_id, source_code, source_lines
8387
)
84-
entities.append(static_entity)
88+
if static_entity:
89+
entities.append(static_entity)
8590

8691
elif child_type == "type_item":
8792
type_entity = self._parse_type_alias(
8893
child, file_path, parent_id, source_code, source_lines
8994
)
90-
entities.append(type_entity)
95+
if type_entity:
96+
entities.append(type_entity)
9197

9298
elif child_type == "mod_item":
93-
mod_result, mod_rels = self._parse_module(
99+
mod_entities, mod_rels = self._parse_module(
94100
child, file_path, parent_id, source_code, source_lines
95101
)
96-
# mod_result can be a single entity or a list (for inline modules with nested content)
97-
if isinstance(mod_result, list):
98-
entities.extend(mod_result)
99-
else:
100-
entities.append(mod_result)
102+
entities.extend(mod_entities)
101103
relationships.extend(mod_rels)
102104

103105
elif child_type == "use_declaration":
@@ -119,7 +121,7 @@ def _parse_struct(
119121
if not name_node:
120122
return [], []
121123

122-
name = self._get_text(name_node, None)
124+
name = self._get_text(name_node)
123125
qualified_name = f"{parent_id.split('::')[-1]}.{name}"
124126

125127
# Extract doc comment, visibility, and attributes
@@ -161,7 +163,7 @@ def _parse_struct(
161163
field_type_node = field.child_by_field_name("type")
162164

163165
if field_name_node:
164-
field_name = self._get_text(field_name_node, None)
166+
field_name = self._get_text(field_name_node)
165167
field_qualified = f"{qualified_name}.{field_name}"
166168

167169
field_entity = self._create_entity(
@@ -183,7 +185,7 @@ def _parse_struct(
183185

184186
# Track type usage (strip generics for base type)
185187
if field_type_node:
186-
type_name = self._get_text(field_type_node, None)
188+
type_name = self._get_text(field_type_node)
187189
base_type = self._strip_generics(type_name)
188190
relationships.append(
189191
Relationship(
@@ -202,13 +204,13 @@ def _parse_enum(
202204
parent_id: str,
203205
source_code: str,
204206
source_lines: list[str],
205-
) -> tuple[Entity, list[Relationship]]:
207+
) -> tuple[Optional[Entity], list[Relationship]]:
206208
"""Parse an enum declaration."""
207209
name_node = node.child_by_field_name("name")
208210
if not name_node:
209211
return None, []
210212

211-
name = self._get_text(name_node, None)
213+
name = self._get_text(name_node)
212214
qualified_name = f"{parent_id.split('::')[-1]}.{name}"
213215
docstring = self._extract_doc_comment(node, source_lines)
214216
visibility = self._extract_visibility(node)
@@ -247,13 +249,13 @@ def _parse_trait(
247249
parent_id: str,
248250
source_code: str,
249251
source_lines: list[str],
250-
) -> tuple[Entity, list[Relationship]]:
252+
) -> tuple[Optional[Entity], list[Relationship]]:
251253
"""Parse a trait declaration."""
252254
name_node = node.child_by_field_name("name")
253255
if not name_node:
254256
return None, []
255257

256-
name = self._get_text(name_node, None)
258+
name = self._get_text(name_node)
257259
qualified_name = f"{parent_id.split('::')[-1]}.{name}"
258260
docstring = self._extract_doc_comment(node, source_lines)
259261
visibility = self._extract_visibility(node)
@@ -311,7 +313,7 @@ def _parse_impl(
311313
# Fallback: This should never happen in valid Rust code
312314
return entities, relationships
313315

314-
type_name = self._get_text(type_node, None)
316+
type_name = self._get_text(type_node)
315317
if not type_name:
316318
return entities, relationships
317319

@@ -322,7 +324,7 @@ def _parse_impl(
322324
# Strip generics from trait name for cleaner linking
323325
trait_name = None
324326
if is_trait_impl:
325-
trait_name_raw = self._get_text(trait_node, None)
327+
trait_name_raw = self._get_text(trait_node)
326328
trait_name = self._strip_generics(trait_name_raw)
327329
relationships.append(
328330
Relationship(
@@ -380,13 +382,13 @@ def _parse_function(
380382
source_code: str,
381383
source_lines: list[str],
382384
impl_type: Optional[str] = None,
383-
) -> tuple[Entity, list[Relationship]]:
385+
) -> tuple[Optional[Entity], list[Relationship]]:
384386
"""Parse a function declaration."""
385387
name_node = node.child_by_field_name("name")
386388
if not name_node:
387389
return None, []
388390

389-
name = self._get_text(name_node, None)
391+
name = self._get_text(name_node)
390392

391393
# Build qualified name
392394
if impl_type:
@@ -448,13 +450,13 @@ def _parse_const(
448450
parent_id: str,
449451
source_code: str,
450452
source_lines: list[str],
451-
) -> Entity:
453+
) -> Optional[Entity]:
452454
"""Parse a const declaration."""
453455
name_node = node.child_by_field_name("name")
454456
if not name_node:
455457
return None
456458

457-
name = self._get_text(name_node, None)
459+
name = self._get_text(name_node)
458460
qualified_name = f"{parent_id.split('::')[-1]}.{name}"
459461
visibility = self._extract_visibility(node)
460462

@@ -480,13 +482,13 @@ def _parse_static(
480482
parent_id: str,
481483
source_code: str,
482484
source_lines: list[str],
483-
) -> Entity:
485+
) -> Optional[Entity]:
484486
"""Parse a static declaration."""
485487
name_node = node.child_by_field_name("name")
486488
if not name_node:
487489
return None
488490

489-
name = self._get_text(name_node, None)
491+
name = self._get_text(name_node)
490492
qualified_name = f"{parent_id.split('::')[-1]}.{name}"
491493
visibility = self._extract_visibility(node)
492494

@@ -512,13 +514,13 @@ def _parse_type_alias(
512514
parent_id: str,
513515
source_code: str,
514516
source_lines: list[str],
515-
) -> Entity:
517+
) -> Optional[Entity]:
516518
"""Parse a type alias declaration."""
517519
name_node = node.child_by_field_name("name")
518520
if not name_node:
519521
return None
520522

521-
name = self._get_text(name_node, None)
523+
name = self._get_text(name_node)
522524
qualified_name = f"{parent_id.split('::')[-1]}.{name}"
523525
visibility = self._extract_visibility(node)
524526

@@ -544,7 +546,7 @@ def _parse_module(
544546
parent_id: str,
545547
source_code: str,
546548
source_lines: list[str],
547-
) -> tuple[Entity, list[Relationship]]:
549+
) -> tuple[list[Entity], list[Relationship]]:
548550
"""Parse a module declaration.
549551
550552
Handles both:
@@ -553,9 +555,9 @@ def _parse_module(
553555
"""
554556
name_node = node.child_by_field_name("name")
555557
if not name_node:
556-
return None, []
558+
return [], []
557559

558-
name = self._get_text(name_node, None)
560+
name = self._get_text(name_node)
559561
qualified_name = f"{parent_id.split('::')[-1]}.{name}"
560562
visibility = self._extract_visibility(node)
561563

@@ -606,9 +608,9 @@ def _parse_module(
606608
source_lines,
607609
)
608610
# Return both the module and its nested entities
609-
return [mod_entity] + nested_entities, relationships + nested_rels
611+
return [mod_entity, *nested_entities], relationships + nested_rels
610612

611-
return mod_entity, relationships
613+
return [mod_entity], relationships
612614

613615
def _parse_use_declaration(self, node: Any, parent_id: str) -> list[Relationship]:
614616
"""Parse use declarations (imports).
@@ -643,10 +645,10 @@ def _extract_function_signature(self, node: Any, source_code: str, impl_type: Op
643645
return_type_node = node.child_by_field_name("return_type")
644646

645647
name_node = node.child_by_field_name("name")
646-
name = self._get_text(name_node, None) if name_node else "unknown"
648+
name = self._get_text(name_node) if name_node else "unknown"
647649

648-
params_text = self._get_text(params_node, None) if params_node else "()"
649-
return_text = self._get_text(return_type_node, None) if return_type_node else ""
650+
params_text = self._get_text(params_node) if params_node else "()"
651+
return_text = self._get_text(return_type_node) if return_type_node else ""
650652

651653
# Resolve Self keyword in return type
652654
if return_text and impl_type:
@@ -658,14 +660,14 @@ def _extract_function_signature(self, node: Any, source_code: str, impl_type: Op
658660

659661
def _extract_calls_from_body(self, body_node: Any, caller_id: str) -> list[Relationship]:
660662
"""Extract function calls from a function body."""
661-
relationships = []
663+
relationships: list[Relationship] = []
662664

663665
def visit_node(node: Any) -> None:
664666
if node.type == "call_expression":
665667
# Get function being called
666668
function_node = node.child_by_field_name("function")
667669
if function_node:
668-
callee_name = self._get_text(function_node, None)
670+
callee_name = self._get_text(function_node)
669671
relationships.append(
670672
Relationship(
671673
source_id=caller_id,
@@ -689,7 +691,7 @@ def _extract_doc_comment(self, node: Any, source_lines: list[str]) -> Optional[s
689691
start_line = node.start_point[0]
690692

691693
# Look backwards for doc comments
692-
doc_lines = []
694+
doc_lines: list[str] = []
693695
line_idx = start_line - 1
694696

695697
while line_idx >= 0:
@@ -719,7 +721,7 @@ def _parse_macro_invocation(self, node: Any, parent_id: str) -> Optional[Relatio
719721
if not macro_node:
720722
return None
721723

722-
macro_name = self._get_text(macro_node, None)
724+
macro_name = self._get_text(macro_node)
723725

724726
# Create CALLS relationship for the macro
725727
return Relationship(
@@ -757,13 +759,13 @@ def _parse_use_tree(self, use_tree_node: Any) -> list[str]:
757759
list_node = use_tree_node.child_by_field_name("list")
758760

759761
if path_node and list_node:
760-
prefix = self._get_text(path_node, None)
762+
prefix = self._get_text(path_node)
761763
sub_paths = self._parse_use_tree(list_node)
762764
paths.extend([f"{prefix}::{sub}" for sub in sub_paths])
763765

764766
else:
765767
# Simple import: use std::vec or an identifier
766-
path_text = self._get_text(use_tree_node, None)
768+
path_text = self._get_text(use_tree_node)
767769
if path_text:
768770
paths.append(path_text.strip())
769771

@@ -777,7 +779,7 @@ def _extract_visibility(self, node: Any) -> str:
777779
# Look for visibility_modifier child
778780
for child in node.children:
779781
if child.type == "visibility_modifier":
780-
vis_text = self._get_text(child, None)
782+
vis_text = self._get_text(child)
781783
if vis_text == "pub":
782784
return "public"
783785
elif vis_text.startswith("pub("):
@@ -791,7 +793,7 @@ def _extract_attributes(self, node: Any, source_lines: list[str]) -> list[str]:
791793
Captures attributes like #[test], #[derive(Debug)], #[inline], etc.
792794
"""
793795
start_line = node.start_point[0]
794-
attributes = []
796+
attributes: list[str] = []
795797
line_idx = start_line - 1
796798

797799
while line_idx >= 0:

src/knowcode/parsers/vue_parser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Vue Single File Component parser using Tree-sitter."""
22

33
from pathlib import Path
4-
from typing import Any, Union
4+
from typing import Any, Union, cast
55
import re
66

77
from knowcode.data_models import Entity, EntityKind, Relationship, RelationshipKind, Location, ParseResult
@@ -27,7 +27,7 @@ def __init__(self) -> None:
2727
# Don't call super().__init__ because vue language is not available
2828
self.language_name = "vue"
2929
self.js_parser = JavaScriptParser()
30-
self.parser = None # No tree-sitter parser for Vue
30+
self.parser = cast(Any, None) # No tree-sitter parser for Vue
3131
self.language = None
3232

3333
def parse_file(self, file_path: Union[str, Path]) -> ParseResult:
@@ -145,7 +145,7 @@ def _extract_entities(
145145

146146
if child_type == "script_element":
147147
# Parse <script> section
148-
script_text = self._get_text(child, None)
148+
script_text = self._get_text(child)
149149
script_entities, script_rels = self._parse_script_content(
150150
script_text, file_path, parent_id, source_lines
151151
)

0 commit comments

Comments
 (0)