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.
Files changed (181) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +458 -152
  3. jarvis/jarvis_agent/agent_manager.py +17 -13
  4. jarvis/jarvis_agent/builtin_input_handler.py +2 -6
  5. jarvis/jarvis_agent/config_editor.py +2 -7
  6. jarvis/jarvis_agent/event_bus.py +82 -12
  7. jarvis/jarvis_agent/file_context_handler.py +329 -0
  8. jarvis/jarvis_agent/file_methodology_manager.py +3 -4
  9. jarvis/jarvis_agent/jarvis.py +628 -55
  10. jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
  11. jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
  12. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
  13. jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
  14. jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
  15. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
  16. jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
  17. jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
  18. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
  19. jarvis/jarvis_agent/language_support_info.py +486 -0
  20. jarvis/jarvis_agent/main.py +34 -10
  21. jarvis/jarvis_agent/memory_manager.py +7 -16
  22. jarvis/jarvis_agent/methodology_share_manager.py +10 -16
  23. jarvis/jarvis_agent/prompt_manager.py +1 -1
  24. jarvis/jarvis_agent/prompts.py +193 -171
  25. jarvis/jarvis_agent/protocols.py +8 -12
  26. jarvis/jarvis_agent/run_loop.py +105 -9
  27. jarvis/jarvis_agent/session_manager.py +2 -3
  28. jarvis/jarvis_agent/share_manager.py +20 -22
  29. jarvis/jarvis_agent/shell_input_handler.py +1 -2
  30. jarvis/jarvis_agent/stdio_redirect.py +295 -0
  31. jarvis/jarvis_agent/task_analyzer.py +31 -6
  32. jarvis/jarvis_agent/task_manager.py +11 -27
  33. jarvis/jarvis_agent/tool_executor.py +2 -3
  34. jarvis/jarvis_agent/tool_share_manager.py +12 -24
  35. jarvis/jarvis_agent/utils.py +5 -1
  36. jarvis/jarvis_agent/web_bridge.py +189 -0
  37. jarvis/jarvis_agent/web_output_sink.py +53 -0
  38. jarvis/jarvis_agent/web_server.py +786 -0
  39. jarvis/jarvis_c2rust/__init__.py +26 -0
  40. jarvis/jarvis_c2rust/cli.py +575 -0
  41. jarvis/jarvis_c2rust/collector.py +250 -0
  42. jarvis/jarvis_c2rust/constants.py +26 -0
  43. jarvis/jarvis_c2rust/library_replacer.py +1254 -0
  44. jarvis/jarvis_c2rust/llm_module_agent.py +1272 -0
  45. jarvis/jarvis_c2rust/loaders.py +207 -0
  46. jarvis/jarvis_c2rust/models.py +28 -0
  47. jarvis/jarvis_c2rust/optimizer.py +2157 -0
  48. jarvis/jarvis_c2rust/scanner.py +1681 -0
  49. jarvis/jarvis_c2rust/transpiler.py +2983 -0
  50. jarvis/jarvis_c2rust/utils.py +385 -0
  51. jarvis/jarvis_code_agent/build_validation_config.py +132 -0
  52. jarvis/jarvis_code_agent/code_agent.py +1371 -220
  53. jarvis/jarvis_code_agent/code_analyzer/__init__.py +65 -0
  54. jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +106 -0
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +74 -0
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +72 -0
  60. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +70 -0
  61. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +53 -0
  62. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +47 -0
  63. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +61 -0
  64. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +110 -0
  65. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +154 -0
  66. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +110 -0
  67. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +153 -0
  68. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
  69. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +648 -0
  70. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
  71. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
  72. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
  73. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
  74. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
  75. jarvis/jarvis_code_agent/code_analyzer/language_support.py +110 -0
  76. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +49 -0
  77. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +299 -0
  78. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +215 -0
  79. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
  80. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
  81. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +269 -0
  82. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +281 -0
  83. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
  84. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +605 -0
  85. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
  86. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +252 -0
  87. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +58 -0
  88. jarvis/jarvis_code_agent/lint.py +501 -8
  89. jarvis/jarvis_code_agent/utils.py +141 -0
  90. jarvis/jarvis_code_analysis/code_review.py +493 -584
  91. jarvis/jarvis_data/config_schema.json +128 -12
  92. jarvis/jarvis_git_squash/main.py +4 -5
  93. jarvis/jarvis_git_utils/git_commiter.py +82 -75
  94. jarvis/jarvis_mcp/sse_mcp_client.py +22 -29
  95. jarvis/jarvis_mcp/stdio_mcp_client.py +12 -13
  96. jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
  97. jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
  98. jarvis/jarvis_methodology/main.py +32 -48
  99. jarvis/jarvis_multi_agent/__init__.py +287 -55
  100. jarvis/jarvis_multi_agent/main.py +36 -4
  101. jarvis/jarvis_platform/base.py +524 -202
  102. jarvis/jarvis_platform/human.py +7 -8
  103. jarvis/jarvis_platform/kimi.py +30 -36
  104. jarvis/jarvis_platform/openai.py +88 -25
  105. jarvis/jarvis_platform/registry.py +26 -10
  106. jarvis/jarvis_platform/tongyi.py +24 -25
  107. jarvis/jarvis_platform/yuanbao.py +32 -43
  108. jarvis/jarvis_platform_manager/main.py +66 -77
  109. jarvis/jarvis_platform_manager/service.py +8 -13
  110. jarvis/jarvis_rag/cli.py +53 -55
  111. jarvis/jarvis_rag/embedding_manager.py +13 -18
  112. jarvis/jarvis_rag/llm_interface.py +8 -9
  113. jarvis/jarvis_rag/query_rewriter.py +10 -21
  114. jarvis/jarvis_rag/rag_pipeline.py +24 -27
  115. jarvis/jarvis_rag/reranker.py +4 -5
  116. jarvis/jarvis_rag/retriever.py +28 -30
  117. jarvis/jarvis_sec/__init__.py +305 -0
  118. jarvis/jarvis_sec/agents.py +143 -0
  119. jarvis/jarvis_sec/analysis.py +276 -0
  120. jarvis/jarvis_sec/checkers/__init__.py +32 -0
  121. jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
  122. jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
  123. jarvis/jarvis_sec/cli.py +139 -0
  124. jarvis/jarvis_sec/clustering.py +1439 -0
  125. jarvis/jarvis_sec/file_manager.py +427 -0
  126. jarvis/jarvis_sec/parsers.py +73 -0
  127. jarvis/jarvis_sec/prompts.py +268 -0
  128. jarvis/jarvis_sec/report.py +336 -0
  129. jarvis/jarvis_sec/review.py +453 -0
  130. jarvis/jarvis_sec/status.py +264 -0
  131. jarvis/jarvis_sec/types.py +20 -0
  132. jarvis/jarvis_sec/utils.py +499 -0
  133. jarvis/jarvis_sec/verification.py +848 -0
  134. jarvis/jarvis_sec/workflow.py +226 -0
  135. jarvis/jarvis_smart_shell/main.py +38 -87
  136. jarvis/jarvis_stats/cli.py +2 -2
  137. jarvis/jarvis_stats/stats.py +8 -8
  138. jarvis/jarvis_stats/storage.py +15 -21
  139. jarvis/jarvis_stats/visualizer.py +1 -1
  140. jarvis/jarvis_tools/clear_memory.py +3 -20
  141. jarvis/jarvis_tools/cli/main.py +21 -23
  142. jarvis/jarvis_tools/edit_file.py +1019 -132
  143. jarvis/jarvis_tools/execute_script.py +83 -25
  144. jarvis/jarvis_tools/file_analyzer.py +6 -9
  145. jarvis/jarvis_tools/generate_new_tool.py +14 -21
  146. jarvis/jarvis_tools/lsp_client.py +1552 -0
  147. jarvis/jarvis_tools/methodology.py +2 -3
  148. jarvis/jarvis_tools/read_code.py +1736 -35
  149. jarvis/jarvis_tools/read_symbols.py +140 -0
  150. jarvis/jarvis_tools/read_webpage.py +12 -13
  151. jarvis/jarvis_tools/registry.py +427 -200
  152. jarvis/jarvis_tools/retrieve_memory.py +20 -19
  153. jarvis/jarvis_tools/rewrite_file.py +72 -158
  154. jarvis/jarvis_tools/save_memory.py +3 -15
  155. jarvis/jarvis_tools/search_web.py +18 -18
  156. jarvis/jarvis_tools/sub_agent.py +36 -43
  157. jarvis/jarvis_tools/sub_code_agent.py +25 -26
  158. jarvis/jarvis_tools/virtual_tty.py +55 -33
  159. jarvis/jarvis_utils/clipboard.py +7 -10
  160. jarvis/jarvis_utils/config.py +232 -45
  161. jarvis/jarvis_utils/embedding.py +8 -5
  162. jarvis/jarvis_utils/fzf.py +8 -8
  163. jarvis/jarvis_utils/git_utils.py +225 -36
  164. jarvis/jarvis_utils/globals.py +3 -3
  165. jarvis/jarvis_utils/http.py +1 -1
  166. jarvis/jarvis_utils/input.py +99 -48
  167. jarvis/jarvis_utils/jsonnet_compat.py +465 -0
  168. jarvis/jarvis_utils/methodology.py +52 -48
  169. jarvis/jarvis_utils/utils.py +819 -491
  170. jarvis_ai_assistant-0.7.6.dist-info/METADATA +600 -0
  171. jarvis_ai_assistant-0.7.6.dist-info/RECORD +218 -0
  172. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/entry_points.txt +4 -0
  173. jarvis/jarvis_agent/config.py +0 -92
  174. jarvis/jarvis_agent/edit_file_handler.py +0 -296
  175. jarvis/jarvis_platform/ai8.py +0 -332
  176. jarvis/jarvis_tools/ask_user.py +0 -54
  177. jarvis_ai_assistant-0.3.30.dist-info/METADATA +0 -381
  178. jarvis_ai_assistant-0.3.30.dist-info/RECORD +0 -137
  179. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/WHEEL +0 -0
  180. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/licenses/LICENSE +0 -0
  181. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.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,110 @@
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
+ # JavaScript语言支持(可选,需要tree-sitter)
56
+ try:
57
+ from .languages import JavaScriptLanguageSupport
58
+ register_language(JavaScriptLanguageSupport())
59
+ except (ImportError, RuntimeError):
60
+ pass # 静默失败,tree-sitter可能不可用
61
+
62
+ # TypeScript语言支持(可选,需要tree-sitter)
63
+ try:
64
+ from .languages import TypeScriptLanguageSupport
65
+ register_language(TypeScriptLanguageSupport())
66
+ except (ImportError, RuntimeError):
67
+ pass # 静默失败,tree-sitter可能不可用
68
+
69
+ # Java语言支持(可选,需要tree-sitter)
70
+ try:
71
+ from .languages import JavaLanguageSupport
72
+ register_language(JavaLanguageSupport())
73
+ except (ImportError, RuntimeError):
74
+ pass # 静默失败,tree-sitter可能不可用
75
+
76
+
77
+ def detect_language(file_path: str) -> Optional[str]:
78
+ """检测文件的编程语言。
79
+
80
+ Args:
81
+ file_path: 文件路径
82
+
83
+ Returns:
84
+ 语言名称,如果无法检测则返回None
85
+ """
86
+ return _detect_language(file_path)
87
+
88
+
89
+ def get_symbol_extractor(language: str) -> Optional[SymbolExtractor]:
90
+ """获取指定语言的符号提取器。
91
+
92
+ Args:
93
+ language: 语言名称
94
+
95
+ Returns:
96
+ SymbolExtractor实例,如果不支持则返回None
97
+ """
98
+ return _get_symbol_extractor(language)
99
+
100
+
101
+ def get_dependency_analyzer(language: str) -> Optional[DependencyAnalyzer]:
102
+ """获取指定语言的依赖分析器。
103
+
104
+ Args:
105
+ language: 语言名称
106
+
107
+ Returns:
108
+ DependencyAnalyzer实例,如果不支持则返回None
109
+ """
110
+ return _get_dependency_analyzer(language)
@@ -0,0 +1,49 @@
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 # noqa: F401
16
+ __all__.append('RustLanguageSupport')
17
+ except (ImportError, RuntimeError):
18
+ pass
19
+
20
+ try:
21
+ from .go_language import GoLanguageSupport # noqa: F401
22
+ __all__.append('GoLanguageSupport')
23
+ except (ImportError, RuntimeError):
24
+ pass
25
+
26
+ try:
27
+ from .c_cpp_language import CLanguageSupport, CppLanguageSupport # noqa: F401
28
+ __all__.extend(['CLanguageSupport', 'CppLanguageSupport'])
29
+ except (ImportError, RuntimeError):
30
+ pass
31
+
32
+ try:
33
+ from .javascript_language import JavaScriptLanguageSupport # noqa: F401
34
+ __all__.append('JavaScriptLanguageSupport')
35
+ except (ImportError, RuntimeError):
36
+ pass
37
+
38
+ try:
39
+ from .typescript_language import TypeScriptLanguageSupport # noqa: F401
40
+ __all__.append('TypeScriptLanguageSupport')
41
+ except (ImportError, RuntimeError):
42
+ pass
43
+
44
+ try:
45
+ from .java_language import JavaLanguageSupport # noqa: F401
46
+ __all__.append('JavaLanguageSupport')
47
+ except (ImportError, RuntimeError):
48
+ pass
49
+
@@ -0,0 +1,299 @@
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语言查询(不包含class_specifier,因为C不支持class)
19
+ C_SYMBOL_QUERY = """
20
+ (function_declarator
21
+ declarator: (identifier) @function.name)
22
+
23
+ (struct_specifier
24
+ name: (type_identifier) @struct.name)
25
+
26
+ (union_specifier
27
+ name: (type_identifier) @union.name)
28
+
29
+ (enum_specifier
30
+ name: (type_identifier) @enum.name)
31
+
32
+ (preproc_def
33
+ name: (identifier) @macro.name)
34
+
35
+ (type_definition
36
+ declarator: (type_identifier) @typedef.name)
37
+ """
38
+
39
+ # C++语言查询(包含class_specifier)
40
+ CPP_SYMBOL_QUERY = """
41
+ (function_declarator
42
+ declarator: (identifier) @function.name)
43
+
44
+ (struct_specifier
45
+ name: (type_identifier) @struct.name)
46
+
47
+ (class_specifier
48
+ name: (type_identifier) @class.name)
49
+
50
+ (union_specifier
51
+ name: (type_identifier) @union.name)
52
+
53
+ (enum_specifier
54
+ name: (type_identifier) @enum.name)
55
+
56
+ (namespace_definition
57
+ name: (identifier)? @namespace.name)
58
+
59
+ (preproc_def
60
+ name: (identifier) @macro.name)
61
+
62
+ (type_definition
63
+ declarator: (type_identifier) @typedef.name)
64
+
65
+ (template_declaration) @template
66
+ """
67
+
68
+ # --- C/C++ Language Setup ---
69
+
70
+ try:
71
+ import tree_sitter_c
72
+ C_LANGUAGE: Optional[Language] = tree_sitter_c.language()
73
+ except (ImportError, Exception):
74
+ C_LANGUAGE = None
75
+
76
+ try:
77
+ import tree_sitter_cpp
78
+ CPP_LANGUAGE: Optional[Language] = tree_sitter_cpp.language()
79
+ except (ImportError, Exception):
80
+ CPP_LANGUAGE = None
81
+
82
+
83
+ # --- C/C++ Symbol Extractors ---
84
+
85
+ class CSymbolExtractor(TreeSitterExtractor):
86
+ """Extracts symbols from C code using tree-sitter."""
87
+
88
+ def __init__(self):
89
+ if not C_LANGUAGE:
90
+ raise RuntimeError("C tree-sitter grammar not available.")
91
+ super().__init__(C_LANGUAGE, C_SYMBOL_QUERY)
92
+
93
+ def _create_symbol_from_capture(self, node: Node, name: str, file_path: str) -> Optional[Symbol]:
94
+ kind_map = {
95
+ "function.name": "function",
96
+ "struct.name": "struct",
97
+ "union.name": "union",
98
+ "enum.name": "enum",
99
+ "macro.name": "macro",
100
+ "typedef.name": "typedef",
101
+ }
102
+ symbol_kind = kind_map.get(name)
103
+ if not symbol_kind:
104
+ return None
105
+
106
+ return Symbol(
107
+ name=node.text.decode('utf8'),
108
+ kind=symbol_kind,
109
+ file_path=file_path,
110
+ line_start=node.start_point[0] + 1,
111
+ line_end=node.end_point[0] + 1,
112
+ )
113
+
114
+
115
+ class CppSymbolExtractor(TreeSitterExtractor):
116
+ """Extracts symbols from C++ code using tree-sitter."""
117
+
118
+ def __init__(self):
119
+ if not CPP_LANGUAGE:
120
+ raise RuntimeError("C++ tree-sitter grammar not available.")
121
+ super().__init__(CPP_LANGUAGE, CPP_SYMBOL_QUERY)
122
+
123
+ def _create_symbol_from_capture(self, node: Node, name: str, file_path: str) -> Optional[Symbol]:
124
+ kind_map = {
125
+ "function.name": "function",
126
+ "struct.name": "struct",
127
+ "class.name": "class",
128
+ "union.name": "union",
129
+ "enum.name": "enum",
130
+ "namespace.name": "namespace",
131
+ "macro.name": "macro",
132
+ "typedef.name": "typedef",
133
+ "template": "template",
134
+ }
135
+ symbol_kind = kind_map.get(name)
136
+ if not symbol_kind:
137
+ return None
138
+
139
+ # For anonymous namespaces, use a generated name
140
+ if name == "namespace.name":
141
+ symbol_name = node.text.decode('utf8') if node.text else "<anonymous_namespace>"
142
+ elif name == "template":
143
+ # For template declarations, extract the template name or use a generic name
144
+ # Try to find the function/class name after template
145
+ template_text = node.text.decode('utf8').strip()
146
+ # Extract template parameters and the following declaration
147
+ # This is a simplified extraction - in practice, you might want more sophisticated parsing
148
+ if 'template' in template_text:
149
+ # Try to extract the name after template<...>
150
+ parts = template_text.split('>', 1)
151
+ if len(parts) > 1:
152
+ # Look for function/class name in the second part
153
+ match = re.search(r'\b(function|class|struct)\s+(\w+)', parts[1])
154
+ if match:
155
+ symbol_name = f"template_{match.group(2)}"
156
+ else:
157
+ symbol_name = "template"
158
+ else:
159
+ symbol_name = "template"
160
+ else:
161
+ symbol_name = "template"
162
+ else:
163
+ symbol_name = node.text.decode('utf8')
164
+
165
+ if not symbol_name:
166
+ return None
167
+
168
+ return Symbol(
169
+ name=symbol_name,
170
+ kind=symbol_kind,
171
+ file_path=file_path,
172
+ line_start=node.start_point[0] + 1,
173
+ line_end=node.end_point[0] + 1,
174
+ )
175
+
176
+
177
+ # --- C/C++ Dependency Analyzers ---
178
+
179
+ class CDependencyAnalyzer(DependencyAnalyzer):
180
+ """Analyzes C include dependencies."""
181
+
182
+ def analyze_imports(self, file_path: str, content: str) -> List[Dependency]:
183
+ """Analyzes C #include statements."""
184
+ dependencies: List[Dependency] = []
185
+
186
+ # Match #include directives
187
+ # Format: #include <header.h> or #include "header.h"
188
+ include_pattern = re.compile(r'#include\s+[<"]([^>"]+)[>"]')
189
+
190
+ for line_num, line in enumerate(content.split('\n'), start=1):
191
+ match = include_pattern.search(line)
192
+ if match:
193
+ header = match.group(1)
194
+ dependencies.append(Dependency(
195
+ from_module=header,
196
+ imported_symbol=None,
197
+ file_path=file_path,
198
+ line=line_num,
199
+ ))
200
+
201
+ return dependencies
202
+
203
+ def build_dependency_graph(self, project_root: str) -> DependencyGraph:
204
+ """Builds a dependency graph for a C project."""
205
+ graph = DependencyGraph()
206
+ extensions = {'.c', '.h'}
207
+
208
+ for root, dirs, files in os.walk(project_root):
209
+ dirs[:] = filter_walk_dirs(dirs)
210
+
211
+ for file in files:
212
+ if not any(file.endswith(ext) for ext in extensions):
213
+ continue
214
+
215
+ file_path = os.path.join(root, file)
216
+ try:
217
+ with open(file_path, 'r', encoding='utf-8', errors='replace') as f:
218
+ content = f.read()
219
+
220
+ dependencies = self.analyze_imports(file_path, content)
221
+ for dep in dependencies:
222
+ dep_path = self._resolve_header_path(project_root, dep.from_module, file_path)
223
+ if dep_path and dep_path != file_path:
224
+ graph.add_dependency(file_path, dep_path)
225
+ except Exception:
226
+ continue
227
+
228
+ return graph
229
+
230
+ def _resolve_header_path(self, project_root: str, header_name: str, from_file: str) -> Optional[str]:
231
+ """Resolve a header name to a file path."""
232
+ # Try relative to current file
233
+ base_dir = os.path.dirname(from_file)
234
+ relative_path = os.path.join(base_dir, header_name)
235
+ if os.path.exists(relative_path):
236
+ return relative_path
237
+
238
+ # Try in project root
239
+ for root, dirs, files in os.walk(project_root):
240
+ dirs[:] = filter_walk_dirs(dirs)
241
+ if header_name in files:
242
+ return os.path.join(root, header_name)
243
+
244
+ return None
245
+
246
+ def _is_source_file(self, file_path: str) -> bool:
247
+ """Check if a file is a C source file."""
248
+ return file_path.endswith(('.c', '.h'))
249
+
250
+
251
+ class CppDependencyAnalyzer(CDependencyAnalyzer):
252
+ """Analyzes C++ include dependencies (same as C)."""
253
+
254
+ def _is_source_file(self, file_path: str) -> bool:
255
+ """Check if a file is a C++ source file."""
256
+ return file_path.endswith(('.cpp', '.hpp', '.cc', '.cxx', '.hxx', '.h'))
257
+
258
+
259
+ class CLanguageSupport(BaseLanguageSupport):
260
+ """C语言支持类。"""
261
+
262
+ @property
263
+ def language_name(self) -> str:
264
+ return 'c'
265
+
266
+ @property
267
+ def file_extensions(self) -> Set[str]:
268
+ return {'.c', '.h'}
269
+
270
+ def create_symbol_extractor(self) -> Optional[SymbolExtractor]:
271
+ try:
272
+ return CSymbolExtractor()
273
+ except RuntimeError:
274
+ return None
275
+
276
+ def create_dependency_analyzer(self) -> Optional[DependencyAnalyzer]:
277
+ return CDependencyAnalyzer()
278
+
279
+
280
+ class CppLanguageSupport(BaseLanguageSupport):
281
+ """C++语言支持类。"""
282
+
283
+ @property
284
+ def language_name(self) -> str:
285
+ return 'cpp'
286
+
287
+ @property
288
+ def file_extensions(self) -> Set[str]:
289
+ return {'.cpp', '.hpp', '.cc', '.cxx', '.hxx'}
290
+
291
+ def create_symbol_extractor(self) -> Optional[SymbolExtractor]:
292
+ try:
293
+ return CppSymbolExtractor()
294
+ except RuntimeError:
295
+ return None
296
+
297
+ def create_dependency_analyzer(self) -> Optional[DependencyAnalyzer]:
298
+ return CppDependencyAnalyzer()
299
+