jarvis-ai-assistant 0.7.8__py3-none-any.whl → 1.0.2__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 +567 -222
- jarvis/jarvis_agent/agent_manager.py +19 -12
- jarvis/jarvis_agent/builtin_input_handler.py +79 -11
- jarvis/jarvis_agent/config_editor.py +7 -2
- jarvis/jarvis_agent/event_bus.py +24 -13
- jarvis/jarvis_agent/events.py +19 -1
- jarvis/jarvis_agent/file_context_handler.py +67 -64
- jarvis/jarvis_agent/file_methodology_manager.py +38 -24
- jarvis/jarvis_agent/jarvis.py +186 -114
- jarvis/jarvis_agent/language_extractors/__init__.py +8 -1
- jarvis/jarvis_agent/language_extractors/c_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +9 -4
- jarvis/jarvis_agent/language_extractors/go_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/java_extractor.py +27 -20
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +22 -17
- jarvis/jarvis_agent/language_extractors/python_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +22 -17
- jarvis/jarvis_agent/language_support_info.py +250 -219
- jarvis/jarvis_agent/main.py +19 -23
- jarvis/jarvis_agent/memory_manager.py +9 -6
- jarvis/jarvis_agent/methodology_share_manager.py +21 -15
- jarvis/jarvis_agent/output_handler.py +4 -2
- jarvis/jarvis_agent/prompt_builder.py +7 -6
- jarvis/jarvis_agent/prompt_manager.py +113 -8
- jarvis/jarvis_agent/prompts.py +317 -85
- jarvis/jarvis_agent/protocols.py +5 -2
- jarvis/jarvis_agent/run_loop.py +192 -32
- jarvis/jarvis_agent/session_manager.py +7 -3
- jarvis/jarvis_agent/share_manager.py +23 -13
- jarvis/jarvis_agent/shell_input_handler.py +12 -8
- jarvis/jarvis_agent/stdio_redirect.py +25 -26
- jarvis/jarvis_agent/task_analyzer.py +29 -23
- jarvis/jarvis_agent/task_list.py +869 -0
- jarvis/jarvis_agent/task_manager.py +26 -23
- jarvis/jarvis_agent/tool_executor.py +6 -5
- jarvis/jarvis_agent/tool_share_manager.py +24 -14
- jarvis/jarvis_agent/user_interaction.py +3 -3
- jarvis/jarvis_agent/utils.py +9 -1
- jarvis/jarvis_agent/web_bridge.py +37 -17
- jarvis/jarvis_agent/web_output_sink.py +5 -2
- jarvis/jarvis_agent/web_server.py +165 -36
- jarvis/jarvis_c2rust/__init__.py +1 -1
- jarvis/jarvis_c2rust/cli.py +260 -141
- jarvis/jarvis_c2rust/collector.py +37 -18
- jarvis/jarvis_c2rust/constants.py +60 -0
- jarvis/jarvis_c2rust/library_replacer.py +242 -1010
- jarvis/jarvis_c2rust/library_replacer_checkpoint.py +133 -0
- jarvis/jarvis_c2rust/library_replacer_llm.py +287 -0
- jarvis/jarvis_c2rust/library_replacer_loader.py +191 -0
- jarvis/jarvis_c2rust/library_replacer_output.py +134 -0
- jarvis/jarvis_c2rust/library_replacer_prompts.py +124 -0
- jarvis/jarvis_c2rust/library_replacer_utils.py +188 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +98 -1044
- jarvis/jarvis_c2rust/llm_module_agent_apply.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_executor.py +288 -0
- jarvis/jarvis_c2rust/llm_module_agent_loader.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_prompts.py +268 -0
- jarvis/jarvis_c2rust/llm_module_agent_types.py +57 -0
- jarvis/jarvis_c2rust/llm_module_agent_utils.py +150 -0
- jarvis/jarvis_c2rust/llm_module_agent_validator.py +119 -0
- jarvis/jarvis_c2rust/loaders.py +28 -10
- jarvis/jarvis_c2rust/models.py +5 -2
- jarvis/jarvis_c2rust/optimizer.py +192 -1974
- jarvis/jarvis_c2rust/optimizer_build_fix.py +286 -0
- jarvis/jarvis_c2rust/optimizer_clippy.py +766 -0
- jarvis/jarvis_c2rust/optimizer_config.py +49 -0
- jarvis/jarvis_c2rust/optimizer_docs.py +183 -0
- jarvis/jarvis_c2rust/optimizer_options.py +48 -0
- jarvis/jarvis_c2rust/optimizer_progress.py +469 -0
- jarvis/jarvis_c2rust/optimizer_report.py +52 -0
- jarvis/jarvis_c2rust/optimizer_unsafe.py +309 -0
- jarvis/jarvis_c2rust/optimizer_utils.py +469 -0
- jarvis/jarvis_c2rust/optimizer_visibility.py +185 -0
- jarvis/jarvis_c2rust/scanner.py +229 -166
- jarvis/jarvis_c2rust/transpiler.py +531 -2732
- jarvis/jarvis_c2rust/transpiler_agents.py +503 -0
- jarvis/jarvis_c2rust/transpiler_build.py +1294 -0
- jarvis/jarvis_c2rust/transpiler_codegen.py +204 -0
- jarvis/jarvis_c2rust/transpiler_compile.py +146 -0
- jarvis/jarvis_c2rust/transpiler_config.py +178 -0
- jarvis/jarvis_c2rust/transpiler_context.py +122 -0
- jarvis/jarvis_c2rust/transpiler_executor.py +516 -0
- jarvis/jarvis_c2rust/transpiler_generation.py +278 -0
- jarvis/jarvis_c2rust/transpiler_git.py +163 -0
- jarvis/jarvis_c2rust/transpiler_mod_utils.py +225 -0
- jarvis/jarvis_c2rust/transpiler_modules.py +336 -0
- jarvis/jarvis_c2rust/transpiler_planning.py +394 -0
- jarvis/jarvis_c2rust/transpiler_review.py +1196 -0
- jarvis/jarvis_c2rust/transpiler_symbols.py +176 -0
- jarvis/jarvis_c2rust/utils.py +269 -79
- jarvis/jarvis_code_agent/after_change.py +233 -0
- jarvis/jarvis_code_agent/build_validation_config.py +37 -30
- jarvis/jarvis_code_agent/builtin_rules.py +68 -0
- jarvis/jarvis_code_agent/code_agent.py +976 -1517
- jarvis/jarvis_code_agent/code_agent_build.py +227 -0
- jarvis/jarvis_code_agent/code_agent_diff.py +246 -0
- jarvis/jarvis_code_agent/code_agent_git.py +525 -0
- jarvis/jarvis_code_agent/code_agent_impact.py +177 -0
- jarvis/jarvis_code_agent/code_agent_lint.py +283 -0
- jarvis/jarvis_code_agent/code_agent_llm.py +159 -0
- jarvis/jarvis_code_agent/code_agent_postprocess.py +105 -0
- jarvis/jarvis_code_agent/code_agent_prompts.py +46 -0
- jarvis/jarvis_code_agent/code_agent_rules.py +305 -0
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +52 -48
- jarvis/jarvis_code_agent/code_analyzer/base_language.py +12 -10
- jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +12 -11
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +16 -12
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +26 -17
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +558 -104
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +22 -18
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +21 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +20 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +47 -23
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +71 -37
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +162 -35
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +111 -57
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +18 -12
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +185 -183
- jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +2 -1
- jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +24 -15
- jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +227 -141
- jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +321 -247
- jarvis/jarvis_code_agent/code_analyzer/language_registry.py +37 -29
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -13
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +15 -9
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +75 -45
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +87 -52
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +84 -51
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +94 -64
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +109 -71
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +97 -63
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +103 -69
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +271 -268
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +76 -64
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +92 -19
- jarvis/jarvis_code_agent/diff_visualizer.py +998 -0
- jarvis/jarvis_code_agent/lint.py +223 -524
- jarvis/jarvis_code_agent/rule_share_manager.py +158 -0
- jarvis/jarvis_code_agent/rules/clean_code.md +144 -0
- jarvis/jarvis_code_agent/rules/code_review.md +115 -0
- jarvis/jarvis_code_agent/rules/documentation.md +165 -0
- jarvis/jarvis_code_agent/rules/generate_rules.md +52 -0
- jarvis/jarvis_code_agent/rules/performance.md +158 -0
- jarvis/jarvis_code_agent/rules/refactoring.md +139 -0
- jarvis/jarvis_code_agent/rules/security.md +160 -0
- jarvis/jarvis_code_agent/rules/tdd.md +78 -0
- jarvis/jarvis_code_agent/test_rules/cpp_test.md +118 -0
- jarvis/jarvis_code_agent/test_rules/go_test.md +98 -0
- jarvis/jarvis_code_agent/test_rules/java_test.md +99 -0
- jarvis/jarvis_code_agent/test_rules/javascript_test.md +113 -0
- jarvis/jarvis_code_agent/test_rules/php_test.md +117 -0
- jarvis/jarvis_code_agent/test_rules/python_test.md +91 -0
- jarvis/jarvis_code_agent/test_rules/ruby_test.md +102 -0
- jarvis/jarvis_code_agent/test_rules/rust_test.md +86 -0
- jarvis/jarvis_code_agent/utils.py +36 -26
- jarvis/jarvis_code_analysis/checklists/loader.py +21 -21
- jarvis/jarvis_code_analysis/code_review.py +64 -33
- jarvis/jarvis_data/config_schema.json +285 -192
- jarvis/jarvis_git_squash/main.py +8 -6
- jarvis/jarvis_git_utils/git_commiter.py +53 -76
- jarvis/jarvis_mcp/__init__.py +5 -2
- jarvis/jarvis_mcp/sse_mcp_client.py +40 -30
- jarvis/jarvis_mcp/stdio_mcp_client.py +27 -19
- jarvis/jarvis_mcp/streamable_mcp_client.py +35 -26
- jarvis/jarvis_memory_organizer/memory_organizer.py +78 -55
- jarvis/jarvis_methodology/main.py +48 -39
- jarvis/jarvis_multi_agent/__init__.py +56 -23
- jarvis/jarvis_multi_agent/main.py +15 -18
- jarvis/jarvis_platform/base.py +179 -111
- jarvis/jarvis_platform/human.py +27 -16
- jarvis/jarvis_platform/kimi.py +52 -45
- jarvis/jarvis_platform/openai.py +101 -40
- jarvis/jarvis_platform/registry.py +51 -33
- jarvis/jarvis_platform/tongyi.py +68 -38
- jarvis/jarvis_platform/yuanbao.py +59 -43
- jarvis/jarvis_platform_manager/main.py +68 -76
- jarvis/jarvis_platform_manager/service.py +24 -14
- jarvis/jarvis_rag/README_CONFIG.md +314 -0
- jarvis/jarvis_rag/README_DYNAMIC_LOADING.md +311 -0
- jarvis/jarvis_rag/README_ONLINE_MODELS.md +230 -0
- jarvis/jarvis_rag/__init__.py +57 -4
- jarvis/jarvis_rag/cache.py +3 -1
- jarvis/jarvis_rag/cli.py +48 -68
- jarvis/jarvis_rag/embedding_interface.py +39 -0
- jarvis/jarvis_rag/embedding_manager.py +7 -230
- jarvis/jarvis_rag/embeddings/__init__.py +41 -0
- jarvis/jarvis_rag/embeddings/base.py +114 -0
- jarvis/jarvis_rag/embeddings/cohere.py +66 -0
- jarvis/jarvis_rag/embeddings/edgefn.py +117 -0
- jarvis/jarvis_rag/embeddings/local.py +260 -0
- jarvis/jarvis_rag/embeddings/openai.py +62 -0
- jarvis/jarvis_rag/embeddings/registry.py +293 -0
- jarvis/jarvis_rag/llm_interface.py +8 -6
- jarvis/jarvis_rag/query_rewriter.py +8 -9
- jarvis/jarvis_rag/rag_pipeline.py +61 -52
- jarvis/jarvis_rag/reranker.py +7 -75
- jarvis/jarvis_rag/reranker_interface.py +32 -0
- jarvis/jarvis_rag/rerankers/__init__.py +41 -0
- jarvis/jarvis_rag/rerankers/base.py +109 -0
- jarvis/jarvis_rag/rerankers/cohere.py +67 -0
- jarvis/jarvis_rag/rerankers/edgefn.py +140 -0
- jarvis/jarvis_rag/rerankers/jina.py +79 -0
- jarvis/jarvis_rag/rerankers/local.py +89 -0
- jarvis/jarvis_rag/rerankers/registry.py +293 -0
- jarvis/jarvis_rag/retriever.py +58 -43
- jarvis/jarvis_sec/__init__.py +66 -141
- jarvis/jarvis_sec/agents.py +21 -17
- jarvis/jarvis_sec/analysis.py +80 -33
- jarvis/jarvis_sec/checkers/__init__.py +7 -13
- jarvis/jarvis_sec/checkers/c_checker.py +356 -164
- jarvis/jarvis_sec/checkers/rust_checker.py +47 -29
- jarvis/jarvis_sec/cli.py +43 -21
- jarvis/jarvis_sec/clustering.py +430 -272
- jarvis/jarvis_sec/file_manager.py +99 -55
- jarvis/jarvis_sec/parsers.py +9 -6
- jarvis/jarvis_sec/prompts.py +4 -3
- jarvis/jarvis_sec/report.py +44 -22
- jarvis/jarvis_sec/review.py +180 -107
- jarvis/jarvis_sec/status.py +50 -41
- jarvis/jarvis_sec/types.py +3 -0
- jarvis/jarvis_sec/utils.py +160 -83
- jarvis/jarvis_sec/verification.py +411 -181
- jarvis/jarvis_sec/workflow.py +132 -21
- jarvis/jarvis_smart_shell/main.py +28 -41
- jarvis/jarvis_stats/cli.py +14 -12
- jarvis/jarvis_stats/stats.py +28 -19
- jarvis/jarvis_stats/storage.py +14 -8
- jarvis/jarvis_stats/visualizer.py +12 -7
- jarvis/jarvis_tools/base.py +5 -2
- jarvis/jarvis_tools/clear_memory.py +13 -9
- jarvis/jarvis_tools/cli/main.py +23 -18
- jarvis/jarvis_tools/edit_file.py +572 -873
- jarvis/jarvis_tools/execute_script.py +10 -7
- jarvis/jarvis_tools/file_analyzer.py +7 -8
- jarvis/jarvis_tools/meta_agent.py +287 -0
- jarvis/jarvis_tools/methodology.py +5 -3
- jarvis/jarvis_tools/read_code.py +305 -1438
- jarvis/jarvis_tools/read_symbols.py +50 -17
- jarvis/jarvis_tools/read_webpage.py +19 -18
- jarvis/jarvis_tools/registry.py +435 -156
- jarvis/jarvis_tools/retrieve_memory.py +16 -11
- jarvis/jarvis_tools/save_memory.py +8 -6
- jarvis/jarvis_tools/search_web.py +31 -31
- jarvis/jarvis_tools/sub_agent.py +32 -28
- jarvis/jarvis_tools/sub_code_agent.py +44 -60
- jarvis/jarvis_tools/task_list_manager.py +1811 -0
- jarvis/jarvis_tools/virtual_tty.py +29 -19
- jarvis/jarvis_utils/__init__.py +4 -0
- jarvis/jarvis_utils/builtin_replace_map.py +2 -1
- jarvis/jarvis_utils/clipboard.py +9 -8
- jarvis/jarvis_utils/collections.py +331 -0
- jarvis/jarvis_utils/config.py +699 -194
- jarvis/jarvis_utils/dialogue_recorder.py +294 -0
- jarvis/jarvis_utils/embedding.py +6 -3
- jarvis/jarvis_utils/file_processors.py +7 -1
- jarvis/jarvis_utils/fzf.py +9 -3
- jarvis/jarvis_utils/git_utils.py +71 -42
- jarvis/jarvis_utils/globals.py +116 -32
- jarvis/jarvis_utils/http.py +6 -2
- jarvis/jarvis_utils/input.py +318 -83
- jarvis/jarvis_utils/jsonnet_compat.py +119 -104
- jarvis/jarvis_utils/methodology.py +37 -28
- jarvis/jarvis_utils/output.py +201 -44
- jarvis/jarvis_utils/utils.py +986 -628
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/METADATA +49 -33
- jarvis_ai_assistant-1.0.2.dist-info/RECORD +304 -0
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +0 -556
- jarvis/jarvis_tools/generate_new_tool.py +0 -205
- jarvis/jarvis_tools/lsp_client.py +0 -1552
- jarvis/jarvis_tools/rewrite_file.py +0 -105
- jarvis_ai_assistant-0.7.8.dist-info/RECORD +0 -218
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/top_level.txt +0 -0
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
管理所有语言支持的注册和发现机制。
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
7
|
+
|
|
6
8
|
import os
|
|
7
|
-
from typing import Dict
|
|
9
|
+
from typing import Dict
|
|
10
|
+
from typing import Optional
|
|
11
|
+
from typing import Set
|
|
8
12
|
|
|
9
13
|
from .base_language import BaseLanguageSupport
|
|
10
14
|
from .dependency_analyzer import DependencyAnalyzer
|
|
@@ -13,7 +17,7 @@ from .symbol_extractor import SymbolExtractor
|
|
|
13
17
|
|
|
14
18
|
class LanguageRegistry:
|
|
15
19
|
"""语言支持注册表。
|
|
16
|
-
|
|
20
|
+
|
|
17
21
|
负责管理所有已注册的语言支持,提供语言检测和工厂方法。
|
|
18
22
|
"""
|
|
19
23
|
|
|
@@ -23,25 +27,27 @@ class LanguageRegistry:
|
|
|
23
27
|
|
|
24
28
|
def register(self, language_support: BaseLanguageSupport) -> None:
|
|
25
29
|
"""注册一个语言支持。
|
|
26
|
-
|
|
30
|
+
|
|
27
31
|
Args:
|
|
28
32
|
language_support: 语言支持实例
|
|
29
33
|
"""
|
|
30
34
|
lang_name = language_support.language_name
|
|
31
35
|
self._languages[lang_name] = language_support
|
|
32
|
-
|
|
36
|
+
|
|
33
37
|
# 注册文件扩展名映射
|
|
34
38
|
for ext in language_support.file_extensions:
|
|
35
39
|
# 如果扩展名已存在,记录警告但不覆盖(保留第一个注册的)
|
|
36
40
|
if ext in self._extension_map and self._extension_map[ext] != lang_name:
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
PrettyOutput.auto_print(
|
|
42
|
+
f"Warning: Extension {ext} already registered for "
|
|
43
|
+
f"{self._extension_map[ext]}, ignoring registration for {lang_name}"
|
|
44
|
+
)
|
|
39
45
|
else:
|
|
40
46
|
self._extension_map[ext] = lang_name
|
|
41
47
|
|
|
42
48
|
def unregister(self, language_name: str) -> None:
|
|
43
49
|
"""取消注册一个语言支持。
|
|
44
|
-
|
|
50
|
+
|
|
45
51
|
Args:
|
|
46
52
|
language_name: 语言名称
|
|
47
53
|
"""
|
|
@@ -49,7 +55,8 @@ class LanguageRegistry:
|
|
|
49
55
|
self._languages.pop(language_name)
|
|
50
56
|
# 移除扩展名映射
|
|
51
57
|
extensions_to_remove = [
|
|
52
|
-
ext
|
|
58
|
+
ext
|
|
59
|
+
for ext, lang in self._extension_map.items()
|
|
53
60
|
if lang == language_name
|
|
54
61
|
]
|
|
55
62
|
for ext in extensions_to_remove:
|
|
@@ -57,10 +64,10 @@ class LanguageRegistry:
|
|
|
57
64
|
|
|
58
65
|
def detect_language(self, file_path: str) -> Optional[str]:
|
|
59
66
|
"""根据文件路径检测编程语言。
|
|
60
|
-
|
|
67
|
+
|
|
61
68
|
Args:
|
|
62
69
|
file_path: 文件路径
|
|
63
|
-
|
|
70
|
+
|
|
64
71
|
Returns:
|
|
65
72
|
语言名称,如果无法检测则返回None
|
|
66
73
|
"""
|
|
@@ -69,10 +76,10 @@ class LanguageRegistry:
|
|
|
69
76
|
|
|
70
77
|
def get_language_support(self, language_name: str) -> Optional[BaseLanguageSupport]:
|
|
71
78
|
"""获取指定语言的支持实例。
|
|
72
|
-
|
|
79
|
+
|
|
73
80
|
Args:
|
|
74
81
|
language_name: 语言名称
|
|
75
|
-
|
|
82
|
+
|
|
76
83
|
Returns:
|
|
77
84
|
语言支持实例,如果未注册则返回None
|
|
78
85
|
"""
|
|
@@ -80,10 +87,10 @@ class LanguageRegistry:
|
|
|
80
87
|
|
|
81
88
|
def get_symbol_extractor(self, language_name: str) -> Optional[SymbolExtractor]:
|
|
82
89
|
"""获取指定语言的符号提取器。
|
|
83
|
-
|
|
90
|
+
|
|
84
91
|
Args:
|
|
85
92
|
language_name: 语言名称
|
|
86
|
-
|
|
93
|
+
|
|
87
94
|
Returns:
|
|
88
95
|
SymbolExtractor实例,如果不支持则返回None
|
|
89
96
|
"""
|
|
@@ -92,12 +99,14 @@ class LanguageRegistry:
|
|
|
92
99
|
return lang_support.create_symbol_extractor()
|
|
93
100
|
return None
|
|
94
101
|
|
|
95
|
-
def get_dependency_analyzer(
|
|
102
|
+
def get_dependency_analyzer(
|
|
103
|
+
self, language_name: str
|
|
104
|
+
) -> Optional[DependencyAnalyzer]:
|
|
96
105
|
"""获取指定语言的依赖分析器。
|
|
97
|
-
|
|
106
|
+
|
|
98
107
|
Args:
|
|
99
108
|
language_name: 语言名称
|
|
100
|
-
|
|
109
|
+
|
|
101
110
|
Returns:
|
|
102
111
|
DependencyAnalyzer实例,如果不支持则返回None
|
|
103
112
|
"""
|
|
@@ -108,7 +117,7 @@ class LanguageRegistry:
|
|
|
108
117
|
|
|
109
118
|
def get_supported_languages(self) -> Set[str]:
|
|
110
119
|
"""获取所有已注册的语言名称集合。
|
|
111
|
-
|
|
120
|
+
|
|
112
121
|
Returns:
|
|
113
122
|
语言名称集合
|
|
114
123
|
"""
|
|
@@ -116,10 +125,10 @@ class LanguageRegistry:
|
|
|
116
125
|
|
|
117
126
|
def is_supported(self, file_path: str) -> bool:
|
|
118
127
|
"""检查文件是否被支持。
|
|
119
|
-
|
|
128
|
+
|
|
120
129
|
Args:
|
|
121
130
|
file_path: 文件路径
|
|
122
|
-
|
|
131
|
+
|
|
123
132
|
Returns:
|
|
124
133
|
如果文件被支持返回True,否则返回False
|
|
125
134
|
"""
|
|
@@ -132,7 +141,7 @@ _registry = LanguageRegistry()
|
|
|
132
141
|
|
|
133
142
|
def get_registry() -> LanguageRegistry:
|
|
134
143
|
"""获取全局语言注册表实例。
|
|
135
|
-
|
|
144
|
+
|
|
136
145
|
Returns:
|
|
137
146
|
全局LanguageRegistry实例
|
|
138
147
|
"""
|
|
@@ -141,7 +150,7 @@ def get_registry() -> LanguageRegistry:
|
|
|
141
150
|
|
|
142
151
|
def register_language(language_support: BaseLanguageSupport) -> None:
|
|
143
152
|
"""注册一个语言支持(便捷函数)。
|
|
144
|
-
|
|
153
|
+
|
|
145
154
|
Args:
|
|
146
155
|
language_support: 语言支持实例
|
|
147
156
|
"""
|
|
@@ -150,10 +159,10 @@ def register_language(language_support: BaseLanguageSupport) -> None:
|
|
|
150
159
|
|
|
151
160
|
def detect_language(file_path: str) -> Optional[str]:
|
|
152
161
|
"""检测文件的语言(便捷函数)。
|
|
153
|
-
|
|
162
|
+
|
|
154
163
|
Args:
|
|
155
164
|
file_path: 文件路径
|
|
156
|
-
|
|
165
|
+
|
|
157
166
|
Returns:
|
|
158
167
|
语言名称,如果无法检测则返回None
|
|
159
168
|
"""
|
|
@@ -162,10 +171,10 @@ def detect_language(file_path: str) -> Optional[str]:
|
|
|
162
171
|
|
|
163
172
|
def get_symbol_extractor(language: str) -> Optional[SymbolExtractor]:
|
|
164
173
|
"""获取指定语言的符号提取器(便捷函数)。
|
|
165
|
-
|
|
174
|
+
|
|
166
175
|
Args:
|
|
167
176
|
language: 语言名称
|
|
168
|
-
|
|
177
|
+
|
|
169
178
|
Returns:
|
|
170
179
|
SymbolExtractor实例,如果不支持则返回None
|
|
171
180
|
"""
|
|
@@ -174,12 +183,11 @@ def get_symbol_extractor(language: str) -> Optional[SymbolExtractor]:
|
|
|
174
183
|
|
|
175
184
|
def get_dependency_analyzer(language: str) -> Optional[DependencyAnalyzer]:
|
|
176
185
|
"""获取指定语言的依赖分析器(便捷函数)。
|
|
177
|
-
|
|
186
|
+
|
|
178
187
|
Args:
|
|
179
188
|
language: 语言名称
|
|
180
|
-
|
|
189
|
+
|
|
181
190
|
Returns:
|
|
182
191
|
DependencyAnalyzer实例,如果不支持则返回None
|
|
183
192
|
"""
|
|
184
193
|
return _registry.get_dependency_analyzer(language)
|
|
185
|
-
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
提供语言检测和工厂函数,使用语言注册表管理所有语言支持。
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
7
|
+
|
|
6
8
|
from typing import Optional
|
|
7
9
|
|
|
8
10
|
from .dependency_analyzer import DependencyAnalyzer
|
|
9
|
-
from .language_registry import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
register_language,
|
|
14
|
-
)
|
|
11
|
+
from .language_registry import detect_language as _detect_language
|
|
12
|
+
from .language_registry import get_dependency_analyzer as _get_dependency_analyzer
|
|
13
|
+
from .language_registry import get_symbol_extractor as _get_symbol_extractor
|
|
14
|
+
from .language_registry import register_language
|
|
15
15
|
from .symbol_extractor import SymbolExtractor
|
|
16
16
|
|
|
17
17
|
# 自动注册所有语言支持
|
|
@@ -20,13 +20,15 @@ from .symbol_extractor import SymbolExtractor
|
|
|
20
20
|
# Python语言支持(必需,因为它是核心语言)
|
|
21
21
|
try:
|
|
22
22
|
from .languages import PythonLanguageSupport
|
|
23
|
+
|
|
23
24
|
register_language(PythonLanguageSupport())
|
|
24
25
|
except ImportError as e:
|
|
25
|
-
|
|
26
|
+
PrettyOutput.auto_print(f"⚠️ Warning: Failed to import PythonLanguageSupport: {e}")
|
|
26
27
|
|
|
27
28
|
# Rust语言支持(可选,需要tree-sitter)
|
|
28
29
|
try:
|
|
29
30
|
from .languages import RustLanguageSupport
|
|
31
|
+
|
|
30
32
|
register_language(RustLanguageSupport())
|
|
31
33
|
except (ImportError, RuntimeError):
|
|
32
34
|
pass # 静默失败,tree-sitter可能不可用
|
|
@@ -34,6 +36,7 @@ except (ImportError, RuntimeError):
|
|
|
34
36
|
# Go语言支持(可选,需要tree-sitter)
|
|
35
37
|
try:
|
|
36
38
|
from .languages import GoLanguageSupport
|
|
39
|
+
|
|
37
40
|
register_language(GoLanguageSupport())
|
|
38
41
|
except (ImportError, RuntimeError):
|
|
39
42
|
pass # 静默失败,tree-sitter可能不可用
|
|
@@ -41,6 +44,7 @@ except (ImportError, RuntimeError):
|
|
|
41
44
|
# C语言支持(可选,需要tree-sitter)
|
|
42
45
|
try:
|
|
43
46
|
from .languages import CLanguageSupport
|
|
47
|
+
|
|
44
48
|
register_language(CLanguageSupport())
|
|
45
49
|
except (ImportError, RuntimeError):
|
|
46
50
|
pass # 静默失败,tree-sitter可能不可用
|
|
@@ -48,6 +52,7 @@ except (ImportError, RuntimeError):
|
|
|
48
52
|
# C++语言支持(可选,需要tree-sitter)
|
|
49
53
|
try:
|
|
50
54
|
from .languages import CppLanguageSupport
|
|
55
|
+
|
|
51
56
|
register_language(CppLanguageSupport())
|
|
52
57
|
except (ImportError, RuntimeError):
|
|
53
58
|
pass # 静默失败,tree-sitter可能不可用
|
|
@@ -55,6 +60,7 @@ except (ImportError, RuntimeError):
|
|
|
55
60
|
# JavaScript语言支持(可选,需要tree-sitter)
|
|
56
61
|
try:
|
|
57
62
|
from .languages import JavaScriptLanguageSupport
|
|
63
|
+
|
|
58
64
|
register_language(JavaScriptLanguageSupport())
|
|
59
65
|
except (ImportError, RuntimeError):
|
|
60
66
|
pass # 静默失败,tree-sitter可能不可用
|
|
@@ -62,6 +68,7 @@ except (ImportError, RuntimeError):
|
|
|
62
68
|
# TypeScript语言支持(可选,需要tree-sitter)
|
|
63
69
|
try:
|
|
64
70
|
from .languages import TypeScriptLanguageSupport
|
|
71
|
+
|
|
65
72
|
register_language(TypeScriptLanguageSupport())
|
|
66
73
|
except (ImportError, RuntimeError):
|
|
67
74
|
pass # 静默失败,tree-sitter可能不可用
|
|
@@ -69,6 +76,7 @@ except (ImportError, RuntimeError):
|
|
|
69
76
|
# Java语言支持(可选,需要tree-sitter)
|
|
70
77
|
try:
|
|
71
78
|
from .languages import JavaLanguageSupport
|
|
79
|
+
|
|
72
80
|
register_language(JavaLanguageSupport())
|
|
73
81
|
except (ImportError, RuntimeError):
|
|
74
82
|
pass # 静默失败,tree-sitter可能不可用
|
|
@@ -76,10 +84,10 @@ except (ImportError, RuntimeError):
|
|
|
76
84
|
|
|
77
85
|
def detect_language(file_path: str) -> Optional[str]:
|
|
78
86
|
"""检测文件的编程语言。
|
|
79
|
-
|
|
87
|
+
|
|
80
88
|
Args:
|
|
81
89
|
file_path: 文件路径
|
|
82
|
-
|
|
90
|
+
|
|
83
91
|
Returns:
|
|
84
92
|
语言名称,如果无法检测则返回None
|
|
85
93
|
"""
|
|
@@ -88,10 +96,10 @@ def detect_language(file_path: str) -> Optional[str]:
|
|
|
88
96
|
|
|
89
97
|
def get_symbol_extractor(language: str) -> Optional[SymbolExtractor]:
|
|
90
98
|
"""获取指定语言的符号提取器。
|
|
91
|
-
|
|
99
|
+
|
|
92
100
|
Args:
|
|
93
101
|
language: 语言名称
|
|
94
|
-
|
|
102
|
+
|
|
95
103
|
Returns:
|
|
96
104
|
SymbolExtractor实例,如果不支持则返回None
|
|
97
105
|
"""
|
|
@@ -100,10 +108,10 @@ def get_symbol_extractor(language: str) -> Optional[SymbolExtractor]:
|
|
|
100
108
|
|
|
101
109
|
def get_dependency_analyzer(language: str) -> Optional[DependencyAnalyzer]:
|
|
102
110
|
"""获取指定语言的依赖分析器。
|
|
103
|
-
|
|
111
|
+
|
|
104
112
|
Args:
|
|
105
113
|
language: 语言名称
|
|
106
|
-
|
|
114
|
+
|
|
107
115
|
Returns:
|
|
108
116
|
DependencyAnalyzer实例,如果不支持则返回None
|
|
109
117
|
"""
|
|
@@ -8,42 +8,48 @@
|
|
|
8
8
|
|
|
9
9
|
from .python_language import PythonLanguageSupport
|
|
10
10
|
|
|
11
|
-
__all__ = [
|
|
11
|
+
__all__ = ["PythonLanguageSupport"]
|
|
12
12
|
|
|
13
13
|
# 尝试导入tree-sitter相关的语言支持
|
|
14
14
|
try:
|
|
15
15
|
from .rust_language import RustLanguageSupport # noqa: F401
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
__all__.append("RustLanguageSupport")
|
|
17
18
|
except (ImportError, RuntimeError):
|
|
18
19
|
pass
|
|
19
20
|
|
|
20
21
|
try:
|
|
21
22
|
from .go_language import GoLanguageSupport # noqa: F401
|
|
22
|
-
|
|
23
|
+
|
|
24
|
+
__all__.append("GoLanguageSupport")
|
|
23
25
|
except (ImportError, RuntimeError):
|
|
24
26
|
pass
|
|
25
27
|
|
|
26
28
|
try:
|
|
27
|
-
from .c_cpp_language import CLanguageSupport
|
|
28
|
-
|
|
29
|
+
from .c_cpp_language import CLanguageSupport # noqa: F401
|
|
30
|
+
from .c_cpp_language import CppLanguageSupport # noqa: F401
|
|
31
|
+
|
|
32
|
+
__all__.extend(["CLanguageSupport", "CppLanguageSupport"])
|
|
29
33
|
except (ImportError, RuntimeError):
|
|
30
34
|
pass
|
|
31
35
|
|
|
32
36
|
try:
|
|
33
37
|
from .javascript_language import JavaScriptLanguageSupport # noqa: F401
|
|
34
|
-
|
|
38
|
+
|
|
39
|
+
__all__.append("JavaScriptLanguageSupport")
|
|
35
40
|
except (ImportError, RuntimeError):
|
|
36
41
|
pass
|
|
37
42
|
|
|
38
43
|
try:
|
|
39
44
|
from .typescript_language import TypeScriptLanguageSupport # noqa: F401
|
|
40
|
-
|
|
45
|
+
|
|
46
|
+
__all__.append("TypeScriptLanguageSupport")
|
|
41
47
|
except (ImportError, RuntimeError):
|
|
42
48
|
pass
|
|
43
49
|
|
|
44
50
|
try:
|
|
45
51
|
from .java_language import JavaLanguageSupport # noqa: F401
|
|
46
|
-
|
|
52
|
+
|
|
53
|
+
__all__.append("JavaLanguageSupport")
|
|
47
54
|
except (ImportError, RuntimeError):
|
|
48
55
|
pass
|
|
49
|
-
|
|
@@ -2,17 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import re
|
|
5
|
-
from typing import List
|
|
5
|
+
from typing import List
|
|
6
|
+
from typing import Optional
|
|
7
|
+
from typing import Set
|
|
8
|
+
from typing import cast
|
|
6
9
|
|
|
7
|
-
from tree_sitter import Language
|
|
10
|
+
from tree_sitter import Language
|
|
11
|
+
from tree_sitter import Node
|
|
8
12
|
|
|
9
13
|
from ..base_language import BaseLanguageSupport
|
|
10
|
-
from ..dependency_analyzer import Dependency
|
|
14
|
+
from ..dependency_analyzer import Dependency
|
|
15
|
+
from ..dependency_analyzer import DependencyAnalyzer
|
|
16
|
+
from ..dependency_analyzer import DependencyGraph
|
|
11
17
|
from ..file_ignore import filter_walk_dirs
|
|
12
|
-
from ..symbol_extractor import Symbol
|
|
18
|
+
from ..symbol_extractor import Symbol
|
|
19
|
+
from ..symbol_extractor import SymbolExtractor
|
|
13
20
|
from ..tree_sitter_extractor import TreeSitterExtractor
|
|
14
21
|
|
|
15
|
-
|
|
16
22
|
# --- C/C++ Symbol Query ---
|
|
17
23
|
|
|
18
24
|
# C语言查询(不包含class_specifier,因为C不支持class)
|
|
@@ -69,19 +75,24 @@ CPP_SYMBOL_QUERY = """
|
|
|
69
75
|
|
|
70
76
|
try:
|
|
71
77
|
import tree_sitter_c
|
|
72
|
-
|
|
78
|
+
|
|
79
|
+
C_LANGUAGE: Optional[Language] = cast(Optional[Language], tree_sitter_c.language())
|
|
73
80
|
except (ImportError, Exception):
|
|
74
81
|
C_LANGUAGE = None
|
|
75
82
|
|
|
76
83
|
try:
|
|
77
84
|
import tree_sitter_cpp
|
|
78
|
-
|
|
85
|
+
|
|
86
|
+
CPP_LANGUAGE: Optional[Language] = cast(
|
|
87
|
+
Optional[Language], tree_sitter_cpp.language()
|
|
88
|
+
)
|
|
79
89
|
except (ImportError, Exception):
|
|
80
90
|
CPP_LANGUAGE = None
|
|
81
91
|
|
|
82
92
|
|
|
83
93
|
# --- C/C++ Symbol Extractors ---
|
|
84
94
|
|
|
95
|
+
|
|
85
96
|
class CSymbolExtractor(TreeSitterExtractor):
|
|
86
97
|
"""Extracts symbols from C code using tree-sitter."""
|
|
87
98
|
|
|
@@ -90,7 +101,9 @@ class CSymbolExtractor(TreeSitterExtractor):
|
|
|
90
101
|
raise RuntimeError("C tree-sitter grammar not available.")
|
|
91
102
|
super().__init__(C_LANGUAGE, C_SYMBOL_QUERY)
|
|
92
103
|
|
|
93
|
-
def _create_symbol_from_capture(
|
|
104
|
+
def _create_symbol_from_capture(
|
|
105
|
+
self, node: Node, name: str, file_path: str
|
|
106
|
+
) -> Optional[Symbol]:
|
|
94
107
|
kind_map = {
|
|
95
108
|
"function.name": "function",
|
|
96
109
|
"struct.name": "struct",
|
|
@@ -103,8 +116,11 @@ class CSymbolExtractor(TreeSitterExtractor):
|
|
|
103
116
|
if not symbol_kind:
|
|
104
117
|
return None
|
|
105
118
|
|
|
119
|
+
if node.text is None:
|
|
120
|
+
return None
|
|
121
|
+
|
|
106
122
|
return Symbol(
|
|
107
|
-
name=node.text.decode(
|
|
123
|
+
name=node.text.decode("utf8"),
|
|
108
124
|
kind=symbol_kind,
|
|
109
125
|
file_path=file_path,
|
|
110
126
|
line_start=node.start_point[0] + 1,
|
|
@@ -120,7 +136,9 @@ class CppSymbolExtractor(TreeSitterExtractor):
|
|
|
120
136
|
raise RuntimeError("C++ tree-sitter grammar not available.")
|
|
121
137
|
super().__init__(CPP_LANGUAGE, CPP_SYMBOL_QUERY)
|
|
122
138
|
|
|
123
|
-
def _create_symbol_from_capture(
|
|
139
|
+
def _create_symbol_from_capture(
|
|
140
|
+
self, node: Node, name: str, file_path: str
|
|
141
|
+
) -> Optional[Symbol]:
|
|
124
142
|
kind_map = {
|
|
125
143
|
"function.name": "function",
|
|
126
144
|
"struct.name": "struct",
|
|
@@ -138,19 +156,23 @@ class CppSymbolExtractor(TreeSitterExtractor):
|
|
|
138
156
|
|
|
139
157
|
# For anonymous namespaces, use a generated name
|
|
140
158
|
if name == "namespace.name":
|
|
141
|
-
symbol_name =
|
|
159
|
+
symbol_name = (
|
|
160
|
+
node.text.decode("utf8") if node.text else "<anonymous_namespace>"
|
|
161
|
+
)
|
|
142
162
|
elif name == "template":
|
|
143
163
|
# For template declarations, extract the template name or use a generic name
|
|
144
164
|
# Try to find the function/class name after template
|
|
145
|
-
|
|
165
|
+
if node.text is None:
|
|
166
|
+
return None
|
|
167
|
+
template_text = node.text.decode("utf8").strip()
|
|
146
168
|
# Extract template parameters and the following declaration
|
|
147
169
|
# This is a simplified extraction - in practice, you might want more sophisticated parsing
|
|
148
|
-
if
|
|
170
|
+
if "template" in template_text:
|
|
149
171
|
# Try to extract the name after template<...>
|
|
150
|
-
parts = template_text.split(
|
|
172
|
+
parts = template_text.split(">", 1)
|
|
151
173
|
if len(parts) > 1:
|
|
152
174
|
# Look for function/class name in the second part
|
|
153
|
-
match = re.search(r
|
|
175
|
+
match = re.search(r"\b(function|class|struct)\s+(\w+)", parts[1])
|
|
154
176
|
if match:
|
|
155
177
|
symbol_name = f"template_{match.group(2)}"
|
|
156
178
|
else:
|
|
@@ -160,8 +182,10 @@ class CppSymbolExtractor(TreeSitterExtractor):
|
|
|
160
182
|
else:
|
|
161
183
|
symbol_name = "template"
|
|
162
184
|
else:
|
|
163
|
-
|
|
164
|
-
|
|
185
|
+
if node.text is None:
|
|
186
|
+
return None
|
|
187
|
+
symbol_name = node.text.decode("utf8")
|
|
188
|
+
|
|
165
189
|
if not symbol_name:
|
|
166
190
|
return None
|
|
167
191
|
|
|
@@ -176,76 +200,83 @@ class CppSymbolExtractor(TreeSitterExtractor):
|
|
|
176
200
|
|
|
177
201
|
# --- C/C++ Dependency Analyzers ---
|
|
178
202
|
|
|
203
|
+
|
|
179
204
|
class CDependencyAnalyzer(DependencyAnalyzer):
|
|
180
205
|
"""Analyzes C include dependencies."""
|
|
181
206
|
|
|
182
207
|
def analyze_imports(self, file_path: str, content: str) -> List[Dependency]:
|
|
183
208
|
"""Analyzes C #include statements."""
|
|
184
209
|
dependencies: List[Dependency] = []
|
|
185
|
-
|
|
210
|
+
|
|
186
211
|
# Match #include directives
|
|
187
212
|
# Format: #include <header.h> or #include "header.h"
|
|
188
213
|
include_pattern = re.compile(r'#include\s+[<"]([^>"]+)[>"]')
|
|
189
|
-
|
|
190
|
-
for line_num, line in enumerate(content.split(
|
|
214
|
+
|
|
215
|
+
for line_num, line in enumerate(content.split("\n"), start=1):
|
|
191
216
|
match = include_pattern.search(line)
|
|
192
217
|
if match:
|
|
193
218
|
header = match.group(1)
|
|
194
|
-
dependencies.append(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
219
|
+
dependencies.append(
|
|
220
|
+
Dependency(
|
|
221
|
+
from_module=header,
|
|
222
|
+
imported_symbol=None,
|
|
223
|
+
file_path=file_path,
|
|
224
|
+
line=line_num,
|
|
225
|
+
)
|
|
226
|
+
)
|
|
227
|
+
|
|
201
228
|
return dependencies
|
|
202
229
|
|
|
203
230
|
def build_dependency_graph(self, project_root: str) -> DependencyGraph:
|
|
204
231
|
"""Builds a dependency graph for a C project."""
|
|
205
232
|
graph = DependencyGraph()
|
|
206
|
-
extensions = {
|
|
207
|
-
|
|
233
|
+
extensions = {".c", ".h"}
|
|
234
|
+
|
|
208
235
|
for root, dirs, files in os.walk(project_root):
|
|
209
236
|
dirs[:] = filter_walk_dirs(dirs)
|
|
210
|
-
|
|
237
|
+
|
|
211
238
|
for file in files:
|
|
212
239
|
if not any(file.endswith(ext) for ext in extensions):
|
|
213
240
|
continue
|
|
214
|
-
|
|
241
|
+
|
|
215
242
|
file_path = os.path.join(root, file)
|
|
216
243
|
try:
|
|
217
|
-
with open(file_path,
|
|
244
|
+
with open(file_path, "r", encoding="utf-8", errors="replace") as f:
|
|
218
245
|
content = f.read()
|
|
219
|
-
|
|
246
|
+
|
|
220
247
|
dependencies = self.analyze_imports(file_path, content)
|
|
221
248
|
for dep in dependencies:
|
|
222
|
-
dep_path = self._resolve_header_path(
|
|
249
|
+
dep_path = self._resolve_header_path(
|
|
250
|
+
project_root, dep.from_module, file_path
|
|
251
|
+
)
|
|
223
252
|
if dep_path and dep_path != file_path:
|
|
224
253
|
graph.add_dependency(file_path, dep_path)
|
|
225
254
|
except Exception:
|
|
226
255
|
continue
|
|
227
|
-
|
|
256
|
+
|
|
228
257
|
return graph
|
|
229
258
|
|
|
230
|
-
def _resolve_header_path(
|
|
259
|
+
def _resolve_header_path(
|
|
260
|
+
self, project_root: str, header_name: str, from_file: str
|
|
261
|
+
) -> Optional[str]:
|
|
231
262
|
"""Resolve a header name to a file path."""
|
|
232
263
|
# Try relative to current file
|
|
233
264
|
base_dir = os.path.dirname(from_file)
|
|
234
265
|
relative_path = os.path.join(base_dir, header_name)
|
|
235
266
|
if os.path.exists(relative_path):
|
|
236
267
|
return relative_path
|
|
237
|
-
|
|
268
|
+
|
|
238
269
|
# Try in project root
|
|
239
270
|
for root, dirs, files in os.walk(project_root):
|
|
240
271
|
dirs[:] = filter_walk_dirs(dirs)
|
|
241
272
|
if header_name in files:
|
|
242
273
|
return os.path.join(root, header_name)
|
|
243
|
-
|
|
274
|
+
|
|
244
275
|
return None
|
|
245
276
|
|
|
246
277
|
def _is_source_file(self, file_path: str) -> bool:
|
|
247
278
|
"""Check if a file is a C source file."""
|
|
248
|
-
return file_path.endswith((
|
|
279
|
+
return file_path.endswith((".c", ".h"))
|
|
249
280
|
|
|
250
281
|
|
|
251
282
|
class CppDependencyAnalyzer(CDependencyAnalyzer):
|
|
@@ -253,7 +284,7 @@ class CppDependencyAnalyzer(CDependencyAnalyzer):
|
|
|
253
284
|
|
|
254
285
|
def _is_source_file(self, file_path: str) -> bool:
|
|
255
286
|
"""Check if a file is a C++ source file."""
|
|
256
|
-
return file_path.endswith((
|
|
287
|
+
return file_path.endswith((".cpp", ".hpp", ".cc", ".cxx", ".hxx", ".h"))
|
|
257
288
|
|
|
258
289
|
|
|
259
290
|
class CLanguageSupport(BaseLanguageSupport):
|
|
@@ -261,11 +292,11 @@ class CLanguageSupport(BaseLanguageSupport):
|
|
|
261
292
|
|
|
262
293
|
@property
|
|
263
294
|
def language_name(self) -> str:
|
|
264
|
-
return
|
|
295
|
+
return "c"
|
|
265
296
|
|
|
266
297
|
@property
|
|
267
298
|
def file_extensions(self) -> Set[str]:
|
|
268
|
-
return {
|
|
299
|
+
return {".c", ".h"}
|
|
269
300
|
|
|
270
301
|
def create_symbol_extractor(self) -> Optional[SymbolExtractor]:
|
|
271
302
|
try:
|
|
@@ -282,11 +313,11 @@ class CppLanguageSupport(BaseLanguageSupport):
|
|
|
282
313
|
|
|
283
314
|
@property
|
|
284
315
|
def language_name(self) -> str:
|
|
285
|
-
return
|
|
316
|
+
return "cpp"
|
|
286
317
|
|
|
287
318
|
@property
|
|
288
319
|
def file_extensions(self) -> Set[str]:
|
|
289
|
-
return {
|
|
320
|
+
return {".cpp", ".hpp", ".cc", ".cxx", ".hxx"}
|
|
290
321
|
|
|
291
322
|
def create_symbol_extractor(self) -> Optional[SymbolExtractor]:
|
|
292
323
|
try:
|
|
@@ -296,4 +327,3 @@ class CppLanguageSupport(BaseLanguageSupport):
|
|
|
296
327
|
|
|
297
328
|
def create_dependency_analyzer(self) -> Optional[DependencyAnalyzer]:
|
|
298
329
|
return CppDependencyAnalyzer()
|
|
299
|
-
|