diff --git a/backend/services/dependency_analyzer.py b/backend/services/dependency_analyzer.py index a209383..927efc6 100644 --- a/backend/services/dependency_analyzer.py +++ b/backend/services/dependency_analyzer.py @@ -9,7 +9,11 @@ # Tree-sitter import tree_sitter_python as tspython import tree_sitter_javascript as tsjavascript -import tree_sitter_typescript as tstypescript +try: + import tree_sitter_typescript as tstypescript + _HAS_TS_PARSER = True +except ModuleNotFoundError: + _HAS_TS_PARSER = False from tree_sitter import Language, Parser from services.observability import logger, metrics @@ -19,14 +23,24 @@ class DependencyAnalyzer: """Analyze code dependencies and build dependency graph""" def __init__(self): - # Initialize parsers + js_lang = Language(tsjavascript.language()) + # Use proper TS parser if available, fall back to JS parser + if _HAS_TS_PARSER: + ts_lang = Language(tstypescript.language_typescript()) + tsx_lang = Language(tstypescript.language_tsx()) + else: + logger.warning("tree-sitter-typescript not installed, falling back to JS parser for TS/TSX") + ts_lang = js_lang + tsx_lang = js_lang + + self.has_ts_parser = _HAS_TS_PARSER self.parsers = { 'python': Parser(Language(tspython.language())), - 'javascript': Parser(Language(tsjavascript.language())), - 'typescript': Parser(Language(tstypescript.language_typescript())), - 'tsx': Parser(Language(tstypescript.language_tsx())), + 'javascript': Parser(js_lang), + 'typescript': Parser(ts_lang), + 'tsx': Parser(tsx_lang), } - logger.info("DependencyAnalyzer initialized") + logger.info("DependencyAnalyzer initialized", ts_parser=self.has_ts_parser) def _detect_language(self, file_path: str) -> str: """Detect language from file extension""" diff --git a/backend/tests/test_dependency_analyzer.py b/backend/tests/test_dependency_analyzer.py index 772b405..317dfe1 100644 --- a/backend/tests/test_dependency_analyzer.py +++ b/backend/tests/test_dependency_analyzer.py @@ -103,6 +103,23 @@ def test_ts_parser_is_not_js(self, analyzer): # They should be different Language objects assert ts_parser is not js_parser + def test_has_ts_parser_flag(self, analyzer): + assert analyzer.has_ts_parser is True + + def test_fallback_when_ts_parser_missing(self, monkeypatch, tmp_path): + """App must not crash if tree-sitter-typescript is missing""" + import services.dependency_analyzer as mod + monkeypatch.setattr(mod, '_HAS_TS_PARSER', False) + from services.dependency_analyzer import DependencyAnalyzer + fallback = DependencyAnalyzer() + # Should initialize without error + assert fallback.has_ts_parser is False + # Should still parse TS files (using JS fallback) + ts_file = tmp_path / "test.ts" + ts_file.write_text('import { foo } from "./bar"') + result = fallback.analyze_file_dependencies(str(ts_file)) + assert './bar' in result['imports'] + class TestLanguageDetection: """Verify file extension to language mapping"""