fix lint error

This commit is contained in:
bobo 2024-07-18 16:22:22 +08:00
parent c47261b06f
commit 7c30ca2135
7 changed files with 159 additions and 107 deletions

View File

@ -184,7 +184,9 @@ class IDEService:
return self._result
@rpc_method
def select_range(self, fileName: str, startLine: int, startColumn: int, endLine: int, endColumn: int) -> bool:
def select_range(
self, fileName: str, startLine: int, startColumn: int, endLine: int, endColumn: int
) -> bool:
"""
Selects a range of text in the specified file.
@ -201,4 +203,4 @@ class IDEService:
Note:
If startLine is -1, it cancels the current selection.
"""
return self._result
return self._result

View File

@ -1,13 +1,15 @@
import os
import sys
import json
import os
import subprocess
import sys
from devchat.ide import IDEService
from lib.chatmark import Button
GLOBAL_CONFIG_PATH = os.path.join(os.path.expanduser("~"), ".chat", ".workflow_config.json")
def save_config(config_path, item, value):
if os.path.exists(config_path):
with open(config_path, "r", encoding="utf-8") as f:
@ -19,32 +21,35 @@ def save_config(config_path, item, value):
with open(config_path, "w", encoding="utf-8") as f:
json.dump(config, f, indent=4)
def write_python_path_to_config():
"""
Write the current system Python path to the configuration.
"""
python_path = sys.executable
save_config(GLOBAL_CONFIG_PATH, 'aider_python', python_path)
save_config(GLOBAL_CONFIG_PATH, "aider_python", python_path)
print(f"Python path '{python_path}' has been written to the configuration.")
def get_aider_files():
"""
.chat/.aider_files文件中读取aider文件列表
"""
aider_files_path = os.path.join('.chat', '.aider_files')
aider_files_path = os.path.join(".chat", ".aider_files")
if not os.path.exists(aider_files_path):
return []
with open(aider_files_path, 'r') as f:
with open(aider_files_path, "r") as f:
return [line.strip() for line in f if line.strip()]
def run_aider(message, files):
"""
运行aider命令
"""
python = sys.executable
model = os.environ.get('LLM_MODEL', 'gpt-3.5-turbo-1106')
model = os.environ.get("LLM_MODEL", "gpt-3.5-turbo-1106")
cmd = [
python,
"-m",
@ -59,12 +64,7 @@ def run_aider(message, files):
message,
] + files
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
has_started = False
aider_output = ""
@ -85,17 +85,18 @@ def run_aider(message, files):
return aider_output
def apply_changes(changes, files):
"""
应用aider生成的更改
"""
changes_file = '.chat/changes.txt'
changes_file = ".chat/changes.txt"
os.makedirs(os.path.dirname(changes_file), exist_ok=True)
with open(changes_file, 'w') as f:
with open(changes_file, "w") as f:
f.write(changes)
python = sys.executable
model = os.environ.get('LLM_MODEL', 'gpt-3.5-turbo-1106')
model = os.environ.get("LLM_MODEL", "gpt-3.5-turbo-1106")
cmd = [
python,
@ -109,12 +110,7 @@ def apply_changes(changes, files):
changes_file,
] + files
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
has_started = False
for line in process.stdout:
@ -133,6 +129,7 @@ def apply_changes(changes, files):
os.remove(changes_file)
def main():
"""
Main function to run the aider command.
@ -150,14 +147,17 @@ def main():
if len(sys.argv) < 2:
print("Usage: python command.py <message>", file=sys.stderr)
sys.exit(1)
write_python_path_to_config()
message = sys.argv[1]
files = get_aider_files()
if not files:
print("No files added to aider. Please add files using 'aider.files.add' command.", file=sys.stderr)
print(
"No files added to aider. Please add files using 'aider.files.add' command.",
file=sys.stderr,
)
sys.exit(1)
print("Running aider...\n", flush=True)
@ -168,11 +168,11 @@ def main():
sys.exit(0)
print("\nApplying changes...\n", flush=True)
# 保存原始文件内容
original_contents = {}
for file in files:
with open(file, 'r') as f:
with open(file, "r") as f:
original_contents[file] = f.read()
# 应用更改
@ -181,25 +181,22 @@ def main():
# 读取更新后的文件内容
updated_contents = {}
for file in files:
with open(file, 'r') as f:
with open(file, "r") as f:
updated_contents[file] = f.read()
# 还原原始文件内容
for file in files:
with open(file, 'w') as f:
with open(file, "w") as f:
f.write(original_contents[file])
# 使用 IDEService 展示差异
ide_service = IDEService()
for index,file in enumerate(files):
for index, file in enumerate(files):
ide_service.diff_apply(file, updated_contents[file])
if index < len(files) - 1:
# 等待用户确认
button = Button(
[
"Show Next Changes",
"Cancel"
],
["Show Next Changes", "Cancel"],
)
button.render()
@ -212,5 +209,6 @@ def main():
print("Changes have been displayed in the IDE.")
if __name__ == "__main__":
main()

View File

@ -1,6 +1,7 @@
import os
import sys
def is_valid_path(path):
"""
检查路径是否为有效的文件路径形式
@ -9,10 +10,14 @@ def is_valid_path(path):
# 尝试规范化路径
normalized_path = os.path.normpath(path)
# 检查路径是否是绝对路径或相对路径
return os.path.isabs(normalized_path) or not os.path.dirname(normalized_path) == normalized_path
return (
os.path.isabs(normalized_path)
or not os.path.dirname(normalized_path) == normalized_path
)
except Exception:
return False
def add_file(file_path):
# 1. 检查是否为有效的文件路径形式
if not is_valid_path(file_path):
@ -23,22 +28,22 @@ def add_file(file_path):
abs_file_path = file_path.strip()
# 2. 将新增文件路径存储到.chat/.aider_files文件中
aider_files_path = os.path.join('.chat', '.aider_files')
aider_files_path = os.path.join(".chat", ".aider_files")
# 确保.chat目录存在
os.makedirs(os.path.dirname(aider_files_path), exist_ok=True)
# 读取现有文件列表
existing_files = set()
if os.path.exists(aider_files_path):
with open(aider_files_path, 'r') as f:
with open(aider_files_path, "r") as f:
existing_files = set(line.strip() for line in f)
# 添加新文件
existing_files.add(abs_file_path)
# 写入更新后的文件列表
with open(aider_files_path, 'w') as f:
with open(aider_files_path, "w") as f:
for file in sorted(existing_files):
f.write(f"{file}\n")
@ -47,6 +52,7 @@ def add_file(file_path):
for file in sorted(existing_files):
print(f"- {file}")
def main():
if len(sys.argv) != 2 or sys.argv[1].strip() == "":
print("Usage: /aider.files.add <file_path>", file=sys.stderr)
@ -55,5 +61,6 @@ def main():
file_path = sys.argv[1]
add_file(file_path)
if __name__ == "__main__":
main()
main()

