llmcodegen/src/llm_codegen/fix_generator.py

147 lines
6.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
from pathlib import Path
from typing import List, Optional
from .core import CodeGenerator
from .models import OutputFormat
class FixGenerator(CodeGenerator):
"""处理 Bug 修复逻辑的生成器类,继承自 BaseGenerator。"""
def __init__(self, **kwargs):
"""初始化 FixGenerator继承基类参数。"""
super().__init__(**kwargs)
def process_fix(
self,
bug_issue_path: Path,
output_format: OutputFormat = OutputFormat.FULL,
) -> bool:
"""
处理 fix 命令逻辑:读取 Bug 工单,分析变更,生成并应用修复代码。
Args:
bug_issue_path: Bug 工单文件路径(如 bug.issue
output_format: 输出格式,默认为 FULL支持 DIFF 用于差异生成
Returns:
bool: 修复是否成功
"""
# 读取 Bug 工单文件内容
try:
with open(bug_issue_path, "r", encoding="utf-8") as f:
issue_content = f.read()
except Exception as e:
self.logger.error(f"读取 Bug 工单文件失败: {e}")
self.console.print(f"[bold red]❌ 读取 Bug 工单文件失败: {e}[/bold red]")
return False
# 调用 LLM 分析工单,获取变更计划
try:
analysis = self._analyze_issue(issue_content, "bug")
except Exception as e:
self.logger.error(f"分析工单失败: {e}")
self.console.print(f"[bold red]❌ 分析工单失败: {e}[/bold red]")
return False
affected_files = analysis.get("affected_files", [])
design_updates = analysis.get("design_updates", {})
successful_files = []
for file_info in affected_files:
file_path = file_info.get("path")
action = file_info.get("action") # 'create' 或 'modify'
description = file_info.get("description", "")
dependencies = file_info.get("dependencies", [])
if action == "modify":
# 修改现有文件:读取当前内容
full_path = self.output_dir / file_path
if not full_path.exists():
self.logger.error(f"文件不存在,无法修改: {file_path}")
self.console.print(f"[bold red]❌ 文件不存在,无法修改: {file_path}[/bold red]")
continue
try:
with open(full_path, "r", encoding="utf-8") as f:
existing_content = f.read()
except Exception as e:
self.logger.error(f"读取文件 {file_path} 失败: {e}")
self.console.print(f"[bold red]❌ 读取文件 {file_path} 失败: {e}[/bold red]")
continue
# 生成修复代码
instruction = (
f"根据 Bug 工单修复文件 '{file_path}'。工单摘要: {issue_content[:200]}..."
)
code, desc, commands = self.generate_file(
file_path=file_path,
prompt_instruction=instruction,
dependency_files=dependencies,
existing_content=existing_content,
output_format=output_format,
)
# 写入修复后的内容
try:
with open(full_path, "w", encoding="utf-8") as f:
f.write(code)
self.logger.info(f"已修复文件: {file_path} - {desc}")
successful_files.append(file_path)
except Exception as e:
self.logger.error(f"写入文件 {file_path} 失败: {e}")
self.console.print(f"[bold red]❌ 写入文件 {file_path} 失败: {e}[/bold red]")
continue
# 执行相关命令
for cmd in commands:
self.execute_command(cmd, cwd=self.output_dir)
# 更新 design.json 中的文件条目
self.update_file_entry(file_path, code)
elif action == "create":
# 创建新文件:无需现有内容
instruction = (
f"根据 Bug 工单创建文件 '{file_path}'。工单摘要: {issue_content[:200]}..."
)
code, desc, commands = self.generate_file(
file_path=file_path,
prompt_instruction=instruction,
dependency_files=dependencies,
existing_content=None,
output_format=output_format,
)
# 写入新文件
full_path = self.output_dir / file_path
full_path.parent.mkdir(parents=True, exist_ok=True)
try:
with open(full_path, "w", encoding="utf-8") as f:
f.write(code)
self.logger.info(f"已创建文件: {file_path} - {desc}")
successful_files.append(file_path)
except Exception as e:
self.logger.error(f"创建文件 {file_path} 失败: {e}")
self.console.print(f"[bold red]❌ 创建文件 {file_path} 失败: {e}[/bold red]")
continue
for cmd in commands:
self.execute_command(cmd, cwd=self.output_dir)
# 添加新条目到 design.json
self._update_design([file_path], design_updates)
# 如果有设计更新,整体更新 design.json
if design_updates and successful_files:
self._update_design(successful_files, design_updates)
if successful_files:
self.logger.info(f"修复成功,处理了 {len(successful_files)} 个文件")
self.console.print(f"[green]✅ 修复成功,处理了 {len(successful_files)} 个文件[/green]")
return True
else:
self.logger.error("修复失败,没有文件被成功处理")
self.console.print("[bold red]❌ 修复失败,没有文件被成功处理[/bold red]")
return False