99# Tree-sitter
1010import tree_sitter_python as tspython
1111import tree_sitter_javascript as tsjavascript
12+ import tree_sitter_typescript as tstypescript
1213from tree_sitter import Language , Parser
1314
1415from services .observability import logger , metrics
@@ -22,7 +23,8 @@ def __init__(self):
2223 self .parsers = {
2324 'python' : Parser (Language (tspython .language ())),
2425 'javascript' : Parser (Language (tsjavascript .language ())),
25- 'typescript' : Parser (Language (tsjavascript .language ())),
26+ 'typescript' : Parser (Language (tstypescript .language_typescript ())),
27+ 'tsx' : Parser (Language (tstypescript .language_tsx ())),
2628 }
2729 logger .info ("DependencyAnalyzer initialized" )
2830
@@ -34,7 +36,7 @@ def _detect_language(self, file_path: str) -> str:
3436 '.js' : 'javascript' ,
3537 '.jsx' : 'javascript' ,
3638 '.ts' : 'typescript' ,
37- '.tsx' : 'typescript ' ,
39+ '.tsx' : 'tsx ' ,
3840 }
3941 return lang_map .get (ext , 'unknown' )
4042
@@ -122,8 +124,8 @@ def analyze_file_dependencies(self, file_path: str) -> Dict:
122124 logger .error ("Error analyzing file" , file_path = file_path , error = str (e ))
123125 return {"file" : str (file_path ), "imports" : [], "language" : language , "error" : str (e )}
124126
125- def build_dependency_graph (self , repo_path : str ) -> Dict :
126- """Build complete dependency graph for repository """
127+ def build_dependency_graph (self , repo_path : str , include_paths : List [ str ] = None ) -> Dict :
128+ """Build dependency graph. If include_paths set, only analyze those dirs. """
127129 repo_path = Path (repo_path )
128130
129131 # Discover code files
@@ -136,8 +138,16 @@ def build_dependency_graph(self, repo_path: str) -> Dict:
136138 continue
137139 if any (skip in file_path .parts for skip in skip_dirs ):
138140 continue
139- if file_path .suffix in extensions :
140- code_files .append (file_path )
141+ if file_path .suffix not in extensions :
142+ continue
143+ if include_paths :
144+ rel_parts = file_path .relative_to (repo_path ).parts
145+ if not any (
146+ rel_parts [:len (Path (p ).parts )] == Path (p ).parts
147+ for p in include_paths
148+ ):
149+ continue
150+ code_files .append (file_path )
141151
142152 logger .info ("Building dependency graph" , file_count = len (code_files ))
143153
@@ -236,6 +246,10 @@ def _resolve_import_to_file(
236246 source_path = Path (source_file )
237247 source_dir = source_path .parent
238248
249+ # TS imports use .js extension but actual file is .ts on disk
250+ if import_path .endswith ('.js' ) or import_path .endswith ('.jsx' ):
251+ import_path = re .sub (r'\.(jsx?)$' , '' , import_path )
252+
239253 # Relative imports
240254 if import_path .startswith ('.' ):
241255 clean_import = import_path .lstrip ('./' )
@@ -250,7 +264,7 @@ def _resolve_import_to_file(
250264 else :
251265 potential_base = source_dir / clean_import
252266
253- extensions = ['' , '.ts' , '.tsx' , '.js' , '.jsx' , '.py' ]
267+ extensions = ['' , '.ts' , '.tsx' , '.d.ts' , '. js' , '.jsx' , '.py' ]
254268
255269 for ext in extensions :
256270 # Build the potential path
@@ -269,7 +283,7 @@ def _resolve_import_to_file(
269283 if not import_path .startswith ('.' ):
270284 module_path = import_path .replace ('.' , '/' )
271285
272- for ext in ['.py ' , '.js ' , '.ts ' ]:
286+ for ext in ['' , '.ts ' , '.tsx ' , '.d.ts' , '.js' , '.jsx' , '.py ' ]:
273287 test_path = module_path + ext
274288 if test_path in internal_files :
275289 return test_path
0 commit comments