From a8b6b4ea6343edcd63ca49ef5c7a14c5f97389f5 Mon Sep 17 00:00:00 2001 From: bobo Date: Mon, 1 Jul 2024 21:27:57 +0800 Subject: [PATCH 1/7] feat: Add new IDE service methods - Implement get_diagnostics_in_range for code diagnostics - Add get_collapsed_code method for code collapsing - Introduce get_extension_tools_path for tool path retrieval --- lib/ide_service/service.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/lib/ide_service/service.py b/lib/ide_service/service.py index eb72052..5234824 100644 --- a/lib/ide_service/service.py +++ b/lib/ide_service/service.py @@ -152,3 +152,34 @@ def get_selected_range(self) -> LocationWithText: if self.ide_name() == "vscode": return selected_range() return IdeaIDEService().get_selected_range() + + @rpc_method + def get_diagnostics_in_range(self, fileName: str, startLine: int, endLine: int) -> List[str]: + """ + Retrieves diagnostics for a specific range of code in the current IDE. + + Returns: + A list of diagnostic messages for the specified range. + """ + return self._result + + @rpc_method + def get_collapsed_code(self, fileName: str, startLine: int, endLine: int) -> str: + """ + Retrives collapsed code exclude specfic range of code in the current IDE. + + Returns: + The collapsed code. + """ + return self._result + + @rpc_method + def get_extension_tools_path(self) -> str: + """ + Retrives extension tools path. + + Returns: + The extension tools path. + """ + return self._result + From 9d07b91a3ea4960f6d6721e3837fef581cebf6fa Mon Sep 17 00:00:00 2001 From: bobo Date: Mon, 1 Jul 2024 21:27:57 +0800 Subject: [PATCH 2/7] feat: Add fix_issue command - Implement new command to automatically fix lint errors - Create main.py with functions for issue detection and fixing - Add command.yml and README.md for fix_issue functionality --- merico/fix_issue/README.md | 3 + merico/fix_issue/command.yml | 4 + merico/fix_issue/main.py | 421 +++++++++++++++++++++++++++++++++++ 3 files changed, 428 insertions(+) create mode 100644 merico/fix_issue/README.md create mode 100644 merico/fix_issue/command.yml create mode 100644 merico/fix_issue/main.py diff --git a/merico/fix_issue/README.md b/merico/fix_issue/README.md new file mode 100644 index 0000000..60da6be --- /dev/null +++ b/merico/fix_issue/README.md @@ -0,0 +1,3 @@ + +### 操作指南 + diff --git a/merico/fix_issue/command.yml b/merico/fix_issue/command.yml new file mode 100644 index 0000000..e96e880 --- /dev/null +++ b/merico/fix_issue/command.yml @@ -0,0 +1,4 @@ +description: Automatically fix lint errors. +help: README.md +steps: + - run: $devchat_python $command_path/main.py diff --git a/merico/fix_issue/main.py b/merico/fix_issue/main.py new file mode 100644 index 0000000..1e233b6 --- /dev/null +++ b/merico/fix_issue/main.py @@ -0,0 +1,421 @@ +import os +import re +import sys + +from devchat.llm import chat +from devchat.memory import FixSizeChatMemory + +from lib.ide_service import IDEService + +PROMPT = prompt = """ +file: {file_path} +``` +{selected_text} +``` +""" + +PROMPT_ZH = prompt = """ +文件: {file_path} +``` +{selected_text} +``` + +输出内容使用中文,我的母语为中文。 +""" + + +def get_prompt(): + ide_language = IDEService().ide_language() + return PROMPT_ZH if ide_language == "zh" else PROMPT + + +MESSAGES_A = [ + { + "role": "system", + "content": """ +Your task is: +Write a documentation comment to the selected code. Please pay attention to using \ +standard comment format, such as method comments, please explain parameters and return values. \ +And just add the documents for the selected portion of the code. +Output documentation comment is format as code block.\ + +You must follow the following rules: +1. Output documentation comment in ```comment ``` \ + format. +2. Different languages have different comment symbols, please choose the correct comment symbol \ + according to the file name. +3. You must output ... to indicate the remaining code, output all code block can make more errors. +""", + }, + { + "role": "user", + "content": """ +file: a1.py +``` + def print_hello(): + print("hello") + print("world") +``` +""", + }, + { + "role": "assistant", + "content": """ +```comment + def print_hello(): + \"\"\" + print hello + + Parameters: + None + + Returns: + None + \"\"\" + print("hello") + ... +``` +""", + }, + { + "role": "user", + "content": """ +file: t1.java +``` + public static void main(String[] args) { + System.out.println("Hello, World!"); + } +``` +""", + }, + { + "role": "assistant", + "content": """ +```comment + /** + * The main method is the entry point of the program. + * This method prints "Hello, World!" to the console. + * + * @param args command line arguments (not used in this program) + */ + public static void main(String[] args) { + ... +``` +""", + }, + { + "role": "user", + "content": """ +file: t1.py +``` +def content_to_json(content): + try: + content_no_block = _try_remove_markdown_block_flag(content) + response_obj = json.loads(content_no_block) + return response_obj + except json.JSONDecodeError as err: + raise RetryException(err) from err + except Exception as err: + raise err +``` +""", + }, + { + "role": "assistant", + "content": """ +```comment +def content_to_json(content): + \"\"\" + Convert the given content to a JSON object. + + Parameters: + content (str): The content to convert. + + Returns: + dict: The JSON object. + + Raises: + RetryException: If the content cannot be decoded to JSON. + \"\"\" + try: + ... +``` +""", + }, +] + + + + +memory = FixSizeChatMemory(max_size=20, messages=MESSAGES_A) + + +@chat(prompt=get_prompt(), stream_out=True, memory=memory) +# pylint: disable=unused-argument +def add_docstring(selected_text, file_path): + """ + call ai to rewrite selected code + """ + pass # pylint: disable=unnecessary-pass + + +def extract_markdown_block(text): + """ + Extracts the first Markdown code block from the given text without the language specifier. + + :param text: A string containing Markdown text + :return: The content of the first Markdown code block, or None if not found + """ + pattern = r"```(?:\w+)?\s*\n(.*?)\n```" + match = re.search(pattern, text, re.DOTALL) + + if match: + block_content = match.group(1) + return block_content + else: + # whether exist ```language? + if text.find("```"): + return None + return text + + +def get_indent_level(text): + """ + Returns the indentation level of the given text. + + :param text: A string containing the text to be analyzed + :return: The indentation level of the text, as an integer + """ + indent_level = 0 + for char in text: + if char == " ": + indent_level += 1 + elif char == "\t": + indent_level += 4 + else: + break + return indent_level + + +def offset_indent_level(text, indent_level): + """ + Offsets the indentation level of the given text by the specified amount. + + :param text: A string containing the text to be modified + :param indent_level: The amount by which to offset the indentation level + :return: The modified text with the indentation level offset + """ + current_indent = get_indent_level(text) + offset_indent = indent_level - current_indent + if offset_indent > 0: + lines = text.splitlines() + new_lines = [] + for line in lines: + new_lines.append(" " * offset_indent + line) + text = "\n".join(new_lines) + return text + + +def merge_code(selected_text, docstring): + user_selected_lines = selected_text.split("\n") + docstring_lines = docstring.split("\n") + + user_selected_trim_lines = [line.replace(" ", "").strip() for line in user_selected_lines] + docstring_trim_lines = [line.replace(" ", "").strip() for line in docstring_lines] + + # match user_selected_trim_line == docstring_trim_line + # and index_selected_line != index_docstring_line + has_match = False + for index, line in enumerate(user_selected_trim_lines): + for index_doc, line_doc in enumerate(docstring_trim_lines): + if line_doc == "..." and has_match: + line_doc = line + break + if line == line_doc: + has_match = True + break + if line != line_doc or index == index_doc: + continue + return "\n".join(docstring_lines[:index_doc] + user_selected_lines[index:]) + + # match with part of code + for index, line in enumerate(user_selected_trim_lines): + for index_doc, line_doc in enumerate(docstring_trim_lines): + if line_doc == "...": + break + if ( + line.strip().find(line_doc.strip()) != -1 + or line_doc.strip().find(line.strip()) != -1 + ): + break + if ( + line.strip().find(line_doc.strip()) == -1 and line_doc.strip().find(line.strip()) == -1 + ) or index == index_doc: + continue + return "\n".join(docstring_lines[:index_doc] + user_selected_lines[index:]) + return docstring + "\n" + selected_text + + +def main(): + # Prepare code + selected_text = get_selected_code() + + # Rewrite + response = add_docstring( + selected_text=selected_text.get("text", ""), file_path=selected_text.get("abspath", "") + ) + if not response: + sys.exit(1) + + # Get indent level + indent = get_indent_level(selected_text.get("text", "")) + + # Apply new code to editor + new_code = extract_markdown_block(response) + if not new_code: + language = IDEService().ide_language() + print_message(language) + sys.exit(0) + + # Offset indent level + new_code = offset_indent_level(new_code, indent) + + # Merge code + docstring_code = merge_code(selected_text.get("text", ""), new_code) + # Apply diff + IDEService().diff_apply("", docstring_code) + + sys.exit(0) + + +def print_message(language): + if language == "zh": + print("\n\n大模型输出不完整,不能进行代码操作。\n\n") + else: + print("\n\nThe output of the LLM is incomplete and cannot perform code operations.\n\n") + + +# step 1 : get selected code +def get_selected_code(): + selected_data = IDEService().get_selected_range().dict() + + if selected_data["range"]["start"] == -1: + return None, None, None + + if selected_data["range"]["start"]["line"] != selected_data["range"]["end"]["line"]: + print("Please select the line code of issue reported.\n\n", file=sys.stderr) + sys.exit(1) + + return selected_data['abspath'], selected_data['text'], selected_data["range"]["start"]["line"] + + +# step 2 : input issue descriptions +def input_issue_descriptions(file_path, issue_line_num): + diagnostics = IDEService().get_diagnostics_in_range(file_path, issue_line_num, issue_line_num) + if not diagnostics: + return None + + # select first sonarlint diagnostic + for diagnostic in diagnostics: + if diagnostic.find(" 0: + return diagnostic + return diagnostics[0] + + +# step 3 : call llm to generate fix solutions +PROMPT = """ +You are a code refactoring assistant. +This is my code file: +{file_content} + +There is a issue in the following code: +{issue_line_code} +{issue_description} + +Here is the rule description: +{rule_description} + +Please provide me refactor code to fix this issue. +""" +@chat(prompt=PROMPT, stream_out=True) +def call_llm_to_generate_fix_solutions(file_content, issue_line_code, issue_description, rule_description): + pass + + +# current file content +def get_current_file_content(file_path, issue_line_num): + try: + return IDEService().get_collapsed_code(file_path, issue_line_num, issue_line_num) + except Exception: + print("Error reading file:", file=sys.stderr) + return None + +# get issue description +def get_rule_description(issue_description): + # Remove 1 unexpected arguments; 'hello' expects 0 positional arguments. [+2 locations] + def parse_source_code(text): + pattern = r'<(\w+):(.+?)>' + match = re.search(pattern, text) + + if match: + source = match.group(1) + code = match.group(2) + return source, code + else: + return None, None + + issue_source, issue_code = parse_source_code(issue_description) + if issue_source.find("sonar") == -1: + return issue_description + + issue_id = issue_code.split(':')[-1] + issue_language = issue_code.split(':')[0] + + tools_path = IDEService().get_extension_tools_path() + rules_path = "sonar_respec" + + rule_path = os.path.join(tools_path, rules_path, "rules", issue_id, issue_language, "rule.adoc") + if os.path.exists(rule_path): + with open(rule_path, "r", encoding="utf-8") as file: + return file.read() + return issue_description + + +# step 4 : apply fix solutions to code +def apply_fix_solutions_to_code(): + pass + + +# step 0: try parse user input +def try_parse_user_input(): + pass + + +def main(): + print("start fix issue ...\n\n") + file_path, issue_line, issue_line_num = get_selected_code() + if not file_path or not issue_line: + print('No code selected. Please select the code line you want to fix.', file=sys.stderr) + sys.exit(1) + issue_description = input_issue_descriptions(file_path, issue_line_num) + if not issue_description: + print('There are no issues to resolve on the current line. Please select the line where an issue needs to be resolved.', file=sys.stderr) + sys.exit(1) + + 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) + + print("call llm to fix issue ...\n\n") + fix_solutions = call_llm_to_generate_fix_solutions( + file_content=current_file_content, + issue_line_code=issue_line, + issue_description=issue_description, + rule_description=rule_description) + if not fix_solutions: + sys.exit(1) + + +if __name__ == "__main__": + main() From 89d19679f5f9c9c2a1aa09dd0d3e24ff168cd484 Mon Sep 17 00:00:00 2001 From: bobo Date: Mon, 1 Jul 2024 21:27:58 +0800 Subject: [PATCH 3/7] fix: Handle error cases and exit with non-zero status --- merico/fix_issue/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/merico/fix_issue/main.py b/merico/fix_issue/main.py index 1e233b6..834a9cc 100644 --- a/merico/fix_issue/main.py +++ b/merico/fix_issue/main.py @@ -399,8 +399,8 @@ def main(): sys.exit(1) issue_description = input_issue_descriptions(file_path, issue_line_num) if not issue_description: - print('There are no issues to resolve on the current line. Please select the line where an issue needs to be resolved.', file=sys.stderr) - sys.exit(1) + print('There are no issues to resolve on the current line. Please select the line where an issue needs to be resolved.') + sys.exit(0) print("make llm prompt ...\n\n") current_file_content = get_current_file_content(file_path, issue_line_num) From d8d1c34406ad84ea6853cc4e38ae2d4f93efacac Mon Sep 17 00:00:00 2001 From: bobo Date: Mon, 1 Jul 2024 21:27:58 +0800 Subject: [PATCH 4/7] fix: Update rules_path to "sonar-rspec" for consistency --- merico/fix_issue/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/merico/fix_issue/main.py b/merico/fix_issue/main.py index 834a9cc..f2b2a83 100644 --- a/merico/fix_issue/main.py +++ b/merico/fix_issue/main.py @@ -372,7 +372,7 @@ def parse_source_code(text): issue_language = issue_code.split(':')[0] tools_path = IDEService().get_extension_tools_path() - rules_path = "sonar_respec" + rules_path = "sonar-rspec" rule_path = os.path.join(tools_path, rules_path, "rules", issue_id, issue_language, "rule.adoc") if os.path.exists(rule_path): From 8a15ea83f223a17921a206d7c54540acb22c88f0 Mon Sep 17 00:00:00 2001 From: bobo Date: Mon, 1 Jul 2024 21:37:29 +0800 Subject: [PATCH 5/7] fix lint error --- lib/ide_service/service.py | 7 +- merico/fix_issue/main.py | 275 +------------------------------------ 2 files changed, 6 insertions(+), 276 deletions(-) diff --git a/lib/ide_service/service.py b/lib/ide_service/service.py index 5234824..ee054a2 100644 --- a/lib/ide_service/service.py +++ b/lib/ide_service/service.py @@ -152,12 +152,12 @@ def get_selected_range(self) -> LocationWithText: if self.ide_name() == "vscode": return selected_range() return IdeaIDEService().get_selected_range() - + @rpc_method def get_diagnostics_in_range(self, fileName: str, startLine: int, endLine: int) -> List[str]: """ Retrieves diagnostics for a specific range of code in the current IDE. - + Returns: A list of diagnostic messages for the specified range. """ @@ -172,7 +172,7 @@ def get_collapsed_code(self, fileName: str, startLine: int, endLine: int) -> str The collapsed code. """ return self._result - + @rpc_method def get_extension_tools_path(self) -> str: """ @@ -182,4 +182,3 @@ def get_extension_tools_path(self) -> str: The extension tools path. """ return self._result - diff --git a/merico/fix_issue/main.py b/merico/fix_issue/main.py index f2b2a83..0713673 100644 --- a/merico/fix_issue/main.py +++ b/merico/fix_issue/main.py @@ -3,161 +3,9 @@ import sys from devchat.llm import chat -from devchat.memory import FixSizeChatMemory from lib.ide_service import IDEService -PROMPT = prompt = """ -file: {file_path} -``` -{selected_text} -``` -""" - -PROMPT_ZH = prompt = """ -文件: {file_path} -``` -{selected_text} -``` - -输出内容使用中文,我的母语为中文。 -""" - - -def get_prompt(): - ide_language = IDEService().ide_language() - return PROMPT_ZH if ide_language == "zh" else PROMPT - - -MESSAGES_A = [ - { - "role": "system", - "content": """ -Your task is: -Write a documentation comment to the selected code. Please pay attention to using \ -standard comment format, such as method comments, please explain parameters and return values. \ -And just add the documents for the selected portion of the code. -Output documentation comment is format as code block.\ - -You must follow the following rules: -1. Output documentation comment in ```comment ``` \ - format. -2. Different languages have different comment symbols, please choose the correct comment symbol \ - according to the file name. -3. You must output ... to indicate the remaining code, output all code block can make more errors. -""", - }, - { - "role": "user", - "content": """ -file: a1.py -``` - def print_hello(): - print("hello") - print("world") -``` -""", - }, - { - "role": "assistant", - "content": """ -```comment - def print_hello(): - \"\"\" - print hello - - Parameters: - None - - Returns: - None - \"\"\" - print("hello") - ... -``` -""", - }, - { - "role": "user", - "content": """ -file: t1.java -``` - public static void main(String[] args) { - System.out.println("Hello, World!"); - } -``` -""", - }, - { - "role": "assistant", - "content": """ -```comment - /** - * The main method is the entry point of the program. - * This method prints "Hello, World!" to the console. - * - * @param args command line arguments (not used in this program) - */ - public static void main(String[] args) { - ... -``` -""", - }, - { - "role": "user", - "content": """ -file: t1.py -``` -def content_to_json(content): - try: - content_no_block = _try_remove_markdown_block_flag(content) - response_obj = json.loads(content_no_block) - return response_obj - except json.JSONDecodeError as err: - raise RetryException(err) from err - except Exception as err: - raise err -``` -""", - }, - { - "role": "assistant", - "content": """ -```comment -def content_to_json(content): - \"\"\" - Convert the given content to a JSON object. - - Parameters: - content (str): The content to convert. - - Returns: - dict: The JSON object. - - Raises: - RetryException: If the content cannot be decoded to JSON. - \"\"\" - try: - ... -``` -""", - }, -] - - - - -memory = FixSizeChatMemory(max_size=20, messages=MESSAGES_A) - - -@chat(prompt=get_prompt(), stream_out=True, memory=memory) -# pylint: disable=unused-argument -def add_docstring(selected_text, file_path): - """ - call ai to rewrite selected code - """ - pass # pylint: disable=unnecessary-pass - def extract_markdown_block(text): """ @@ -178,123 +26,6 @@ def extract_markdown_block(text): return None return text - -def get_indent_level(text): - """ - Returns the indentation level of the given text. - - :param text: A string containing the text to be analyzed - :return: The indentation level of the text, as an integer - """ - indent_level = 0 - for char in text: - if char == " ": - indent_level += 1 - elif char == "\t": - indent_level += 4 - else: - break - return indent_level - - -def offset_indent_level(text, indent_level): - """ - Offsets the indentation level of the given text by the specified amount. - - :param text: A string containing the text to be modified - :param indent_level: The amount by which to offset the indentation level - :return: The modified text with the indentation level offset - """ - current_indent = get_indent_level(text) - offset_indent = indent_level - current_indent - if offset_indent > 0: - lines = text.splitlines() - new_lines = [] - for line in lines: - new_lines.append(" " * offset_indent + line) - text = "\n".join(new_lines) - return text - - -def merge_code(selected_text, docstring): - user_selected_lines = selected_text.split("\n") - docstring_lines = docstring.split("\n") - - user_selected_trim_lines = [line.replace(" ", "").strip() for line in user_selected_lines] - docstring_trim_lines = [line.replace(" ", "").strip() for line in docstring_lines] - - # match user_selected_trim_line == docstring_trim_line - # and index_selected_line != index_docstring_line - has_match = False - for index, line in enumerate(user_selected_trim_lines): - for index_doc, line_doc in enumerate(docstring_trim_lines): - if line_doc == "..." and has_match: - line_doc = line - break - if line == line_doc: - has_match = True - break - if line != line_doc or index == index_doc: - continue - return "\n".join(docstring_lines[:index_doc] + user_selected_lines[index:]) - - # match with part of code - for index, line in enumerate(user_selected_trim_lines): - for index_doc, line_doc in enumerate(docstring_trim_lines): - if line_doc == "...": - break - if ( - line.strip().find(line_doc.strip()) != -1 - or line_doc.strip().find(line.strip()) != -1 - ): - break - if ( - line.strip().find(line_doc.strip()) == -1 and line_doc.strip().find(line.strip()) == -1 - ) or index == index_doc: - continue - return "\n".join(docstring_lines[:index_doc] + user_selected_lines[index:]) - return docstring + "\n" + selected_text - - -def main(): - # Prepare code - selected_text = get_selected_code() - - # Rewrite - response = add_docstring( - selected_text=selected_text.get("text", ""), file_path=selected_text.get("abspath", "") - ) - if not response: - sys.exit(1) - - # Get indent level - indent = get_indent_level(selected_text.get("text", "")) - - # Apply new code to editor - new_code = extract_markdown_block(response) - if not new_code: - language = IDEService().ide_language() - print_message(language) - sys.exit(0) - - # Offset indent level - new_code = offset_indent_level(new_code, indent) - - # Merge code - docstring_code = merge_code(selected_text.get("text", ""), new_code) - # Apply diff - IDEService().diff_apply("", docstring_code) - - sys.exit(0) - - -def print_message(language): - if language == "zh": - print("\n\n大模型输出不完整,不能进行代码操作。\n\n") - else: - print("\n\nThe output of the LLM is incomplete and cannot perform code operations.\n\n") - - # step 1 : get selected code def get_selected_code(): selected_data = IDEService().get_selected_range().dict() @@ -352,7 +83,6 @@ def get_current_file_content(file_path, issue_line_num): # get issue description def get_rule_description(issue_description): - # Remove 1 unexpected arguments; 'hello' expects 0 positional arguments. [+2 locations] def parse_source_code(text): pattern = r'<(\w+):(.+?)>' match = re.search(pattern, text) @@ -399,9 +129,10 @@ def main(): sys.exit(1) issue_description = input_issue_descriptions(file_path, issue_line_num) if not issue_description: - print('There are no issues to resolve on the current line. Please select the line where an issue needs to be resolved.') + print('There are no issues to resolve on the current line. ' + 'Please select the line where an issue needs to be resolved.') sys.exit(0) - + 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) From ecdee052aa10876b993db2bea28cbc96f66268d4 Mon Sep 17 00:00:00 2001 From: bobo Date: Mon, 1 Jul 2024 21:39:44 +0800 Subject: [PATCH 6/7] fix lint error --- merico/fix_issue/main.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/merico/fix_issue/main.py b/merico/fix_issue/main.py index 0713673..88c33d6 100644 --- a/merico/fix_issue/main.py +++ b/merico/fix_issue/main.py @@ -69,7 +69,11 @@ def input_issue_descriptions(file_path, issue_line_num): Please provide me refactor code to fix this issue. """ @chat(prompt=PROMPT, stream_out=True) -def call_llm_to_generate_fix_solutions(file_content, issue_line_code, issue_description, rule_description): +def call_llm_to_generate_fix_solutions( + file_content, + issue_line_code, + issue_description, + rule_description): pass From 8830931562e6b1cc5371af0826c332b69edb7f6a Mon Sep 17 00:00:00 2001 From: bobo Date: Mon, 1 Jul 2024 21:42:18 +0800 Subject: [PATCH 7/7] feat: Refactor fix_issue command to improve code readability and maintainability --- merico/fix_issue/main.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/merico/fix_issue/main.py b/merico/fix_issue/main.py index 88c33d6..7afe2b9 100644 --- a/merico/fix_issue/main.py +++ b/merico/fix_issue/main.py @@ -26,6 +26,7 @@ def extract_markdown_block(text): return None return text + # step 1 : get selected code def get_selected_code(): selected_data = IDEService().get_selected_range().dict() @@ -37,7 +38,7 @@ def get_selected_code(): print("Please select the line code of issue reported.\n\n", file=sys.stderr) sys.exit(1) - return selected_data['abspath'], selected_data['text'], selected_data["range"]["start"]["line"] + return selected_data["abspath"], selected_data["text"], selected_data["range"]["start"]["line"] # step 2 : input issue descriptions @@ -68,12 +69,12 @@ def input_issue_descriptions(file_path, issue_line_num): Please provide me refactor code to fix this issue. """ + + @chat(prompt=PROMPT, stream_out=True) def call_llm_to_generate_fix_solutions( - file_content, - issue_line_code, - issue_description, - rule_description): + file_content, issue_line_code, issue_description, rule_description +): pass @@ -85,10 +86,11 @@ def get_current_file_content(file_path, issue_line_num): print("Error reading file:", file=sys.stderr) return None + # get issue description def get_rule_description(issue_description): def parse_source_code(text): - pattern = r'<(\w+):(.+?)>' + pattern = r"<(\w+):(.+?)>" match = re.search(pattern, text) if match: @@ -102,8 +104,8 @@ def parse_source_code(text): if issue_source.find("sonar") == -1: return issue_description - issue_id = issue_code.split(':')[-1] - issue_language = issue_code.split(':')[0] + issue_id = issue_code.split(":")[-1] + issue_language = issue_code.split(":")[0] tools_path = IDEService().get_extension_tools_path() rules_path = "sonar-rspec" @@ -129,12 +131,14 @@ def main(): print("start fix issue ...\n\n") file_path, issue_line, issue_line_num = get_selected_code() if not file_path or not issue_line: - print('No code selected. Please select the code line you want to fix.', file=sys.stderr) + print("No code selected. Please select the code line you want to fix.", file=sys.stderr) sys.exit(1) issue_description = input_issue_descriptions(file_path, issue_line_num) if not issue_description: - print('There are no issues to resolve on the current line. ' - 'Please select the line where an issue needs to be resolved.') + print( + "There are no issues to resolve on the current line. " + "Please select the line where an issue needs to be resolved." + ) sys.exit(0) print("make llm prompt ...\n\n") @@ -147,7 +151,8 @@ def main(): file_content=current_file_content, issue_line_code=issue_line, issue_description=issue_description, - rule_description=rule_description) + rule_description=rule_description, + ) if not fix_solutions: sys.exit(1)