Skip to content

Commit c7257a4

Browse files
committed
revert: undo PR #455 (JS/TS service call resolution) due to 30 test regressions
1 parent 5050c0f commit c7257a4

5 files changed

Lines changed: 32 additions & 315 deletions

File tree

‎codebase_rag/graph_updater.py‎

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -390,62 +390,12 @@ def _collect_eligible_files(self) -> list[Path]:
390390
eligible.append(filepath)
391391
return eligible
392392

393-
def _should_force_full_reindex(
394-
self, force: bool, old_hashes: FileHashCache
395-
) -> bool:
396-
if force or not old_hashes:
397-
return False
398-
399-
fetch_all = getattr(self.ingestor, "fetch_all", None)
400-
if not callable(fetch_all):
401-
return False
402-
403-
try:
404-
results = fetch_all(
405-
(
406-
"MATCH (n) "
407-
"WHERE toString(n.qualified_name) STARTS WITH $prefix "
408-
"RETURN count(n) AS c"
409-
),
410-
{"prefix": f"{self.project_name}."},
411-
)
412-
except Exception as e:
413-
logger.debug(
414-
"Incremental reindex graph-state probe failed for {name}: {error}",
415-
name=self.project_name,
416-
error=e,
417-
)
418-
return False
419-
420-
if not results:
421-
logger.info(
422-
"No graph-state probe results for {name}; forcing full reindex",
423-
name=self.project_name,
424-
)
425-
return True
426-
427-
symbol_count = results[0].get("c", 0)
428-
if not isinstance(symbol_count, int):
429-
return False
430-
431-
if symbol_count == 0:
432-
logger.info(
433-
"No existing graph symbols found for {name}; ignoring hash cache and forcing full reindex",
434-
name=self.project_name,
435-
)
436-
return True
437-
438-
return False
439-
440393
def _process_files(self, force: bool = False) -> None:
441394
cache_path = self.repo_path / cs.HASH_CACHE_FILENAME
442395
old_hashes = _load_hash_cache(cache_path) if not force else {}
443396
if force:
444397
logger.info(ls.INCREMENTAL_FORCE)
445398

446-
if self._should_force_full_reindex(force, old_hashes):
447-
old_hashes = {}
448-
449399
eligible_files = self._collect_eligible_files()
450400
new_hashes: FileHashCache = {}
451401
skipped_count = 0

‎codebase_rag/parsers/call_resolver.py‎

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
_SEPARATOR_PATTERN = re.compile(r"[.:]|::")
1717
_CHAINED_METHOD_PATTERN = re.compile(r"\.([^.()]+)$")
18-
_JS_INSTANCE_PREFIXES = {cs.KEYWORD_SELF, "this"}
1918

2019

