jarvis-ai-assistant 0.1.222__py3-none-any.whl → 0.7.0__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 +1143 -245
- jarvis/jarvis_agent/agent_manager.py +97 -0
- jarvis/jarvis_agent/builtin_input_handler.py +12 -10
- jarvis/jarvis_agent/config_editor.py +57 -0
- jarvis/jarvis_agent/edit_file_handler.py +392 -99
- jarvis/jarvis_agent/event_bus.py +48 -0
- jarvis/jarvis_agent/events.py +157 -0
- jarvis/jarvis_agent/file_context_handler.py +79 -0
- jarvis/jarvis_agent/file_methodology_manager.py +117 -0
- jarvis/jarvis_agent/jarvis.py +1117 -147
- jarvis/jarvis_agent/main.py +78 -34
- jarvis/jarvis_agent/memory_manager.py +195 -0
- jarvis/jarvis_agent/methodology_share_manager.py +174 -0
- jarvis/jarvis_agent/prompt_manager.py +82 -0
- jarvis/jarvis_agent/prompts.py +46 -9
- jarvis/jarvis_agent/protocols.py +4 -1
- jarvis/jarvis_agent/rewrite_file_handler.py +141 -0
- jarvis/jarvis_agent/run_loop.py +146 -0
- jarvis/jarvis_agent/session_manager.py +9 -9
- jarvis/jarvis_agent/share_manager.py +228 -0
- jarvis/jarvis_agent/shell_input_handler.py +23 -3
- jarvis/jarvis_agent/stdio_redirect.py +295 -0
- jarvis/jarvis_agent/task_analyzer.py +212 -0
- jarvis/jarvis_agent/task_manager.py +154 -0
- jarvis/jarvis_agent/task_planner.py +496 -0
- jarvis/jarvis_agent/tool_executor.py +8 -4
- jarvis/jarvis_agent/tool_share_manager.py +139 -0
- jarvis/jarvis_agent/user_interaction.py +42 -0
- jarvis/jarvis_agent/utils.py +54 -0
- jarvis/jarvis_agent/web_bridge.py +189 -0
- jarvis/jarvis_agent/web_output_sink.py +53 -0
- jarvis/jarvis_agent/web_server.py +751 -0
- jarvis/jarvis_c2rust/__init__.py +26 -0
- jarvis/jarvis_c2rust/cli.py +613 -0
- jarvis/jarvis_c2rust/collector.py +258 -0
- jarvis/jarvis_c2rust/library_replacer.py +1122 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +1300 -0
- jarvis/jarvis_c2rust/optimizer.py +960 -0
- jarvis/jarvis_c2rust/scanner.py +1681 -0
- jarvis/jarvis_c2rust/transpiler.py +2325 -0
- jarvis/jarvis_code_agent/build_validation_config.py +133 -0
- jarvis/jarvis_code_agent/code_agent.py +1605 -178
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +62 -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 +102 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +59 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +69 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +38 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +44 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +38 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +50 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +93 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +129 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +54 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +154 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +363 -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 +89 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +31 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +231 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +183 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +219 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +209 -0
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +451 -0
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +77 -0
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +48 -0
- jarvis/jarvis_code_agent/lint.py +275 -13
- jarvis/jarvis_code_agent/utils.py +142 -0
- jarvis/jarvis_code_analysis/checklists/loader.py +20 -6
- jarvis/jarvis_code_analysis/code_review.py +583 -548
- jarvis/jarvis_data/config_schema.json +339 -28
- jarvis/jarvis_git_squash/main.py +22 -13
- jarvis/jarvis_git_utils/git_commiter.py +171 -55
- jarvis/jarvis_mcp/sse_mcp_client.py +22 -15
- jarvis/jarvis_mcp/stdio_mcp_client.py +4 -4
- jarvis/jarvis_mcp/streamable_mcp_client.py +36 -16
- jarvis/jarvis_memory_organizer/memory_organizer.py +753 -0
- jarvis/jarvis_methodology/main.py +48 -63
- jarvis/jarvis_multi_agent/__init__.py +302 -43
- jarvis/jarvis_multi_agent/main.py +70 -24
- jarvis/jarvis_platform/ai8.py +40 -23
- jarvis/jarvis_platform/base.py +210 -49
- jarvis/jarvis_platform/human.py +11 -1
- jarvis/jarvis_platform/kimi.py +82 -76
- jarvis/jarvis_platform/openai.py +73 -1
- jarvis/jarvis_platform/registry.py +8 -15
- jarvis/jarvis_platform/tongyi.py +115 -101
- jarvis/jarvis_platform/yuanbao.py +89 -63
- jarvis/jarvis_platform_manager/main.py +194 -132
- jarvis/jarvis_platform_manager/service.py +122 -86
- jarvis/jarvis_rag/cli.py +156 -53
- jarvis/jarvis_rag/embedding_manager.py +155 -12
- jarvis/jarvis_rag/llm_interface.py +10 -13
- jarvis/jarvis_rag/query_rewriter.py +63 -12
- jarvis/jarvis_rag/rag_pipeline.py +222 -40
- jarvis/jarvis_rag/reranker.py +26 -3
- jarvis/jarvis_rag/retriever.py +270 -14
- jarvis/jarvis_sec/__init__.py +3605 -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 +116 -0
- jarvis/jarvis_sec/report.py +257 -0
- jarvis/jarvis_sec/status.py +264 -0
- jarvis/jarvis_sec/types.py +20 -0
- jarvis/jarvis_sec/workflow.py +219 -0
- jarvis/jarvis_smart_shell/main.py +405 -137
- jarvis/jarvis_stats/__init__.py +13 -0
- jarvis/jarvis_stats/cli.py +387 -0
- jarvis/jarvis_stats/stats.py +711 -0
- jarvis/jarvis_stats/storage.py +612 -0
- jarvis/jarvis_stats/visualizer.py +282 -0
- jarvis/jarvis_tools/ask_user.py +1 -0
- jarvis/jarvis_tools/base.py +18 -2
- jarvis/jarvis_tools/clear_memory.py +239 -0
- jarvis/jarvis_tools/cli/main.py +220 -144
- jarvis/jarvis_tools/execute_script.py +52 -12
- jarvis/jarvis_tools/file_analyzer.py +17 -12
- jarvis/jarvis_tools/generate_new_tool.py +46 -24
- jarvis/jarvis_tools/read_code.py +277 -18
- jarvis/jarvis_tools/read_symbols.py +141 -0
- jarvis/jarvis_tools/read_webpage.py +86 -13
- jarvis/jarvis_tools/registry.py +294 -90
- jarvis/jarvis_tools/retrieve_memory.py +227 -0
- jarvis/jarvis_tools/save_memory.py +194 -0
- jarvis/jarvis_tools/search_web.py +62 -28
- jarvis/jarvis_tools/sub_agent.py +205 -0
- jarvis/jarvis_tools/sub_code_agent.py +217 -0
- jarvis/jarvis_tools/virtual_tty.py +330 -62
- jarvis/jarvis_utils/builtin_replace_map.py +4 -5
- jarvis/jarvis_utils/clipboard.py +90 -0
- jarvis/jarvis_utils/config.py +607 -50
- jarvis/jarvis_utils/embedding.py +3 -0
- jarvis/jarvis_utils/fzf.py +57 -0
- jarvis/jarvis_utils/git_utils.py +251 -29
- jarvis/jarvis_utils/globals.py +174 -17
- jarvis/jarvis_utils/http.py +58 -79
- jarvis/jarvis_utils/input.py +899 -153
- jarvis/jarvis_utils/methodology.py +210 -83
- jarvis/jarvis_utils/output.py +220 -137
- jarvis/jarvis_utils/utils.py +1906 -135
- jarvis_ai_assistant-0.7.0.dist-info/METADATA +465 -0
- jarvis_ai_assistant-0.7.0.dist-info/RECORD +192 -0
- {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/entry_points.txt +8 -2
- jarvis/jarvis_git_details/main.py +0 -265
- jarvis/jarvis_platform/oyi.py +0 -357
- jarvis/jarvis_tools/edit_file.py +0 -255
- jarvis/jarvis_tools/rewrite_file.py +0 -195
- jarvis_ai_assistant-0.1.222.dist-info/METADATA +0 -767
- jarvis_ai_assistant-0.1.222.dist-info/RECORD +0 -110
- /jarvis/{jarvis_git_details → jarvis_memory_organizer}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""语言注册表。
|
|
2
|
+
|
|
3
|
+
管理所有语言支持的注册和发现机制。
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
from typing import Dict, Optional, Set
|
|
8
|
+
|
|
9
|
+
from .base_language import BaseLanguageSupport
|
|
10
|
+
from .dependency_analyzer import DependencyAnalyzer
|
|
11
|
+
from .symbol_extractor import SymbolExtractor
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LanguageRegistry:
|
|
15
|
+
"""语言支持注册表。
|
|
16
|
+
|
|
17
|
+
负责管理所有已注册的语言支持,提供语言检测和工厂方法。
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self):
|
|
21
|
+
self._languages: Dict[str, BaseLanguageSupport] = {}
|
|
22
|
+
self._extension_map: Dict[str, str] = {} # extension -> language_name
|
|
23
|
+
|
|
24
|
+
def register(self, language_support: BaseLanguageSupport) -> None:
|
|
25
|
+
"""注册一个语言支持。
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
language_support: 语言支持实例
|
|
29
|
+
"""
|
|
30
|
+
lang_name = language_support.language_name
|
|
31
|
+
self._languages[lang_name] = language_support
|
|
32
|
+
|
|
33
|
+
# 注册文件扩展名映射
|
|
34
|
+
for ext in language_support.file_extensions:
|
|
35
|
+
# 如果扩展名已存在,记录警告但不覆盖(保留第一个注册的)
|
|
36
|
+
if ext in self._extension_map and self._extension_map[ext] != lang_name:
|
|
37
|
+
print(f"Warning: Extension {ext} already registered for "
|
|
38
|
+
f"{self._extension_map[ext]}, ignoring registration for {lang_name}")
|
|
39
|
+
else:
|
|
40
|
+
self._extension_map[ext] = lang_name
|
|
41
|
+
|
|
42
|
+
def unregister(self, language_name: str) -> None:
|
|
43
|
+
"""取消注册一个语言支持。
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
language_name: 语言名称
|
|
47
|
+
"""
|
|
48
|
+
if language_name in self._languages:
|
|
49
|
+
self._languages.pop(language_name)
|
|
50
|
+
# 移除扩展名映射
|
|
51
|
+
extensions_to_remove = [
|
|
52
|
+
ext for ext, lang in self._extension_map.items()
|
|
53
|
+
if lang == language_name
|
|
54
|
+
]
|
|
55
|
+
for ext in extensions_to_remove:
|
|
56
|
+
del self._extension_map[ext]
|
|
57
|
+
|
|
58
|
+
def detect_language(self, file_path: str) -> Optional[str]:
|
|
59
|
+
"""根据文件路径检测编程语言。
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
file_path: 文件路径
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
语言名称,如果无法检测则返回None
|
|
66
|
+
"""
|
|
67
|
+
_, ext = os.path.splitext(file_path)
|
|
68
|
+
return self._extension_map.get(ext)
|
|
69
|
+
|
|
70
|
+
def get_language_support(self, language_name: str) -> Optional[BaseLanguageSupport]:
|
|
71
|
+
"""获取指定语言的支持实例。
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
language_name: 语言名称
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
语言支持实例,如果未注册则返回None
|
|
78
|
+
"""
|
|
79
|
+
return self._languages.get(language_name)
|
|
80
|
+
|
|
81
|
+
def get_symbol_extractor(self, language_name: str) -> Optional[SymbolExtractor]:
|
|
82
|
+
"""获取指定语言的符号提取器。
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
language_name: 语言名称
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
SymbolExtractor实例,如果不支持则返回None
|
|
89
|
+
"""
|
|
90
|
+
lang_support = self.get_language_support(language_name)
|
|
91
|
+
if lang_support:
|
|
92
|
+
return lang_support.create_symbol_extractor()
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
def get_dependency_analyzer(self, language_name: str) -> Optional[DependencyAnalyzer]:
|
|
96
|
+
"""获取指定语言的依赖分析器。
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
language_name: 语言名称
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
DependencyAnalyzer实例,如果不支持则返回None
|
|
103
|
+
"""
|
|
104
|
+
lang_support = self.get_language_support(language_name)
|
|
105
|
+
if lang_support:
|
|
106
|
+
return lang_support.create_dependency_analyzer()
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
def get_supported_languages(self) -> Set[str]:
|
|
110
|
+
"""获取所有已注册的语言名称集合。
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
语言名称集合
|
|
114
|
+
"""
|
|
115
|
+
return set(self._languages.keys())
|
|
116
|
+
|
|
117
|
+
def is_supported(self, file_path: str) -> bool:
|
|
118
|
+
"""检查文件是否被支持。
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
file_path: 文件路径
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
如果文件被支持返回True,否则返回False
|
|
125
|
+
"""
|
|
126
|
+
return self.detect_language(file_path) is not None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# 全局注册表实例
|
|
130
|
+
_registry = LanguageRegistry()
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def get_registry() -> LanguageRegistry:
|
|
134
|
+
"""获取全局语言注册表实例。
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
全局LanguageRegistry实例
|
|
138
|
+
"""
|
|
139
|
+
return _registry
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def register_language(language_support: BaseLanguageSupport) -> None:
|
|
143
|
+
"""注册一个语言支持(便捷函数)。
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
language_support: 语言支持实例
|
|
147
|
+
"""
|
|
148
|
+
_registry.register(language_support)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def detect_language(file_path: str) -> Optional[str]:
|
|
152
|
+
"""检测文件的语言(便捷函数)。
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
file_path: 文件路径
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
语言名称,如果无法检测则返回None
|
|
159
|
+
"""
|
|
160
|
+
return _registry.detect_language(file_path)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def get_symbol_extractor(language: str) -> Optional[SymbolExtractor]:
|
|
164
|
+
"""获取指定语言的符号提取器(便捷函数)。
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
language: 语言名称
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
SymbolExtractor实例,如果不支持则返回None
|
|
171
|
+
"""
|
|
172
|
+
return _registry.get_symbol_extractor(language)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def get_dependency_analyzer(language: str) -> Optional[DependencyAnalyzer]:
|
|
176
|
+
"""获取指定语言的依赖分析器(便捷函数)。
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
language: 语言名称
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
DependencyAnalyzer实例,如果不支持则返回None
|
|
183
|
+
"""
|
|
184
|
+
return _registry.get_dependency_analyzer(language)
|
|
185
|
+
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""语言支持模块。
|
|
2
|
+
|
|
3
|
+
提供语言检测和工厂函数,使用语言注册表管理所有语言支持。
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from .dependency_analyzer import DependencyAnalyzer
|
|
9
|
+
from .language_registry import (
|
|
10
|
+
detect_language as _detect_language,
|
|
11
|
+
get_dependency_analyzer as _get_dependency_analyzer,
|
|
12
|
+
get_symbol_extractor as _get_symbol_extractor,
|
|
13
|
+
register_language,
|
|
14
|
+
)
|
|
15
|
+
from .symbol_extractor import SymbolExtractor
|
|
16
|
+
|
|
17
|
+
# 自动注册所有语言支持
|
|
18
|
+
# 使用try-except确保某个语言支持导入失败不影响其他语言
|
|
19
|
+
|
|
20
|
+
# Python语言支持(必需,因为它是核心语言)
|
|
21
|
+
try:
|
|
22
|
+
from .languages import PythonLanguageSupport
|
|
23
|
+
register_language(PythonLanguageSupport())
|
|
24
|
+
except ImportError as e:
|
|
25
|
+
print(f"Warning: Failed to import PythonLanguageSupport: {e}")
|
|
26
|
+
|
|
27
|
+
# Rust语言支持(可选,需要tree-sitter)
|
|
28
|
+
try:
|
|
29
|
+
from .languages import RustLanguageSupport
|
|
30
|
+
register_language(RustLanguageSupport())
|
|
31
|
+
except (ImportError, RuntimeError):
|
|
32
|
+
pass # 静默失败,tree-sitter可能不可用
|
|
33
|
+
|
|
34
|
+
# Go语言支持(可选,需要tree-sitter)
|
|
35
|
+
try:
|
|
36
|
+
from .languages import GoLanguageSupport
|
|
37
|
+
register_language(GoLanguageSupport())
|
|
38
|
+
except (ImportError, RuntimeError):
|
|
39
|
+
pass # 静默失败,tree-sitter可能不可用
|
|
40
|
+
|
|
41
|
+
# C语言支持(可选,需要tree-sitter)
|
|
42
|
+
try:
|
|
43
|
+
from .languages import CLanguageSupport
|
|
44
|
+
register_language(CLanguageSupport())
|
|
45
|
+
except (ImportError, RuntimeError):
|
|
46
|
+
pass # 静默失败,tree-sitter可能不可用
|
|
47
|
+
|
|
48
|
+
# C++语言支持(可选,需要tree-sitter)
|
|
49
|
+
try:
|
|
50
|
+
from .languages import CppLanguageSupport
|
|
51
|
+
register_language(CppLanguageSupport())
|
|
52
|
+
except (ImportError, RuntimeError):
|
|
53
|
+
pass # 静默失败,tree-sitter可能不可用
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def detect_language(file_path: str) -> Optional[str]:
|
|
57
|
+
"""检测文件的编程语言。
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
file_path: 文件路径
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
语言名称,如果无法检测则返回None
|
|
64
|
+
"""
|
|
65
|
+
return _detect_language(file_path)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_symbol_extractor(language: str) -> Optional[SymbolExtractor]:
|
|
69
|
+
"""获取指定语言的符号提取器。
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
language: 语言名称
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
SymbolExtractor实例,如果不支持则返回None
|
|
76
|
+
"""
|
|
77
|
+
return _get_symbol_extractor(language)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_dependency_analyzer(language: str) -> Optional[DependencyAnalyzer]:
|
|
81
|
+
"""获取指定语言的依赖分析器。
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
language: 语言名称
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
DependencyAnalyzer实例,如果不支持则返回None
|
|
88
|
+
"""
|
|
89
|
+
return _get_dependency_analyzer(language)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""语言支持实现模块。
|
|
2
|
+
|
|
3
|
+
包含各种编程语言的支持实现。
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# 导入所有语言支持类,以便自动注册
|
|
7
|
+
# 使用try-except确保某个语言支持导入失败不影响其他语言
|
|
8
|
+
|
|
9
|
+
from .python_language import PythonLanguageSupport
|
|
10
|
+
|
|
11
|
+
__all__ = ['PythonLanguageSupport']
|
|
12
|
+
|
|
13
|
+
# 尝试导入tree-sitter相关的语言支持
|
|
14
|
+
try:
|
|
15
|
+
from .rust_language import RustLanguageSupport
|
|
16
|
+
__all__.append('RustLanguageSupport')
|
|
17
|
+
except (ImportError, RuntimeError):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
from .go_language import GoLanguageSupport
|
|
22
|
+
__all__.append('GoLanguageSupport')
|
|
23
|
+
except (ImportError, RuntimeError):
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
from .c_cpp_language import CLanguageSupport, CppLanguageSupport
|
|
28
|
+
__all__.extend(['CLanguageSupport', 'CppLanguageSupport'])
|
|
29
|
+
except (ImportError, RuntimeError):
|
|
30
|
+
pass
|
|
31
|
+
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"""C/C++语言支持实现。"""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import re
|
|
5
|
+
from typing import List, Optional, Set
|
|
6
|
+
|
|
7
|
+
from tree_sitter import Language, Node
|
|
8
|
+
|
|
9
|
+
from ..base_language import BaseLanguageSupport
|
|
10
|
+
from ..dependency_analyzer import Dependency, DependencyAnalyzer, DependencyGraph
|
|
11
|
+
from ..file_ignore import filter_walk_dirs
|
|
12
|
+
from ..symbol_extractor import Symbol, SymbolExtractor
|
|
13
|
+
from ..tree_sitter_extractor import TreeSitterExtractor
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# --- C/C++ Symbol Query ---
|
|
17
|
+
|
|
18
|
+
C_CPP_SYMBOL_QUERY = """
|
|
19
|
+
(function_declarator
|
|
20
|
+
declarator: (identifier) @function.name)
|
|
21
|
+
|
|
22
|
+
(struct_specifier
|
|
23
|
+
name: (type_identifier) @struct.name)
|
|
24
|
+
|
|
25
|
+
(class_specifier
|
|
26
|
+
name: (type_identifier) @class.name)
|
|
27
|
+
|
|
28
|
+
(union_specifier
|
|
29
|
+
name: (type_identifier) @union.name)
|
|
30
|
+
|
|
31
|
+
(enum_specifier
|
|
32
|
+
name: (type_identifier) @enum.name)
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
# --- C/C++ Language Setup ---
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
import tree_sitter_c
|
|
39
|
+
C_LANGUAGE: Optional[Language] = tree_sitter_c.language()
|
|
40
|
+
except (ImportError, Exception):
|
|
41
|
+
C_LANGUAGE = None
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
import tree_sitter_cpp
|
|
45
|
+
CPP_LANGUAGE: Optional[Language] = tree_sitter_cpp.language()
|
|
46
|
+
except (ImportError, Exception):
|
|
47
|
+
CPP_LANGUAGE = None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# --- C/C++ Symbol Extractors ---
|
|
51
|
+
|
|
52
|
+
class CSymbolExtractor(TreeSitterExtractor):
|
|
53
|
+
"""Extracts symbols from C code using tree-sitter."""
|
|
54
|
+
|
|
55
|
+
def __init__(self):
|
|
56
|
+
if not C_LANGUAGE:
|
|
57
|
+
raise RuntimeError("C tree-sitter grammar not available.")
|
|
58
|
+
super().__init__(C_LANGUAGE, C_CPP_SYMBOL_QUERY)
|
|
59
|
+
|
|
60
|
+
def _create_symbol_from_capture(self, node: Node, name: str, file_path: str) -> Optional[Symbol]:
|
|
61
|
+
kind_map = {
|
|
62
|
+
"function.name": "function",
|
|
63
|
+
"struct.name": "struct",
|
|
64
|
+
"union.name": "union",
|
|
65
|
+
"enum.name": "enum",
|
|
66
|
+
}
|
|
67
|
+
symbol_kind = kind_map.get(name)
|
|
68
|
+
if not symbol_kind:
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
return Symbol(
|
|
72
|
+
name=node.text.decode('utf8'),
|
|
73
|
+
kind=symbol_kind,
|
|
74
|
+
file_path=file_path,
|
|
75
|
+
line_start=node.start_point[0] + 1,
|
|
76
|
+
line_end=node.end_point[0] + 1,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class CppSymbolExtractor(TreeSitterExtractor):
|
|
81
|
+
"""Extracts symbols from C++ code using tree-sitter."""
|
|
82
|
+
|
|
83
|
+
def __init__(self):
|
|
84
|
+
if not CPP_LANGUAGE:
|
|
85
|
+
raise RuntimeError("C++ tree-sitter grammar not available.")
|
|
86
|
+
super().__init__(CPP_LANGUAGE, C_CPP_SYMBOL_QUERY)
|
|
87
|
+
|
|
88
|
+
def _create_symbol_from_capture(self, node: Node, name: str, file_path: str) -> Optional[Symbol]:
|
|
89
|
+
kind_map = {
|
|
90
|
+
"function.name": "function",
|
|
91
|
+
"struct.name": "struct",
|
|
92
|
+
"class.name": "class",
|
|
93
|
+
"union.name": "union",
|
|
94
|
+
"enum.name": "enum",
|
|
95
|
+
}
|
|
96
|
+
symbol_kind = kind_map.get(name)
|
|
97
|
+
if not symbol_kind:
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
return Symbol(
|
|
101
|
+
name=node.text.decode('utf8'),
|
|
102
|
+
kind=symbol_kind,
|
|
103
|
+
file_path=file_path,
|
|
104
|
+
line_start=node.start_point[0] + 1,
|
|
105
|
+
line_end=node.end_point[0] + 1,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# --- C/C++ Dependency Analyzers ---
|
|
110
|
+
|
|
111
|
+
class CDependencyAnalyzer(DependencyAnalyzer):
|
|
112
|
+
"""Analyzes C include dependencies."""
|
|
113
|
+
|
|
114
|
+
def analyze_imports(self, file_path: str, content: str) -> List[Dependency]:
|
|
115
|
+
"""Analyzes C #include statements."""
|
|
116
|
+
dependencies: List[Dependency] = []
|
|
117
|
+
|
|
118
|
+
# Match #include directives
|
|
119
|
+
# Format: #include <header.h> or #include "header.h"
|
|
120
|
+
include_pattern = re.compile(r'#include\s+[<"]([^>"]+)[>"]')
|
|
121
|
+
|
|
122
|
+
for line_num, line in enumerate(content.split('\n'), start=1):
|
|
123
|
+
match = include_pattern.search(line)
|
|
124
|
+
if match:
|
|
125
|
+
header = match.group(1)
|
|
126
|
+
dependencies.append(Dependency(
|
|
127
|
+
from_module=header,
|
|
128
|
+
imported_symbol=None,
|
|
129
|
+
file_path=file_path,
|
|
130
|
+
line=line_num,
|
|
131
|
+
))
|
|
132
|
+
|
|
133
|
+
return dependencies
|
|
134
|
+
|
|
135
|
+
def build_dependency_graph(self, project_root: str) -> DependencyGraph:
|
|
136
|
+
"""Builds a dependency graph for a C project."""
|
|
137
|
+
graph = DependencyGraph()
|
|
138
|
+
extensions = {'.c', '.h'}
|
|
139
|
+
|
|
140
|
+
for root, dirs, files in os.walk(project_root):
|
|
141
|
+
dirs[:] = filter_walk_dirs(dirs)
|
|
142
|
+
|
|
143
|
+
for file in files:
|
|
144
|
+
if not any(file.endswith(ext) for ext in extensions):
|
|
145
|
+
continue
|
|
146
|
+
|
|
147
|
+
file_path = os.path.join(root, file)
|
|
148
|
+
try:
|
|
149
|
+
with open(file_path, 'r', encoding='utf-8', errors='replace') as f:
|
|
150
|
+
content = f.read()
|
|
151
|
+
|
|
152
|
+
dependencies = self.analyze_imports(file_path, content)
|
|
153
|
+
for dep in dependencies:
|
|
154
|
+
dep_path = self._resolve_header_path(project_root, dep.from_module, file_path)
|
|
155
|
+
if dep_path and dep_path != file_path:
|
|
156
|
+
graph.add_dependency(file_path, dep_path)
|
|
157
|
+
except Exception:
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
return graph
|
|
161
|
+
|
|
162
|
+
def _resolve_header_path(self, project_root: str, header_name: str, from_file: str) -> Optional[str]:
|
|
163
|
+
"""Resolve a header name to a file path."""
|
|
164
|
+
# Try relative to current file
|
|
165
|
+
base_dir = os.path.dirname(from_file)
|
|
166
|
+
relative_path = os.path.join(base_dir, header_name)
|
|
167
|
+
if os.path.exists(relative_path):
|
|
168
|
+
return relative_path
|
|
169
|
+
|
|
170
|
+
# Try in project root
|
|
171
|
+
for root, dirs, files in os.walk(project_root):
|
|
172
|
+
dirs[:] = filter_walk_dirs(dirs)
|
|
173
|
+
if header_name in files:
|
|
174
|
+
return os.path.join(root, header_name)
|
|
175
|
+
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
def _is_source_file(self, file_path: str) -> bool:
|
|
179
|
+
"""Check if a file is a C source file."""
|
|
180
|
+
return file_path.endswith(('.c', '.h'))
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class CppDependencyAnalyzer(CDependencyAnalyzer):
|
|
184
|
+
"""Analyzes C++ include dependencies (same as C)."""
|
|
185
|
+
|
|
186
|
+
def _is_source_file(self, file_path: str) -> bool:
|
|
187
|
+
"""Check if a file is a C++ source file."""
|
|
188
|
+
return file_path.endswith(('.cpp', '.hpp', '.cc', '.cxx', '.hxx', '.h'))
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class CLanguageSupport(BaseLanguageSupport):
|
|
192
|
+
"""C语言支持类。"""
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def language_name(self) -> str:
|
|
196
|
+
return 'c'
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def file_extensions(self) -> Set[str]:
|
|
200
|
+
return {'.c', '.h'}
|
|
201
|
+
|
|
202
|
+
def create_symbol_extractor(self) -> Optional[SymbolExtractor]:
|
|
203
|
+
try:
|
|
204
|
+
return CSymbolExtractor()
|
|
205
|
+
except RuntimeError:
|
|
206
|
+
return None
|
|
207
|
+
|
|
208
|
+
def create_dependency_analyzer(self) -> Optional[DependencyAnalyzer]:
|
|
209
|
+
return CDependencyAnalyzer()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class CppLanguageSupport(BaseLanguageSupport):
|
|
213
|
+
"""C++语言支持类。"""
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def language_name(self) -> str:
|
|
217
|
+
return 'cpp'
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def file_extensions(self) -> Set[str]:
|
|
221
|
+
return {'.cpp', '.hpp', '.cc', '.cxx', '.hxx'}
|
|
222
|
+
|
|
223
|
+
def create_symbol_extractor(self) -> Optional[SymbolExtractor]:
|
|
224
|
+
try:
|
|
225
|
+
return CppSymbolExtractor()
|
|
226
|
+
except RuntimeError:
|
|
227
|
+
return None
|
|
228
|
+
|
|
229
|
+
def create_dependency_analyzer(self) -> Optional[DependencyAnalyzer]:
|
|
230
|
+
return CppDependencyAnalyzer()
|
|
231
|
+
|