Skip to content

Discussion about Support for Multiple Programming Languages #86

@Umpire2018

Description

@Umpire2018

@magaton @Major-wagh @sandeshchand @alikinir Adapted from issue #60 for continued discussion in this thread.

Background

Currently, the repository primarily supports Python by leveraging jedi and custom-built modules to construct the Repository Map. Developers with the necessary skills are encouraged to understand, modify, and adapt this functionality for their specific needs. Due to the substantial workload required, this project will not consider supporting additional languages in the short term. The functionality constructs the Repository Map and saves it to .project_doc_record, which serves as the basis for subsequent features in the repoagent project:

def find_all_referencer(
repo_path, variable_name, file_path, line_number, column_number, in_file_only=False
):
"""复制过来的之前的实现"""
script = jedi.Script(path=os.path.join(repo_path, file_path))
try:
if in_file_only:
references = script.get_references(
line=line_number, column=column_number, scope="file"
)
else:
references = script.get_references(line=line_number, column=column_number)
# 过滤出变量名为 variable_name 的引用,并返回它们的位置
variable_references = [ref for ref in references if ref.name == variable_name]
# if variable_name == "need_to_generate":
# import pdb; pdb.set_trace()
return [
(os.path.relpath(ref.module_path, repo_path), ref.line, ref.column)
for ref in variable_references
if not (ref.line == line_number and ref.column == column_number)
]
except Exception as e:
# 打印错误信息和相关参数
logger.error(f"Error occurred: {e}")
logger.error(
f"Parameters: variable_name={variable_name}, file_path={file_path}, line_number={line_number}, column_number={column_number}"
)
return []
@dataclass
class MetaInfo:
repo_path: Path = "" # type: ignore
document_version: str = (
"" # 随时间变化,""代表没完成,否则对应一个目标仓库的commit hash
)
target_repo_hierarchical_tree: "DocItem" = field(
default_factory=lambda: DocItem()
) # 整个repo的文件结构
white_list: Any[List] = None
fake_file_reflection: Dict[str, str] = field(default_factory=dict)
jump_files: List[str] = field(default_factory=list)
deleted_items_from_older_meta: List[List] = field(default_factory=list)
in_generation_process: bool = False
checkpoint_lock: threading.Lock = threading.Lock()
@staticmethod
def init_meta_info(file_path_reflections, jump_files) -> MetaInfo:
"""从一个仓库path中初始化metainfo"""
setting = SettingsManager.get_setting()
project_abs_path = setting.project.target_repo
print(
f"{Fore.LIGHTRED_EX}Initializing MetaInfo: {Style.RESET_ALL}from {project_abs_path}"
)
file_handler = FileHandler(project_abs_path, None)
repo_structure = file_handler.generate_overall_structure(
file_path_reflections, jump_files
)
metainfo = MetaInfo.from_project_hierarchy_json(repo_structure)
metainfo.repo_path = project_abs_path
metainfo.fake_file_reflection = file_path_reflections
metainfo.jump_files = jump_files
return metainfo
@staticmethod
def from_checkpoint_path(checkpoint_dir_path: Path) -> MetaInfo:
"""从已有的metainfo dir里面读取metainfo"""
setting = SettingsManager.get_setting()
project_hierarchy_json_path = checkpoint_dir_path / "project_hierarchy.json"
with open(project_hierarchy_json_path, "r", encoding="utf-8") as reader:
project_hierarchy_json = json.load(reader)
metainfo = MetaInfo.from_project_hierarchy_json(project_hierarchy_json)
with open(
checkpoint_dir_path / "meta-info.json", "r", encoding="utf-8"
) as reader:
meta_data = json.load(reader)
metainfo.repo_path = setting.project.target_repo
metainfo.document_version = meta_data["doc_version"]
metainfo.fake_file_reflection = meta_data["fake_file_reflection"]
metainfo.jump_files = meta_data["jump_files"]
metainfo.in_generation_process = meta_data["in_generation_process"]
metainfo.deleted_items_from_older_meta = meta_data[
"deleted_items_from_older_meta"
]
print(f"{Fore.CYAN}Loading MetaInfo:{Style.RESET_ALL} {checkpoint_dir_path}")
return metainfo

Community Interest

Multiple users have expressed interest in extending this capability to additional programming languages and have provided valuable feedback. We sincerely appreciate their contributions and ideas. Below are some of my thoughts on this topic.

First, the aider project utilizes tree-sitter to implement their Repository Map feature. However, it has limitations. Since different programming languages have unique features, supporting multiple languages simultaneously requires developers to possess strong cross-language expertise.

I have personally attempted to use tree-sitter to mimic jedi for constructing reference relationships here.
However, this effort has been temporarily shelved.

Additionally, RepoGraph has made progress in this area and published a related paper.
The work introduces an effective plug-in, repo-level module that provides the desired context and significantly enhances LLM-based AI software engineering capabilities.

Another approach is the Language Server Protocol (LSP). With implementations for many languages, LSP can assist in static analysis.

Proposal

Based on the above, my personal suggestion is to adopt different implementations for different programming languages to assist in analysis. The results can then be stored in a unified format to integrate seamlessly with repoagent.

This is a preliminary idea intended to spark further discussion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions