jarvis-ai-assistant 0.3.30__py3-none-any.whl → 0.7.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +458 -152
- jarvis/jarvis_agent/agent_manager.py +17 -13
- jarvis/jarvis_agent/builtin_input_handler.py +2 -6
- jarvis/jarvis_agent/config_editor.py +2 -7
- jarvis/jarvis_agent/event_bus.py +82 -12
- jarvis/jarvis_agent/file_context_handler.py +329 -0
- jarvis/jarvis_agent/file_methodology_manager.py +3 -4
- jarvis/jarvis_agent/jarvis.py +628 -55
- jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
- jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
- jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
- jarvis/jarvis_agent/language_support_info.py +486 -0
- jarvis/jarvis_agent/main.py +34 -10
- jarvis/jarvis_agent/memory_manager.py +7 -16
- jarvis/jarvis_agent/methodology_share_manager.py +10 -16
- jarvis/jarvis_agent/prompt_manager.py +1 -1
- jarvis/jarvis_agent/prompts.py +193 -171
- jarvis/jarvis_agent/protocols.py +8 -12
- jarvis/jarvis_agent/run_loop.py +105 -9
- jarvis/jarvis_agent/session_manager.py +2 -3
- jarvis/jarvis_agent/share_manager.py +20 -22
- jarvis/jarvis_agent/shell_input_handler.py +1 -2
- jarvis/jarvis_agent/stdio_redirect.py +295 -0
- jarvis/jarvis_agent/task_analyzer.py +31 -6
- jarvis/jarvis_agent/task_manager.py +11 -27
- jarvis/jarvis_agent/tool_executor.py +2 -3
- jarvis/jarvis_agent/tool_share_manager.py +12 -24
- jarvis/jarvis_agent/utils.py +5 -1
- jarvis/jarvis_agent/web_bridge.py +189 -0
- jarvis/jarvis_agent/web_output_sink.py +53 -0
- jarvis/jarvis_agent/web_server.py +786 -0
- jarvis/jarvis_c2rust/__init__.py +26 -0
- jarvis/jarvis_c2rust/cli.py +575 -0
- jarvis/jarvis_c2rust/collector.py +250 -0
- jarvis/jarvis_c2rust/constants.py +26 -0
- jarvis/jarvis_c2rust/library_replacer.py +1254 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +1272 -0
- jarvis/jarvis_c2rust/loaders.py +207 -0
- jarvis/jarvis_c2rust/models.py +28 -0
- jarvis/jarvis_c2rust/optimizer.py +2157 -0
- jarvis/jarvis_c2rust/scanner.py +1681 -0
- jarvis/jarvis_c2rust/transpiler.py +2983 -0
- jarvis/jarvis_c2rust/utils.py +385 -0
- jarvis/jarvis_code_agent/build_validation_config.py +132 -0
- jarvis/jarvis_code_agent/code_agent.py +1371 -220
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +65 -0
- jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +106 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +74 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +72 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +70 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +53 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +47 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +61 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +110 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +154 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +110 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +153 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +648 -0
- jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
- jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
- jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
- jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
- jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +110 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +49 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +299 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +215 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +269 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +281 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +605 -0
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +252 -0
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +58 -0
- jarvis/jarvis_code_agent/lint.py +501 -8
- jarvis/jarvis_code_agent/utils.py +141 -0
- jarvis/jarvis_code_analysis/code_review.py +493 -584
- jarvis/jarvis_data/config_schema.json +128 -12
- jarvis/jarvis_git_squash/main.py +4 -5
- jarvis/jarvis_git_utils/git_commiter.py +82 -75
- jarvis/jarvis_mcp/sse_mcp_client.py +22 -29
- jarvis/jarvis_mcp/stdio_mcp_client.py +12 -13
- jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
- jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
- jarvis/jarvis_methodology/main.py +32 -48
- jarvis/jarvis_multi_agent/__init__.py +287 -55
- jarvis/jarvis_multi_agent/main.py +36 -4
- jarvis/jarvis_platform/base.py +524 -202
- jarvis/jarvis_platform/human.py +7 -8
- jarvis/jarvis_platform/kimi.py +30 -36
- jarvis/jarvis_platform/openai.py +88 -25
- jarvis/jarvis_platform/registry.py +26 -10
- jarvis/jarvis_platform/tongyi.py +24 -25
- jarvis/jarvis_platform/yuanbao.py +32 -43
- jarvis/jarvis_platform_manager/main.py +66 -77
- jarvis/jarvis_platform_manager/service.py +8 -13
- jarvis/jarvis_rag/cli.py +53 -55
- jarvis/jarvis_rag/embedding_manager.py +13 -18
- jarvis/jarvis_rag/llm_interface.py +8 -9
- jarvis/jarvis_rag/query_rewriter.py +10 -21
- jarvis/jarvis_rag/rag_pipeline.py +24 -27
- jarvis/jarvis_rag/reranker.py +4 -5
- jarvis/jarvis_rag/retriever.py +28 -30
- jarvis/jarvis_sec/__init__.py +305 -0
- jarvis/jarvis_sec/agents.py +143 -0
- jarvis/jarvis_sec/analysis.py +276 -0
- jarvis/jarvis_sec/checkers/__init__.py +32 -0
- jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
- jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
- jarvis/jarvis_sec/cli.py +139 -0
- jarvis/jarvis_sec/clustering.py +1439 -0
- jarvis/jarvis_sec/file_manager.py +427 -0
- jarvis/jarvis_sec/parsers.py +73 -0
- jarvis/jarvis_sec/prompts.py +268 -0
- jarvis/jarvis_sec/report.py +336 -0
- jarvis/jarvis_sec/review.py +453 -0
- jarvis/jarvis_sec/status.py +264 -0
- jarvis/jarvis_sec/types.py +20 -0
- jarvis/jarvis_sec/utils.py +499 -0
- jarvis/jarvis_sec/verification.py +848 -0
- jarvis/jarvis_sec/workflow.py +226 -0
- jarvis/jarvis_smart_shell/main.py +38 -87
- jarvis/jarvis_stats/cli.py +2 -2
- jarvis/jarvis_stats/stats.py +8 -8
- jarvis/jarvis_stats/storage.py +15 -21
- jarvis/jarvis_stats/visualizer.py +1 -1
- jarvis/jarvis_tools/clear_memory.py +3 -20
- jarvis/jarvis_tools/cli/main.py +21 -23
- jarvis/jarvis_tools/edit_file.py +1019 -132
- jarvis/jarvis_tools/execute_script.py +83 -25
- jarvis/jarvis_tools/file_analyzer.py +6 -9
- jarvis/jarvis_tools/generate_new_tool.py +14 -21
- jarvis/jarvis_tools/lsp_client.py +1552 -0
- jarvis/jarvis_tools/methodology.py +2 -3
- jarvis/jarvis_tools/read_code.py +1736 -35
- jarvis/jarvis_tools/read_symbols.py +140 -0
- jarvis/jarvis_tools/read_webpage.py +12 -13
- jarvis/jarvis_tools/registry.py +427 -200
- jarvis/jarvis_tools/retrieve_memory.py +20 -19
- jarvis/jarvis_tools/rewrite_file.py +72 -158
- jarvis/jarvis_tools/save_memory.py +3 -15
- jarvis/jarvis_tools/search_web.py +18 -18
- jarvis/jarvis_tools/sub_agent.py +36 -43
- jarvis/jarvis_tools/sub_code_agent.py +25 -26
- jarvis/jarvis_tools/virtual_tty.py +55 -33
- jarvis/jarvis_utils/clipboard.py +7 -10
- jarvis/jarvis_utils/config.py +232 -45
- jarvis/jarvis_utils/embedding.py +8 -5
- jarvis/jarvis_utils/fzf.py +8 -8
- jarvis/jarvis_utils/git_utils.py +225 -36
- jarvis/jarvis_utils/globals.py +3 -3
- jarvis/jarvis_utils/http.py +1 -1
- jarvis/jarvis_utils/input.py +99 -48
- jarvis/jarvis_utils/jsonnet_compat.py +465 -0
- jarvis/jarvis_utils/methodology.py +52 -48
- jarvis/jarvis_utils/utils.py +819 -491
- jarvis_ai_assistant-0.7.6.dist-info/METADATA +600 -0
- jarvis_ai_assistant-0.7.6.dist-info/RECORD +218 -0
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/entry_points.txt +4 -0
- jarvis/jarvis_agent/config.py +0 -92
- jarvis/jarvis_agent/edit_file_handler.py +0 -296
- jarvis/jarvis_platform/ai8.py +0 -332
- jarvis/jarvis_tools/ask_user.py +0 -54
- jarvis_ai_assistant-0.3.30.dist-info/METADATA +0 -381
- jarvis_ai_assistant-0.3.30.dist-info/RECORD +0 -137
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"""TypeScript语言支持实现。"""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import re
|
|
5
|
+
from typing import List, Optional, Set
|
|
6
|
+
|
|
7
|
+
from ..base_language import BaseLanguageSupport
|
|
8
|
+
from ..dependency_analyzer import Dependency, DependencyAnalyzer, DependencyGraph
|
|
9
|
+
from ..file_ignore import filter_walk_dirs
|
|
10
|
+
from ..symbol_extractor import Symbol, SymbolExtractor
|
|
11
|
+
from ..tree_sitter_extractor import TreeSitterExtractor
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from tree_sitter import Language, Node
|
|
15
|
+
import tree_sitter_typescript
|
|
16
|
+
TS_LANGUAGE: Optional[Language] = tree_sitter_typescript.language_typescript()
|
|
17
|
+
except (ImportError, Exception):
|
|
18
|
+
TS_LANGUAGE = None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# --- TypeScript Symbol Extractor ---
|
|
22
|
+
|
|
23
|
+
TS_SYMBOL_QUERY = """
|
|
24
|
+
(function_declaration
|
|
25
|
+
name: (identifier) @function.name)
|
|
26
|
+
|
|
27
|
+
(function_expression
|
|
28
|
+
name: (identifier) @function.name)
|
|
29
|
+
|
|
30
|
+
(generator_function_declaration
|
|
31
|
+
name: (identifier) @generator.name)
|
|
32
|
+
|
|
33
|
+
(generator_function
|
|
34
|
+
name: (identifier) @generator.name)
|
|
35
|
+
|
|
36
|
+
(arrow_function) @arrow.function
|
|
37
|
+
|
|
38
|
+
(method_definition
|
|
39
|
+
name: (property_identifier) @method.name)
|
|
40
|
+
|
|
41
|
+
(class_declaration
|
|
42
|
+
name: (type_identifier) @class.name)
|
|
43
|
+
|
|
44
|
+
(class_expression
|
|
45
|
+
name: (type_identifier) @class.name)
|
|
46
|
+
|
|
47
|
+
(interface_declaration
|
|
48
|
+
name: (type_identifier) @interface.name)
|
|
49
|
+
|
|
50
|
+
(enum_declaration
|
|
51
|
+
name: (identifier) @enum.name)
|
|
52
|
+
|
|
53
|
+
(type_alias_declaration
|
|
54
|
+
name: (type_identifier) @type.name)
|
|
55
|
+
|
|
56
|
+
(namespace_declaration
|
|
57
|
+
name: (identifier) @namespace.name)
|
|
58
|
+
|
|
59
|
+
(variable_declaration
|
|
60
|
+
(variable_declarator
|
|
61
|
+
name: (identifier) @variable.name))
|
|
62
|
+
|
|
63
|
+
(decorator) @decorator
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TypeScriptSymbolExtractor(TreeSitterExtractor):
|
|
68
|
+
"""Extracts symbols from TypeScript code using tree-sitter."""
|
|
69
|
+
|
|
70
|
+
def __init__(self):
|
|
71
|
+
if not TS_LANGUAGE:
|
|
72
|
+
raise RuntimeError("TypeScript tree-sitter grammar not available.")
|
|
73
|
+
# 如果传入的是 PyCapsule,需要转换为 Language 对象
|
|
74
|
+
if not isinstance(TS_LANGUAGE, Language):
|
|
75
|
+
lang = Language(TS_LANGUAGE)
|
|
76
|
+
else:
|
|
77
|
+
lang = TS_LANGUAGE
|
|
78
|
+
super().__init__(lang, TS_SYMBOL_QUERY)
|
|
79
|
+
|
|
80
|
+
def _create_symbol_from_capture(self, node: Node, name: str, file_path: str) -> Optional[Symbol]:
|
|
81
|
+
"""Maps a tree-sitter capture to a Symbol object."""
|
|
82
|
+
kind_map = {
|
|
83
|
+
"function.name": "function",
|
|
84
|
+
"arrow.function": "function",
|
|
85
|
+
"generator.name": "function",
|
|
86
|
+
"method.name": "method",
|
|
87
|
+
"class.name": "class",
|
|
88
|
+
"interface.name": "interface",
|
|
89
|
+
"enum.name": "enum",
|
|
90
|
+
"type.name": "type",
|
|
91
|
+
"namespace.name": "namespace",
|
|
92
|
+
"variable.name": "variable",
|
|
93
|
+
"decorator": "decorator",
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
symbol_kind = kind_map.get(name)
|
|
97
|
+
if not symbol_kind:
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
# For arrow functions without names, use a generated name
|
|
101
|
+
if name == "arrow.function":
|
|
102
|
+
symbol_name = "<anonymous_arrow_function>"
|
|
103
|
+
elif name == "decorator":
|
|
104
|
+
# Extract decorator name (e.g., @Component -> Component)
|
|
105
|
+
decorator_text = node.text.decode('utf8').strip()
|
|
106
|
+
if decorator_text.startswith('@'):
|
|
107
|
+
symbol_name = decorator_text[1:].split('(')[0].strip()
|
|
108
|
+
else:
|
|
109
|
+
symbol_name = decorator_text.split('(')[0].strip()
|
|
110
|
+
elif name == "generator.name":
|
|
111
|
+
symbol_name = node.text.decode('utf8')
|
|
112
|
+
else:
|
|
113
|
+
symbol_name = node.text.decode('utf8')
|
|
114
|
+
|
|
115
|
+
if not symbol_name:
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
return Symbol(
|
|
119
|
+
name=symbol_name,
|
|
120
|
+
kind=symbol_kind,
|
|
121
|
+
file_path=file_path,
|
|
122
|
+
line_start=node.start_point[0] + 1,
|
|
123
|
+
line_end=node.end_point[0] + 1,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# --- TypeScript Dependency Analyzer ---
|
|
128
|
+
|
|
129
|
+
class TypeScriptDependencyAnalyzer(DependencyAnalyzer):
|
|
130
|
+
"""Analyzes TypeScript import dependencies."""
|
|
131
|
+
|
|
132
|
+
def analyze_imports(self, file_path: str, content: str) -> List[Dependency]:
|
|
133
|
+
"""Analyzes TypeScript import statements."""
|
|
134
|
+
dependencies: List[Dependency] = []
|
|
135
|
+
|
|
136
|
+
# ES6 import statements (same as JavaScript)
|
|
137
|
+
# import module from 'path'
|
|
138
|
+
# import { symbol } from 'path'
|
|
139
|
+
# import * as alias from 'path'
|
|
140
|
+
# import type { Type } from 'path'
|
|
141
|
+
import_pattern = re.compile(
|
|
142
|
+
r'import\s+(?:type\s+)?(?:(?:\*\s+as\s+(\w+)|(\{[^}]*\})|(\w+))\s+from\s+)?["\']([^"\']+)["\']',
|
|
143
|
+
re.MULTILINE
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# CommonJS require statements
|
|
147
|
+
require_pattern = re.compile(
|
|
148
|
+
r'(?:const|let|var)\s+\w+\s*=\s*require\(["\']([^"\']+)["\']\)|require\(["\']([^"\']+)["\']\)',
|
|
149
|
+
re.MULTILINE
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
for line_num, line in enumerate(content.split('\n'), start=1):
|
|
153
|
+
# Check for ES6 imports
|
|
154
|
+
import_match = import_pattern.search(line)
|
|
155
|
+
if import_match:
|
|
156
|
+
module_path = import_match.group(4) or import_match.group(5)
|
|
157
|
+
if module_path:
|
|
158
|
+
# Extract imported symbols if any
|
|
159
|
+
symbols_group = import_match.group(2) or import_match.group(1)
|
|
160
|
+
imported_symbol = None
|
|
161
|
+
if symbols_group and symbols_group.startswith('{'):
|
|
162
|
+
# Extract first symbol from { symbol1, symbol2 }
|
|
163
|
+
symbol_match = re.search(r'\{([^}]+)\}', symbols_group)
|
|
164
|
+
if symbol_match:
|
|
165
|
+
first_symbol = symbol_match.group(1).split(',')[0].strip()
|
|
166
|
+
imported_symbol = first_symbol.split(' as ')[0].strip()
|
|
167
|
+
|
|
168
|
+
dependencies.append(Dependency(
|
|
169
|
+
from_module=module_path,
|
|
170
|
+
imported_symbol=imported_symbol,
|
|
171
|
+
file_path=file_path,
|
|
172
|
+
line=line_num,
|
|
173
|
+
))
|
|
174
|
+
|
|
175
|
+
# Check for require statements
|
|
176
|
+
require_match = require_pattern.search(line)
|
|
177
|
+
if require_match:
|
|
178
|
+
module_path = require_match.group(1) or require_match.group(2)
|
|
179
|
+
if module_path:
|
|
180
|
+
dependencies.append(Dependency(
|
|
181
|
+
from_module=module_path,
|
|
182
|
+
imported_symbol=None,
|
|
183
|
+
file_path=file_path,
|
|
184
|
+
line=line_num,
|
|
185
|
+
))
|
|
186
|
+
|
|
187
|
+
return dependencies
|
|
188
|
+
|
|
189
|
+
def build_dependency_graph(self, project_root: str) -> DependencyGraph:
|
|
190
|
+
"""Builds a dependency graph for a TypeScript project."""
|
|
191
|
+
graph = DependencyGraph()
|
|
192
|
+
|
|
193
|
+
for root, dirs, files in os.walk(project_root):
|
|
194
|
+
dirs[:] = filter_walk_dirs(dirs)
|
|
195
|
+
|
|
196
|
+
for file in files:
|
|
197
|
+
if not file.endswith(('.ts', '.tsx', '.cts', '.mts')):
|
|
198
|
+
continue
|
|
199
|
+
|
|
200
|
+
file_path = os.path.join(root, file)
|
|
201
|
+
try:
|
|
202
|
+
with open(file_path, 'r', encoding='utf-8', errors='replace') as f:
|
|
203
|
+
content = f.read()
|
|
204
|
+
|
|
205
|
+
dependencies = self.analyze_imports(file_path, content)
|
|
206
|
+
for dep in dependencies:
|
|
207
|
+
# Skip node_modules and external packages
|
|
208
|
+
if dep.from_module.startswith(('.', '/')) or not dep.from_module.startswith('http'):
|
|
209
|
+
dep_path = self._resolve_module_path(project_root, dep.from_module, file_path)
|
|
210
|
+
if dep_path and dep_path != file_path:
|
|
211
|
+
graph.add_dependency(file_path, dep_path)
|
|
212
|
+
except Exception:
|
|
213
|
+
continue
|
|
214
|
+
|
|
215
|
+
return graph
|
|
216
|
+
|
|
217
|
+
def _resolve_module_path(self, project_root: str, module_name: str, from_file: str) -> Optional[str]:
|
|
218
|
+
"""Resolve a TypeScript module name to a file path."""
|
|
219
|
+
if not module_name:
|
|
220
|
+
return None
|
|
221
|
+
|
|
222
|
+
# Handle relative imports
|
|
223
|
+
if module_name.startswith('.'):
|
|
224
|
+
base_dir = os.path.dirname(from_file)
|
|
225
|
+
# Resolve relative path
|
|
226
|
+
if module_name.endswith(('.ts', '.tsx')):
|
|
227
|
+
# Direct file reference
|
|
228
|
+
resolved = os.path.normpath(os.path.join(base_dir, module_name))
|
|
229
|
+
else:
|
|
230
|
+
# Try with .ts extension
|
|
231
|
+
resolved = os.path.normpath(os.path.join(base_dir, module_name + '.ts'))
|
|
232
|
+
if not os.path.exists(resolved):
|
|
233
|
+
# Try with .tsx extension
|
|
234
|
+
resolved = os.path.normpath(os.path.join(base_dir, module_name + '.tsx'))
|
|
235
|
+
if not os.path.exists(resolved):
|
|
236
|
+
# Try index.ts
|
|
237
|
+
resolved = os.path.normpath(os.path.join(base_dir, module_name, 'index.ts'))
|
|
238
|
+
if not os.path.exists(resolved):
|
|
239
|
+
resolved = os.path.normpath(os.path.join(base_dir, module_name, 'index.tsx'))
|
|
240
|
+
|
|
241
|
+
if os.path.exists(resolved) and os.path.isfile(resolved):
|
|
242
|
+
return resolved
|
|
243
|
+
|
|
244
|
+
# Handle absolute imports (from project root)
|
|
245
|
+
if module_name.startswith('/'):
|
|
246
|
+
resolved = os.path.normpath(os.path.join(project_root, module_name.lstrip('/')))
|
|
247
|
+
if not resolved.endswith(('.ts', '.tsx')):
|
|
248
|
+
resolved += '.ts'
|
|
249
|
+
if os.path.exists(resolved) and os.path.isfile(resolved):
|
|
250
|
+
return resolved
|
|
251
|
+
|
|
252
|
+
# For node_modules and external packages, we can't resolve without package.json
|
|
253
|
+
# Return None to skip them
|
|
254
|
+
return None
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
# --- TypeScript Language Support ---
|
|
258
|
+
|
|
259
|
+
class TypeScriptLanguageSupport(BaseLanguageSupport):
|
|
260
|
+
"""TypeScript语言支持。"""
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def language_name(self) -> str:
|
|
264
|
+
return "typescript"
|
|
265
|
+
|
|
266
|
+
@property
|
|
267
|
+
def file_extensions(self) -> Set[str]:
|
|
268
|
+
return {'.ts', '.tsx', '.cts', '.mts'}
|
|
269
|
+
|
|
270
|
+
def create_symbol_extractor(self) -> Optional[SymbolExtractor]:
|
|
271
|
+
if not TS_LANGUAGE:
|
|
272
|
+
return None
|
|
273
|
+
try:
|
|
274
|
+
return TypeScriptSymbolExtractor()
|
|
275
|
+
except Exception:
|
|
276
|
+
return None
|
|
277
|
+
|
|
278
|
+
def create_dependency_analyzer(self) -> Optional[DependencyAnalyzer]:
|
|
279
|
+
return TypeScriptDependencyAnalyzer()
|
|
280
|
+
|