2120
class CallResolver:
@@ -53,15 +52,6 @@ def _try_resolve_method(
5352
method_qn = f"{class_qn}{separator}{method_name}"
5453
if method_qn in self.function_registry:
5554
return self.function_registry[method_qn], method_qn
56-
57-
class_name = class_qn.split(cs.SEPARATOR_DOT)[-1]
58-
suffix_matches = self.function_registry.find_ending_with(
59-
f"{class_name}{separator}{method_name}"
60-
)
61-
if len(suffix_matches) == 1:
62-
matched_qn = suffix_matches[0]
63-
return self.function_registry[matched_qn], matched_qn
64-
6555
return self._resolve_inherited_method(class_qn, method_name)
6656

6757
def resolve_function_call(
@@ -81,17 +71,14 @@ def resolve_function_call(
8171
return self._resolve_chained_call(call_name, module_qn, local_var_types)
8272

8373
if result := self._try_resolve_via_imports(
84-
call_name, module_qn, local_var_types, class_context
74+
call_name, module_qn, local_var_types
8575
):
8676
return result
8777

88-
if not self._has_separator(call_name):
89-
if result := self._try_resolve_same_module(call_name, module_qn):
90-
return result
91-
return self._try_resolve_via_trie(call_name, module_qn)
78+
if result := self._try_resolve_same_module(call_name, module_qn):
79+
return result
9280

93-
logger.debug(ls.CALL_UNRESOLVED, call_name=call_name)
94-
return None
81+
return self._try_resolve_via_trie(call_name, module_qn)
9582

9683
def _try_resolve_iife(
9784
self, call_name: str, module_qn: str
@@ -120,21 +107,21 @@ def _try_resolve_via_imports(
120107
call_name: str,
121108
module_qn: str,
122109
local_var_types: dict[str, str] | None,
123-
class_context: str | None = None,
124110
) -> tuple[str, str] | None:
125-
import_map = self.import_processor.import_mapping.get(module_qn, {})
111+
if module_qn not in self.import_processor.import_mapping:
112+
return None
113+
114+
import_map = self.import_processor.import_mapping[module_qn]
126115

127116
if result := self._try_resolve_direct_import(call_name, import_map):
128117
return result
129118

130119
if result := self._try_resolve_qualified_call(
131-
call_name, import_map, module_qn, local_var_types, class_context
120+
call_name, import_map, module_qn, local_var_types
132121
):
133122
return result
134123

135-
if import_map:
136-
return self._try_resolve_wildcard_imports(call_name, import_map)
137-
return None
124+
return self._try_resolve_wildcard_imports(call_name, import_map)
138125

139126
def _try_resolve_direct_import(
140127
self, call_name: str, import_map: dict[str, str]
@@ -153,7 +140,6 @@ def _try_resolve_qualified_call(
153140
import_map: dict[str, str],
154141
module_qn: str,
155142
local_var_types: dict[str, str] | None,
156-
class_context: str | None = None,
157143
) -> tuple[str, str] | None:
158144
if not self._has_separator(call_name):
159145
return None
@@ -163,17 +149,11 @@ def _try_resolve_qualified_call(
163149

164150
if len(parts) == 2:
165151
if result := self._resolve_two_part_call(
166-
parts,
167-
call_name,
168-
separator,
169-
import_map,
170-
module_qn,
171-
local_var_types,
172-
class_context,
152+
parts, call_name, separator, import_map, module_qn, local_var_types
173153
):
174154
return result
175155

176-
if len(parts) >= 3 and parts[0] in _JS_INSTANCE_PREFIXES:
156+
if len(parts) >= 3 and parts[0] == cs.KEYWORD_SELF:
177157
return self._resolve_self_attribute_call(
178158
parts, call_name, import_map, module_qn, local_var_types
179159
)
@@ -255,14 +235,9 @@ def _resolve_two_part_call(
255235
import_map: dict[str, str],
256236
module_qn: str,
257237
local_var_types: dict[str, str] | None,
258-
class_context: str | None = None,
259238
) -> tuple[str, str] | None:
260239
object_name, method_name = parts
261240

262-
if object_name in _JS_INSTANCE_PREFIXES and class_context:
263-
if result := self._try_resolve_method(class_context, method_name, separator):
264-
return result
265-
266241
if result := self._try_resolve_via_local_type(
267242
object_name,
268243
method_name,
@@ -279,7 +254,7 @@ def _resolve_two_part_call(
279254
):
280255
return result
281256

282-
return None
257+
return self._try_resolve_module_method(method_name, call_name, module_qn)
283258

284259
def _try_resolve_via_local_type(
285260
self,
@@ -426,15 +401,28 @@ def _resolve_self_attribute_call(
426401
if class_qn := self._resolve_class_qn_from_type(
427402
var_type, import_map, module_qn
428403
):
429-
if resolved_method := self._try_resolve_method(class_qn, method_name):
404+
method_qn = f"{class_qn}.{method_name}"
405+
if method_qn in self.function_registry:
430406
logger.debug(
431407
ls.CALL_INSTANCE_ATTR,
432408
call_name=call_name,
433-
method_qn=resolved_method[1],
409+
method_qn=method_qn,
434410
attr_ref=attribute_ref,
435411
var_type=var_type,
436412
)
437-
return resolved_method
413+
return self.function_registry[method_qn], method_qn
414+
415+
if inherited_method := self._resolve_inherited_method(
416+
class_qn, method_name
417+
):
418+
logger.debug(
419+
ls.CALL_INSTANCE_ATTR_INHERITED,
420+
call_name=call_name,
421+
method_qn=inherited_method[1],
422+
attr_ref=attribute_ref,
423+
var_type=var_type,
424+
)
425+
return inherited_method
438426

439427
return None
440428

‎codebase_rag/parsers/js_ts/type_inference.py‎

Lines changed: 3 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,8 @@ def build_local_variable_type_map(
3535
) -> dict[str, str]:
3636
local_var_types: dict[str, str] = {}
3737

38-
if class_node := self._find_enclosing_class_node(caller_node):
39-
self._collect_constructor_injected_types(
40-
class_node, module_qn, local_var_types
41-
)
42-
43-
self._collect_parameter_types(caller_node, module_qn, local_var_types)
44-
4538
stack: list[ASTNode] = [caller_node]
39+
4640
declarator_count = 0
4741

4842
while stack:
@@ -65,7 +59,7 @@ def build_local_variable_type_map(
6559
)
6660

6761
if var_type := self._infer_js_variable_type_from_value(
68-
value_node, module_qn, local_var_types
62+
value_node, module_qn
6963
):
7064
local_var_types[var_name] = var_type
7165
logger.debug(
@@ -85,138 +79,11 @@ def build_local_variable_type_map(
8579
)
8680
return local_var_types
8781

88-
def _find_enclosing_class_node(self, node: ASTNode) -> ASTNode | None:
89-
current = node
90-
while current is not None:
91-
if current.type == cs.TS_CLASS_DECLARATION:
92-
return current
93-
current = current.parent
94-
return None
95-
96-
def _collect_constructor_injected_types(
97-
self,
98-
class_node: ASTNode,
99-
module_qn: str,
100-
local_var_types: dict[str, str],
101-
) -> None:
102-
body_node = class_node.child_by_field_name(cs.FIELD_BODY)
103-
if body_node is None:
104-
return
105-
106-
for child in body_node.children:
107-
if child.type != cs.TS_METHOD_DEFINITION:
108-
continue
109-
110-
name_node = child.child_by_field_name(cs.FIELD_NAME)
111-
if (
112-
name_node is None
113-
or name_node.text is None
114-
or safe_decode_text(name_node) != cs.KEYWORD_CONSTRUCTOR
115-
):
116-
continue
117-
118-
params_node = child.child_by_field_name(cs.TS_FIELD_PARAMETERS)
119-
if params_node is None:
120-
return
121-
122-
for param in params_node.children:
123-
self._collect_constructor_parameter_type(
124-
param, module_qn, local_var_types
125-
)
126-
return
127-
128-
def _collect_constructor_parameter_type(
129-
self,
130-
param_node: ASTNode,
131-
module_qn: str,
132-
local_var_types: dict[str, str],
133-
) -> None:
134-
if param_node.type not in {
135-
"required_parameter",
136-
"optional_parameter",
137-
cs.TS_FORMAL_PARAMETER,
138-
}:
139-
return
140-
141-
has_accessibility_modifier = any(
142-
child.type == "accessibility_modifier" for child in param_node.children
143-
)
144-
if not has_accessibility_modifier:
145-
return
146-
147-
param_name = self._extract_parameter_name(param_node)
148-
if not param_name:
149-
return
150-
151-
if not (param_type := self._extract_type_annotation_name(param_node)):
152-
return
153-
154-
resolved_type = self._resolve_js_class_name(param_type, module_qn) or param_type
155-
local_var_types[param_name] = resolved_type
156-
local_var_types[f"this.{param_name}"] = resolved_type
157-
158-
def _collect_parameter_types(
159-
self,
160-
caller_node: ASTNode,
161-
module_qn: str,
162-
local_var_types: dict[str, str],
163-
) -> None:
164-
params_node = caller_node.child_by_field_name(cs.TS_FIELD_PARAMETERS)
165-
if params_node is None:
166-
return
167-
168-
for param in params_node.children:
169-
if param.type not in {
170-
"required_parameter",
171-
"optional_parameter",
172-
cs.TS_FORMAL_PARAMETER,
173-
}:
174-
continue
175-
176-
param_name = self._extract_parameter_name(param)
177-
if not param_name or param_name in local_var_types:
178-
continue
179-
180-
if not (param_type := self._extract_type_annotation_name(param)):
181-
continue
182-
183-
resolved_type = self._resolve_js_class_name(param_type, module_qn) or param_type
184-
local_var_types[param_name] = resolved_type
185-
186-
def _extract_parameter_name(self, param_node: ASTNode) -> str | None:
187-
identifier_node = next(
188-
(child for child in param_node.children if child.type == cs.TS_IDENTIFIER),
189-
None,
190-
)
191-
return safe_decode_text(identifier_node) if identifier_node is not None else None
192-
193-
def _extract_type_annotation_name(self, node: ASTNode) -> str | None:
194-
type_node = next(
195-
(child for child in node.children if child.type == "type_annotation"),
196-
None,
197-
)
198-
if type_node is None or type_node.text is None:
199-
return None
200-
201-
type_text = safe_decode_text(type_node)
202-
if not type_text:
203-
return None
204-
205-
return type_text.lstrip(":").strip()
206-
20782
def _infer_js_variable_type_from_value(
208-
self,
209-
value_node: ASTNode,
210-
module_qn: str,
211-
local_var_types: dict[str, str],
83+
self, value_node: ASTNode, module_qn: str
21284
) -> str | None:
21385
logger.debug(ls.JS_INFER_VALUE_NODE, node_type=value_node.type)
21486

215-
if value_node.type == cs.TS_MEMBER_EXPRESSION:
216-
expr_text = safe_decode_text(value_node)
217-
if expr_text and expr_text in local_var_types:
218-
return local_var_types[expr_text]
219-
22087
if value_node.type == cs.TS_NEW_EXPRESSION:
22188
if class_name := ut.extract_constructor_name(value_node):
22289
class_qn = self._resolve_js_class_name(class_name, module_qn)

0 commit comments

Comments
 (0)