View File

@ -1,16 +1,17 @@
import os
import sys
def list_files():
aider_files_path = os.path.join('.chat', '.aider_files')
aider_files_path = os.path.join(".chat", ".aider_files")
# 确保.chat/.aider_files文件存在
if not os.path.exists(aider_files_path):
print("No files have been added to aider yet.")
sys.exit(0)
# 读取文件列表
with open(aider_files_path, 'r') as f:
with open(aider_files_path, "r") as f:
files = [line.strip() for line in f]
# 打印文件列表
@ -21,8 +22,10 @@ def list_files():
else:
print("No files found in aider.")
def main():
list_files()
if __name__ == "__main__":
main()
main()

View File

@ -1,6 +1,7 @@
import os
import sys
def is_valid_path(path):
"""
检查路径是否为有效的文件路径形式
@ -9,10 +10,14 @@ def is_valid_path(path):
# 尝试规范化路径
normalized_path = os.path.normpath(path)
# 检查路径是否是绝对路径或相对路径
return os.path.isabs(normalized_path) or not os.path.dirname(normalized_path) == normalized_path
return (
os.path.isabs(normalized_path)
or not os.path.dirname(normalized_path) == normalized_path
)
except Exception:
return False
def remove_file(file_path):
# 1. 检查是否为有效的文件路径形式
if not is_valid_path(file_path):
@ -23,8 +28,8 @@ def remove_file(file_path):
abs_file_path = file_path.strip()
# 2. 从.chat/.aider_files文件中移除指定文件路径
aider_files_path = os.path.join('.chat', '.aider_files')
aider_files_path = os.path.join(".chat", ".aider_files")
# 确保.chat目录存在
if not os.path.exists(aider_files_path):
print(f"Error: '{aider_files_path}' does not exist.", file=sys.stderr)
@ -32,7 +37,7 @@ def remove_file(file_path):
# 读取现有文件列表
existing_files = set()
with open(aider_files_path, 'r') as f:
with open(aider_files_path, "r") as f:
existing_files = set(line.strip() for line in f)
# 检查文件是否在列表中
@ -44,7 +49,7 @@ def remove_file(file_path):
existing_files.remove(abs_file_path)
# 写入更新后的文件列表
with open(aider_files_path, 'w') as f:
with open(aider_files_path, "w") as f:
for file in sorted(existing_files):
f.write(f"{file}\n")
@ -53,6 +58,7 @@ def remove_file(file_path):
for file in sorted(existing_files):
print(f"- {file}")
def main():
if len(sys.argv) != 2 or sys.argv[1].strip() == "":
print("Usage: /aider.files.remove <file_path>", file=sys.stderr)
@ -61,5 +67,6 @@ def main():
file_path = sys.argv[1]
remove_file(file_path)
if __name__ == "__main__":
main()
main()

View File

@ -26,6 +26,7 @@ def extract_edits_block(text):
else:
return text[start:end]
def extract_markdown_block(text):
"""
Extracts the first Markdown code block from the given text without the language specifier.
@ -78,8 +79,11 @@ def input_issue_descriptions(file_path, issue_line_num):
# step 3 : call llm to generate fix solutions
SYSTEM_ROLE_DIFF= """
You are a code refactoring assistant. Your task is to refactor the user's code to fix lint diagnostics. You will be provided with a code snippet and a list of diagnostics. Your response should include two parts:
SYSTEM_ROLE_DIFF = """
You are a code refactoring assistant.
Your task is to refactor the user's code to fix lint diagnostics.
You will be provided with a code snippet and a list of diagnostics. \
Your response should include two parts:
1. An explanation of the reason for the diagnostics and how to fix them.
2. The edited code snippet with the diagnostics fixed, using markdown format for clarity.
@ -105,9 +109,14 @@ Or like this, if a variable is not defined:
```
Please note the following important points:
1. The new code should maintain the correct indentation. The "+ " sign is followed by two spaces for indentation, which should be included in the edited code.
2. In addition to outputting key editing information, sufficient context (i.e., key information before and after editing) should also be provided to help locate the specific position of the edited line.
3. Don't output all file lines, if some lines are unchanged, please use "..." to indicate the ignored lines.
1. The new code should maintain the correct indentation. \
The "+ " sign is followed by two spaces for indentation, \
which should be included in the edited code.
2. In addition to outputting key editing information, \
sufficient context (i.e., key information before and after editing) \
should also be provided to help locate the specific position of the edited line.
3. Don't output all file lines, if some lines are unchanged, \
please use "..." to indicate the ignored lines.
4. Use "+ " and "- " at start of the line to indicate the addition and deletion of lines.
Here are some examples of incorrect responses:
@ -119,14 +128,16 @@ def hello():
print("Call hello():")
+ print("hello")
```
In this case, if the "+ " sign and the extra space are removed, the print("hello") statement will lack the necessary two spaces for correct indentation.
In this case, if the "+ " sign and the extra space are removed, \
the print("hello") statement will lack the necessary two spaces for correct indentation.
Incorrect example 2, where no other code lines are provided:
```edits
+ print("hello")
```
This is an incorrect example because without additional context, it's unclear where the new print("hello") statement should be inserted.
This is an incorrect example because without additional context, \
it's unclear where the new print("hello") statement should be inserted.
"""
SYSTEM_ROLE_CODEBLOCK = """
@ -150,7 +161,14 @@ if __name__ == "__main__":
LLM_MODEL = os.environ.get("LLM_MODEL", "gpt-3.5-turbo-1106")
if LLM_MODEL in ["qwen2-72b-instruct", "qwen-long", "qwen-turbo", "Yi-34B-Chat", "deepseek-coder", "xinghuo-3.5"]:
if LLM_MODEL in [
"qwen2-72b-instruct",
"qwen-long",
"qwen-turbo",
"Yi-34B-Chat",
"deepseek-coder",
"xinghuo-3.5",
]:
SYSTEM_ROLE = SYSTEM_ROLE_CODEBLOCK
else:
SYSTEM_ROLE = SYSTEM_ROLE_DIFF
@ -178,11 +196,14 @@ Here is the rule description:
{rule_description}
Please focus only on the error described in the prompt. Other errors in the code should be disregarded.
Please focus only on the error described in the prompt. \
Other errors in the code should be disregarded.
"""
memory = FixSizeChatMemory(max_size=20, messages=MESSAGES_A)
@chat(prompt=PROMPT, stream_out=True, memory=memory)
def call_llm_to_generate_fix_solutions(
file_content, issue_line_code, issue_description, rule_description
@ -246,7 +267,7 @@ def main():
print("make llm prompt ...\n\n")
current_file_content = get_current_file_content(file_path, issue_line_num)
rule_description = get_rule_description(issue_description)
#print("Rule description:\n\n", rule_description, end="\n\n")
# print("Rule description:\n\n", rule_description, end="\n\n")
print("call llm to fix issue ...\n\n")
fix_solutions = call_llm_to_generate_fix_solutions(

View File

@ -1,10 +1,10 @@
import json
import os
import re
import json
import subprocess
import sys
from devchat.llm import chat, chat_completion_stream
from devchat.llm import chat
from devchat.memory import FixSizeChatMemory
from lib.ide_service import IDEService
@ -28,6 +28,7 @@ def extract_edits_block(text):
else:
return text[start:end]
def extract_markdown_block(text):
"""
Extracts the first Markdown code block from the given text without the language specifier.
@ -80,8 +81,11 @@ def input_issue_descriptions(file_path, issue_line_num):
# step 3 : call llm to generate fix solutions
SYSTEM_ROLE_DIFF= """
You are a code refactoring assistant. Your task is to refactor the user's code to fix lint diagnostics. You will be provided with a code snippet and a list of diagnostics. Your response should include two parts:
SYSTEM_ROLE_DIFF = """
You are a code refactoring assistant. \
Your task is to refactor the user's code to fix lint diagnostics. \
You will be provided with a code snippet and a list of diagnostics. \
Your response should include two parts:
1. An explanation of the reason for the diagnostics and how to fix them.
2. The edited code snippet with the diagnostics fixed, using markdown format for clarity.
@ -107,9 +111,14 @@ Or like this, if a variable is not defined:
```
Please note the following important points:
1. The new code should maintain the correct indentation. The "+ " sign is followed by two spaces for indentation, which should be included in the edited code.
2. In addition to outputting key editing information, sufficient context (i.e., key information before and after editing) should also be provided to help locate the specific position of the edited line.
3. Don't output all file lines, if some lines are unchanged, please use "..." to indicate the ignored lines.
1. The new code should maintain the correct indentation. \
The "+ " sign is followed by two spaces for indentation, \
which should be included in the edited code.
2. In addition to outputting key editing information, \
sufficient context (i.e., key information before and after editing) \
should also be provided to help locate the specific position of the edited line.
3. Don't output all file lines, if some lines are unchanged, \
please use "..." to indicate the ignored lines.
4. Use "+ " and "- " at start of the line to indicate the addition and deletion of lines.
Here are some examples of incorrect responses:
@ -121,14 +130,16 @@ def hello():
print("Call hello():")
+ print("hello")
```
In this case, if the "+ " sign and the extra space are removed, the print("hello") statement will lack the necessary two spaces for correct indentation.
In this case, if the "+ " sign and the extra space are removed, \
the print("hello") statement will lack the necessary two spaces for correct indentation.
Incorrect example 2, where no other code lines are provided:
```edits
+ print("hello")
```
This is an incorrect example because without additional context, it's unclear where the new print("hello") statement should be inserted.
This is an incorrect example because without additional context, \
it's unclear where the new print("hello") statement should be inserted.
"""
SYSTEM_ROLE_CODEBLOCK = """
@ -152,7 +163,14 @@ if __name__ == "__main__":
LLM_MODEL = os.environ.get("LLM_MODEL", "gpt-3.5-turbo-1106")
if LLM_MODEL in ["qwen2-72b-instruct", "qwen-long", "qwen-turbo", "Yi-34B-Chat", "deepseek-coder", "xinghuo-3.5"]:
if LLM_MODEL in [
"qwen2-72b-instruct",
"qwen-long",
"qwen-turbo",
"Yi-34B-Chat",
"deepseek-coder",
"xinghuo-3.5",
]:
SYSTEM_ROLE = SYSTEM_ROLE_CODEBLOCK
else:
SYSTEM_ROLE = SYSTEM_ROLE_DIFF
@ -180,11 +198,14 @@ Here is the rule description:
{rule_description}
Please focus only on the error described in the prompt. Other errors in the code should be disregarded.
Please focus only on the error described in the prompt. \
Other errors in the code should be disregarded.
"""
memory = FixSizeChatMemory(max_size=20, messages=MESSAGES_A)
@chat(prompt=PROMPT, stream_out=True, memory=memory)
def call_llm_to_generate_fix_solutions(
file_content, issue_line_code, issue_description, rule_description
@ -193,7 +214,8 @@ def call_llm_to_generate_fix_solutions(
APPLY_SYSTEM_PROMPT = """
Your task is apply the fix solution to the code, output the whole new code in markdown code block format.
Your task is apply the fix solution to the code, \
output the whole new code in markdown code block format.
Here is the code file:
{file_content}
@ -204,10 +226,14 @@ Here is the fix solution:
Some rules for output code:
1. Focus on the fix solution, don't focus on other errors in the code.
2. Don't change the indentation of the code.
3. Don't change lines which are not metioned in fix solution, for example, don't remove empty lines in code.
3. Don't change lines which are not metioned in fix solution, for example, \
don't remove empty lines in code.
Please output only the whole new code which is the result of applying the fix solution, and output the whole code.
Please output only the whole new code which is the result of \
applying the fix solution, and output the whole code.
"""
@chat(prompt=APPLY_SYSTEM_PROMPT, stream_out=True, model="deepseek-coder")
def apply_fix_solution(file_content, fix_solution):
pass
@ -254,14 +280,16 @@ def get_rule_description(issue_description):
def get_file_content(file_path):
try:
with open(file_path, 'r', encoding='utf-8') as file:
with open(file_path, "r", encoding="utf-8") as file:
return file.read()
except Exception:
print("Error reading file:", file=sys.stderr)
return None
GLOBAL_CONFIG_PATH = os.path.join(os.path.expanduser("~"), ".chat", ".workflow_config.json")
def get_aider_python_path():
"""
Retrieves the path to the Aider Python executable from the global configuration file.
@ -273,9 +301,10 @@ def get_aider_python_path():
if os.path.exists(GLOBAL_CONFIG_PATH):
with open(GLOBAL_CONFIG_PATH, "r", encoding="utf-8") as f:
config = json.load(f)
return config.get('aider_python')
return config.get("aider_python")
return None
def run_aider(message, file_path):
"""
Run the Aider tool to apply changes to a file based on a given message.
@ -294,8 +323,8 @@ def run_aider(message, file_path):
SystemExit: If the Aider process returns a non-zero exit code, indicating an error.
"""
python = get_aider_python_path()
model = os.environ.get('LLM_MODEL', 'gpt-3.5-turbo-1106')
model = os.environ.get("LLM_MODEL", "gpt-3.5-turbo-1106")
cmd = [
python,
"-m",
@ -303,20 +332,15 @@ def run_aider(message, file_path):
"--model",
f"openai/{model}",
"--yes",
"--no-auto-commits",
"--no-auto-commits",
"--dry-run",
"--no-pretty",
"--message",
message,
file_path
file_path,
]
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
has_started = False
aider_output = ""
@ -350,13 +374,13 @@ def apply_changes(changes, file_path):
these changes to the specified file. It handles the execution of aider and manages
the output and potential errors.
"""
changes_file = '.chat/changes.txt'
changes_file = ".chat/changes.txt"
os.makedirs(os.path.dirname(changes_file), exist_ok=True)
with open(changes_file, 'w', encoding='utf-8') as f:
with open(changes_file, "w", encoding="utf-8") as f:
f.write(changes)
python = get_aider_python_path()
model = os.environ.get('LLM_MODEL', 'gpt-3.5-turbo-1106')
model = os.environ.get("LLM_MODEL", "gpt-3.5-turbo-1106")
cmd = [
python,
@ -368,15 +392,10 @@ def apply_changes(changes, file_path):
"--no-auto-commits",
"--apply",
changes_file,
file_path
file_path,
]
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
has_started = False
for line in process.stdout:
@ -418,7 +437,7 @@ def main():
print("make llm prompt ...\n\n", flush=True)
current_file_content = get_current_file_content(file_path, issue_line_num)
rule_description = get_rule_description(issue_description)
#print("Rule description:\n\n", rule_description, end="\n\n")
# print("Rule description:\n\n", rule_description, end="\n\n")
print("call llm to fix issue ...\n\n", flush=True)
@ -444,15 +463,15 @@ Rule description: {rule_description}
print("\nApplying changes...\n", flush=True)
with open(file_path, 'r', encoding='utf-8') as f:
with open(file_path, "r", encoding="utf-8") as f:
original_content = f.read()
apply_changes(changes, file_path)
with open(file_path, 'r', encoding='utf-8') as f:
with open(file_path, "r", encoding="utf-8") as f:
updated_content = f.read()
with open(file_path, 'w', encoding='utf-8') as f:
with open(file_path, "w", encoding="utf-8") as f:
f.write(original_content)
os.environ["PYTHONPATH"] = python_path
@ -474,11 +493,6 @@ Rule description: {rule_description}
print("\n\n", flush=True)
print("apply fix solution ...\n\n")
# updated_content = apply_fix_solution(file_content=get_file_content(file_path), fix_solution=fix_solutions)
# if not updated_content:
# print("No edits code generated.")
# sys.exit(0)
# updated_content = fix_solutions['content']
updated_content = extract_markdown_block(fix_solutions)
if updated_content:
# Display changes in IDE