2023-07-15 09:30:50 +03:00
import copy
import textwrap
2023-12-17 16:52:03 +02:00
from functools import partial
2023-10-16 14:56:00 +03:00
from typing import Dict , List
2023-07-15 09:30:50 +03:00
from jinja2 import Environment , StrictUndefined
2023-12-12 23:03:38 +08:00
from pr_agent . algo . ai_handlers . base_ai_handler import BaseAiHandler
2023-12-14 09:00:14 +02:00
from pr_agent . algo . ai_handlers . litellm_ai_handler import LiteLLMAIHandler
2023-10-16 14:56:00 +03:00
from pr_agent . algo . pr_processing import get_pr_diff , get_pr_multi_diffs , retry_with_fallback_models
2023-07-15 09:30:50 +03:00
from pr_agent . algo . token_handler import TokenHandler
2023-08-28 09:48:43 +03:00
from pr_agent . algo . utils import load_yaml
2023-08-01 14:43:26 +03:00
from pr_agent . config_loader import get_settings
2023-10-16 14:56:00 +03:00
from pr_agent . git_providers import get_git_provider
2023-07-15 09:30:50 +03:00
from pr_agent . git_providers . git_provider import get_main_pr_language
2023-10-16 14:56:00 +03:00
from pr_agent . log import get_logger
2024-01-15 15:10:54 +02:00
from pr_agent . tools . pr_description import insert_br_after_x_chars
2023-07-15 09:30:50 +03:00
class PRCodeSuggestions :
2023-12-14 09:00:14 +02:00
def __init__ ( self , pr_url : str , cli_mode = False , args : list = None ,
2023-12-17 16:52:03 +02:00
ai_handler : partial [ BaseAiHandler , ] = LiteLLMAIHandler ) :
2023-07-15 09:30:50 +03:00
self . git_provider = get_git_provider ( ) ( pr_url )
self . main_language = get_main_pr_language (
self . git_provider . get_languages ( ) , self . git_provider . get_files ( )
)
2023-07-30 11:43:44 +03:00
2023-08-22 09:42:59 +03:00
# extended mode
2023-09-25 18:56:10 +03:00
try :
2024-01-03 14:21:38 +02:00
self . is_extended = self . _get_is_extended ( args or [ ] )
2023-09-25 18:56:10 +03:00
except :
self . is_extended = False
2023-08-22 09:42:59 +03:00
if self . is_extended :
num_code_suggestions = get_settings ( ) . pr_code_suggestions . num_code_suggestions_per_chunk
else :
num_code_suggestions = get_settings ( ) . pr_code_suggestions . num_code_suggestions
2023-12-17 16:52:03 +02:00
self . ai_handler = ai_handler ( )
2023-07-15 09:30:50 +03:00
self . patches_diff = None
self . prediction = None
self . cli_mode = cli_mode
self . vars = {
" title " : self . git_provider . pr . title ,
" branch " : self . git_provider . get_pr_branch ( ) ,
" description " : self . git_provider . get_pr_description ( ) ,
" language " : self . main_language ,
" diff " : " " , # empty diff for initial calculation
2023-08-22 09:42:59 +03:00
" num_code_suggestions " : num_code_suggestions ,
2024-01-09 22:09:48 +02:00
" summarize_mode " : get_settings ( ) . pr_code_suggestions . summarize ,
2023-08-01 14:43:26 +03:00
" extra_instructions " : get_settings ( ) . pr_code_suggestions . extra_instructions ,
2023-08-02 18:26:39 +03:00
" commit_messages_str " : self . git_provider . get_commit_messages ( ) ,
2023-07-15 09:30:50 +03:00
}
self . token_handler = TokenHandler ( self . git_provider . pr ,
self . vars ,
2023-08-01 14:43:26 +03:00
get_settings ( ) . pr_code_suggestions_prompt . system ,
get_settings ( ) . pr_code_suggestions_prompt . user )
2023-07-15 09:30:50 +03:00
2023-08-01 14:43:26 +03:00
async def run ( self ) :
2024-01-15 15:10:54 +02:00
data = { ' code_suggestions ' : [ { ' relevant_file ' : ' pr_agent/tools/pr_update_changelog.py ' , ' suggestion_content ' : ' The `get_git_provider()` function is called twice in the `__init__` method of `PRUpdateChangelog` class. It would be more efficient to call this function once and store the result in a variable, then use this variable in the conditional statements. \n ' , ' existing_code ' : ' if isinstance(self.git_provider, GithubProvider): \n self.git_provider = get_git_provider()(pr_url) \n elif isinstance(self.git_provider, GitLabProvider): \n self.git_provider = get_git_provider()(pr_url, incremental=True) \n ' , ' improved_code ' : ' git_provider = get_git_provider() \n if isinstance(self.git_provider, GithubProvider): \n self.git_provider = git_provider(pr_url) \n elif isinstance(self.git_provider, GitLabProvider): \n self.git_provider = git_provider(pr_url, incremental=True) \n ' , ' relevant_lines_start ' : 22 , ' relevant_lines_end ' : 25 , ' label ' : ' performance ' } , { ' relevant_file ' : ' pr_agent/tools/pr_update_changelog.py ' , ' suggestion_content ' : ' The `run` method of `PRUpdateChangelog` class has duplicate code for `GithubProvider` and `GitLabProvider`. This can be refactored to a separate method that accepts a `git_provider` as an argument, reducing code duplication. \n ' , ' existing_code ' : ' if isinstance(self.git_provider, GithubProvider): \n if get_settings().config.publish_output: \n self.git_provider.publish_comment( " Preparing changelog updates... " , is_temporary=True) \n elif isinstance(self.git_provider, GitLabProvider): \n # Add code for preparing changelog updates for GitLabProvider \n pass \n ' , ' improved_code ' : ' def prepare_changelog_updates(self, git_provider): \n if get_settings().config.publish_output: \n git_provider.publish_comment( " Preparing changelog updates... " , is_temporary=True) \n \n if isinstance(self.git_provider, GithubProvider): \n self.prepare_changelog_updates(self.git_provider) \n elif isinstance(self.git_provider, GitLabProvider): \n # Add code for preparing changelog updates for GitLabProvider \n pass \n ' , ' relevant_lines_start ' : 55 , ' relevant_lines_end ' : 60 , ' label ' : ' maintainability ' } , { ' relevant_file ' : ' pr_agent/tools/pr_update_changelog.py ' , ' suggestion_content ' : ' The `assert` statement in the `run` method of `PRUpdateChangelog` class can be replaced with a more descriptive exception. This would provide a more meaningful error message if the condition is not met. \n ' , ' existing_code ' : ' assert type(self.git_provider) in [GithubProvider, GitLabProvider], " Currently only Github and GitLab are supported " \n ' , ' improved_code ' : ' if type(self.git_provider) not in [GithubProvider, GitLabProvider]: \n raise ValueError( " Unsupported git provider. Currently only Github and GitLab are supported. " ) \n ' , ' relevant_lines_start ' : 52 , ' relevant_lines_end ' : 52 , ' label ' : ' enhancement ' } , { ' relevant_file ' : ' pr_agent/tools/pr_update_changelog.py ' , ' suggestion_content ' : ' The `CHANGELOG_LINES` constant is defined at the global scope but is only used within the `PRUpdateChangelog` class. It would be more appropriate to define it as a class attribute. \n ' , ' existing_code ' : ' CHANGELOG_LINES = 25 \n ' , ' improved_code ' : ' class PRUpdateChangelog: \n CHANGELOG_LINES = 25 \n ... \n ' , ' relevant_lines_start ' : 16 , ' relevant_lines_end ' : 16 , ' label ' : ' best practice ' } , { ' relevant_file ' : ' .github/ISSUE_TEMPLATE/sweep-bugfix.yml ' , ' suggestion_content ' : ' The `id` attribute for the second textarea is `description2`, which is not very descriptive. Consider using a more meaningful `id`. \n ' , ' existing_code ' : ' id: description2 \n ' , ' improved_code ' : ' id: additional_details \n ' , ' relevant_lines_start ' : 13 , ' relevant_lines_end ' : 13 , ' label ' : ' enhancement ' } , { ' relevant_file ' : ' .github/ISSUE_TEMPLATE/sweep-feature.yml ' , ' suggestion_content ' : ' The `description` attribute for the textarea is " More details for Sweep " , which is not very descriptive. Consider providing a more specific description. \n ' , ' existing_code ' : ' description: More details for Sweep \n ' , ' improved_code ' : ' description: Please provide more details about the feature you want to
self . publish_summarizes_suggestions ( data )
# try:
# get_logger().info('Generating code suggestions for PR...')
# if get_settings().config.publish_output:
# self.git_provider.publish_comment("Preparing suggestions...", is_temporary=True)
#
# get_logger().info('Preparing PR code suggestions...')
# if not self.is_extended:
# await retry_with_fallback_models(self._prepare_prediction)
# data = self._prepare_pr_code_suggestions()
# else:
# data = await retry_with_fallback_models(self._prepare_prediction_extended)
# if (not data) or (not 'code_suggestions' in data):
# get_logger().info('No code suggestions found for PR.')
# return
#
# if (not self.is_extended and get_settings().pr_code_suggestions.rank_suggestions) or \
# (self.is_extended and get_settings().pr_code_suggestions.rank_extended_suggestions):
# get_logger().info('Ranking Suggestions...')
# data['code_suggestions'] = await self.rank_suggestions(data['code_suggestions'])
#
# if get_settings().config.publish_output:
# get_logger().info('Pushing PR code suggestions...')
# self.git_provider.remove_initial_comment()
# if get_settings().pr_code_suggestions.summarize:
# get_logger().info('Pushing summarize code suggestions...')
# self.publish_summarizes_suggestions(data)
# else:
# get_logger().info('Pushing inline code suggestions...')
# self.push_inline_code_suggestions(data)
# except Exception as e:
# get_logger().error(f"Failed to generate code suggestions for PR, error: {e}")
2023-07-15 09:30:50 +03:00
2023-07-23 16:16:36 +03:00
async def _prepare_prediction ( self , model : str ) :
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( ' Getting PR diff... ' )
2023-07-23 16:16:36 +03:00
self . patches_diff = get_pr_diff ( self . git_provider ,
self . token_handler ,
model ,
add_line_numbers_to_hunks = True ,
disable_extra_lines = True )
2023-08-03 21:38:18 +03:00
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( ' Getting AI prediction... ' )
2023-07-23 16:16:36 +03:00
self . prediction = await self . _get_prediction ( model )
async def _get_prediction ( self , model : str ) :
2023-07-15 09:30:50 +03:00
variables = copy . deepcopy ( self . vars )
variables [ " diff " ] = self . patches_diff # update diff
environment = Environment ( undefined = StrictUndefined )
2023-08-01 14:43:26 +03:00
system_prompt = environment . from_string ( get_settings ( ) . pr_code_suggestions_prompt . system ) . render ( variables )
user_prompt = environment . from_string ( get_settings ( ) . pr_code_suggestions_prompt . user ) . render ( variables )
if get_settings ( ) . config . verbosity_level > = 2 :
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( f " \n System prompt: \n { system_prompt } " )
get_logger ( ) . info ( f " \n User prompt: \n { user_prompt } " )
2023-07-15 09:30:50 +03:00
response , finish_reason = await self . ai_handler . chat_completion ( model = model , temperature = 0.2 ,
system = system_prompt , user = user_prompt )
2023-12-18 17:35:04 +02:00
if get_settings ( ) . config . verbosity_level > = 2 :
get_logger ( ) . info ( f " \n AI response: \n { response } " )
2023-07-15 09:30:50 +03:00
return response
2023-08-28 09:48:43 +03:00
def _prepare_pr_code_suggestions ( self ) - > Dict :
2023-07-15 09:30:50 +03:00
review = self . prediction . strip ( )
2023-12-24 09:44:08 +02:00
data = load_yaml ( review ,
keys_fix_yaml = [ " relevant_file " , " suggestion_content " , " existing_code " , " improved_code " ] )
2023-08-28 09:48:43 +03:00
if isinstance ( data , list ) :
2023-12-24 08:30:35 +02:00
data = { ' code_suggestions ' : data }
# remove invalid suggestions
suggestion_list = [ ]
for i , suggestion in enumerate ( data [ ' code_suggestions ' ] ) :
if suggestion [ ' existing_code ' ] != suggestion [ ' improved_code ' ] :
suggestion_list . append ( suggestion )
else :
2023-12-24 09:44:08 +02:00
get_logger ( ) . debug (
f " Skipping suggestion { i + 1 } , because existing code is equal to improved code { suggestion [ ' existing_code ' ] } " )
2023-12-24 08:30:35 +02:00
data [ ' code_suggestions ' ] = suggestion_list
2023-07-15 09:30:50 +03:00
return data
def push_inline_code_suggestions ( self , data ) :
2023-07-19 20:57:14 +03:00
code_suggestions = [ ]
2023-08-14 13:07:00 -04:00
2023-12-24 08:30:35 +02:00
if not data [ ' code_suggestions ' ] :
2023-11-28 18:29:35 +02:00
get_logger ( ) . info ( ' No suggestions found to improve this PR. ' )
2023-08-15 08:35:57 -04:00
return self . git_provider . publish_comment ( ' No suggestions found to improve this PR. ' )
2023-08-14 13:07:00 -04:00
2023-12-24 08:30:35 +02:00
for d in data [ ' code_suggestions ' ] :
2023-07-28 10:52:49 +03:00
try :
2023-08-01 14:43:26 +03:00
if get_settings ( ) . config . verbosity_level > = 2 :
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( f " suggestion: { d } " )
2023-12-24 08:30:35 +02:00
relevant_file = d [ ' relevant_file ' ] . strip ( )
relevant_lines_start = int ( d [ ' relevant_lines_start ' ] ) # absolute position
relevant_lines_end = int ( d [ ' relevant_lines_end ' ] )
content = d [ ' suggestion_content ' ] . rstrip ( )
new_code_snippet = d [ ' improved_code ' ] . rstrip ( )
2023-12-24 09:44:08 +02:00
label = d [ ' label ' ] . strip ( )
2023-07-28 10:52:49 +03:00
if new_code_snippet :
new_code_snippet = self . dedent_code ( relevant_file , relevant_lines_start , new_code_snippet )
2023-12-24 09:44:08 +02:00
if get_settings ( ) . pr_code_suggestions . include_improved_code :
body = f " **Suggestion:** { content } [ { label } ] \n ```suggestion \n " + new_code_snippet + " \n ``` "
code_suggestions . append ( { ' body ' : body , ' relevant_file ' : relevant_file ,
' relevant_lines_start ' : relevant_lines_start ,
' relevant_lines_end ' : relevant_lines_end } )
else :
if self . git_provider . is_supported ( " create_inline_comment " ) :
body = f " **Suggestion:** { content } [ { label } ] "
comment = self . git_provider . create_inline_comment ( body , relevant_file , " " ,
absolute_position = relevant_lines_end )
if comment :
code_suggestions . append ( comment )
else :
get_logger ( ) . error ( " Inline comments are not supported by the git provider " )
2023-08-01 14:43:26 +03:00
except Exception :
if get_settings ( ) . config . verbosity_level > = 2 :
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( f " Could not parse suggestion: { d } " )
2023-07-19 20:57:14 +03:00
2023-12-24 09:44:08 +02:00
if get_settings ( ) . pr_code_suggestions . include_improved_code :
is_successful = self . git_provider . publish_code_suggestions ( code_suggestions )
else :
is_successful = self . git_provider . publish_inline_comments ( code_suggestions )
2023-08-22 16:11:51 +03:00
if not is_successful :
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( " Failed to publish code suggestions, trying to publish each suggestion separately " )
2023-08-22 16:11:51 +03:00
for code_suggestion in code_suggestions :
2023-12-24 09:44:08 +02:00
if get_settings ( ) . pr_code_suggestions . include_improved_code :
self . git_provider . publish_code_suggestions ( [ code_suggestion ] )
else :
self . git_provider . publish_inline_comments ( [ code_suggestion ] )
2023-07-19 20:57:14 +03:00
def dedent_code ( self , relevant_file , relevant_lines_start , new_code_snippet ) :
try : # dedent code snippet
self . diff_files = self . git_provider . diff_files if self . git_provider . diff_files \
else self . git_provider . get_diff_files ( )
original_initial_line = None
for file in self . diff_files :
if file . filename . strip ( ) == relevant_file :
original_initial_line = file . head_file . splitlines ( ) [ relevant_lines_start - 1 ]
break
if original_initial_line :
suggested_initial_line = new_code_snippet . splitlines ( ) [ 0 ]
original_initial_spaces = len ( original_initial_line ) - len ( original_initial_line . lstrip ( ) )
suggested_initial_spaces = len ( suggested_initial_line ) - len ( suggested_initial_line . lstrip ( ) )
delta_spaces = original_initial_spaces - suggested_initial_spaces
if delta_spaces > 0 :
new_code_snippet = textwrap . indent ( new_code_snippet , delta_spaces * " " ) . rstrip ( ' \n ' )
except Exception as e :
2023-08-01 14:43:26 +03:00
if get_settings ( ) . config . verbosity_level > = 2 :
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( f " Could not dedent code snippet for file { relevant_file } , error: { e } " )
2023-07-19 20:57:14 +03:00
return new_code_snippet
2023-07-30 11:43:44 +03:00
2024-01-03 14:21:38 +02:00
def _get_is_extended ( self , args : list [ str ] ) - > bool :
2024-01-04 18:53:45 +02:00
""" Check if extended mode should be enabled by the `--extended` flag or automatically according to the configuration """
2024-01-03 14:21:38 +02:00
if any ( [ " extended " in arg for arg in args ] ) :
get_logger ( ) . info ( " Extended mode is enabled by the `--extended` flag " )
return True
2024-01-04 18:53:45 +02:00
if get_settings ( ) . pr_code_suggestions . auto_extended_mode :
get_logger ( ) . info ( " Extended mode is enabled automatically based on the configuration toggle " )
2024-01-03 14:21:38 +02:00
return True
return False
2023-08-22 09:42:59 +03:00
async def _prepare_prediction_extended ( self , model : str ) - > dict :
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( ' Getting PR diff... ' )
2023-08-22 09:42:59 +03:00
patches_diff_list = get_pr_multi_diffs ( self . git_provider , self . token_handler , model ,
max_calls = get_settings ( ) . pr_code_suggestions . max_number_of_calls )
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( ' Getting multi AI predictions... ' )
2023-08-22 09:42:59 +03:00
prediction_list = [ ]
for i , patches_diff in enumerate ( patches_diff_list ) :
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( f " Processing chunk { i + 1 } of { len ( patches_diff_list ) } " )
2023-08-22 09:42:59 +03:00
self . patches_diff = patches_diff
prediction = await self . _get_prediction ( model )
prediction_list . append ( prediction )
self . prediction_list = prediction_list
data = { }
for prediction in prediction_list :
self . prediction = prediction
data_per_chunk = self . _prepare_pr_code_suggestions ( )
2023-12-24 08:30:35 +02:00
if " code_suggestions " in data :
data [ " code_suggestions " ] . extend ( data_per_chunk [ " code_suggestions " ] )
2023-08-22 09:42:59 +03:00
else :
data . update ( data_per_chunk )
self . data = data
return data
async def rank_suggestions ( self , data : List ) - > List :
"""
Call a model to rank ( sort ) code suggestions based on their importance order .
Args :
data ( List ) : A list of code suggestions to be ranked .
Returns :
List : The ranked list of code suggestions .
"""
suggestion_list = [ ]
2023-12-24 10:08:36 +02:00
for suggestion in data :
suggestion_list . append ( suggestion )
2023-08-22 09:42:59 +03:00
data_sorted = [ [ ] ] * len ( suggestion_list )
try :
suggestion_str = " "
for i , suggestion in enumerate ( suggestion_list ) :
suggestion_str + = f " suggestion { i + 1 } : " + str ( suggestion ) + ' \n \n '
variables = { ' suggestion_list ' : suggestion_list , ' suggestion_str ' : suggestion_str }
model = get_settings ( ) . config . model
environment = Environment ( undefined = StrictUndefined )
system_prompt = environment . from_string ( get_settings ( ) . pr_sort_code_suggestions_prompt . system ) . render (
variables )
user_prompt = environment . from_string ( get_settings ( ) . pr_sort_code_suggestions_prompt . user ) . render ( variables )
if get_settings ( ) . config . verbosity_level > = 2 :
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( f " \n System prompt: \n { system_prompt } " )
get_logger ( ) . info ( f " \n User prompt: \n { user_prompt } " )
2023-08-22 09:42:59 +03:00
response , finish_reason = await self . ai_handler . chat_completion ( model = model , system = system_prompt ,
user = user_prompt )
2023-08-28 09:48:43 +03:00
sort_order = load_yaml ( response )
2023-08-22 09:42:59 +03:00
for s in sort_order [ ' Sort Order ' ] :
suggestion_number = s [ ' suggestion number ' ]
importance_order = s [ ' importance order ' ]
data_sorted [ importance_order - 1 ] = suggestion_list [ suggestion_number - 1 ]
2023-08-22 16:11:51 +03:00
if get_settings ( ) . pr_code_suggestions . final_clip_factor != 1 :
2024-01-03 16:26:32 +02:00
max_len = max (
len ( data_sorted ) ,
get_settings ( ) . pr_code_suggestions . num_code_suggestions ,
get_settings ( ) . pr_code_suggestions . num_code_suggestions_per_chunk ,
)
new_len = int ( 0.5 + max_len * get_settings ( ) . pr_code_suggestions . final_clip_factor )
if new_len < len ( data_sorted ) :
data_sorted = data_sorted [ : new_len ]
2023-08-22 09:42:59 +03:00
except Exception as e :
if get_settings ( ) . config . verbosity_level > = 1 :
2023-10-16 14:56:00 +03:00
get_logger ( ) . info ( f " Could not sort suggestions, error: { e } " )
2023-08-22 09:42:59 +03:00
data_sorted = suggestion_list
return data_sorted
2023-11-26 11:57:45 +02:00
def publish_summarizes_suggestions ( self , data : Dict ) :
try :
2024-01-15 15:10:54 +02:00
pr_body = " ## PR Code Suggestions \n \n "
2023-12-01 12:12:49 +02:00
language_extension_map_org = get_settings ( ) . language_extension_map_org
extension_to_language = { }
for language , extensions in language_extension_map_org . items ( ) :
for ext in extensions :
extension_to_language [ ext ] = language
2024-01-15 15:10:54 +02:00
pr_body + = " <table> "
header = f " Suggestions "
delta = 65
header + = " " * delta
pr_body + = f """ <thead><tr><th></th><th> { header } </th></tr></thead> """
pr_body + = """ <tbody> """
suggestions_labels = dict ( )
# add all suggestions related to to each label
for suggestion in data [ ' code_suggestions ' ] :
label = suggestion [ ' label ' ] . strip ( ) . strip ( " ' " ) . strip ( ' " ' )
if label not in suggestions_labels :
suggestions_labels [ label ] = [ ]
suggestions_labels [ label ] . append ( suggestion )
for label , suggestions in suggestions_labels . items ( ) :
pr_body + = f """ <tr><td><strong> { label } </strong></td> """
pr_body + = f """ <td><table> """
for suggestion in suggestions :
relevant_file = suggestion [ ' relevant_file ' ] . strip ( )
relevant_lines_start = int ( suggestion [ ' relevant_lines_start ' ] )
relevant_lines_end = int ( suggestion [ ' relevant_lines_end ' ] )
code_snippet_link = self . git_provider . get_line_link ( relevant_file , relevant_lines_start ,
relevant_lines_end )
# add html table for each suggestion
suggestion_content = suggestion [ ' suggestion_content ' ] . rstrip ( ) . rstrip ( )
suggestion_content = insert_br_after_x_chars ( suggestion_content , 90 )
# pr_body += f"<tr><td><details><summary>{suggestion_content}</summary>"
existing_code = suggestion [ ' existing_code ' ] . rstrip ( )
improved_code = suggestion [ ' improved_code ' ] . rstrip ( )
2023-12-01 12:12:49 +02:00
language_name = " python "
2024-01-15 15:10:54 +02:00
extension_s = suggestion [ ' relevant_file ' ] . rsplit ( ' . ' ) [ - 1 ]
2023-12-01 12:12:49 +02:00
if extension_s and ( extension_s in extension_to_language ) :
language_name = extension_to_language [ extension_s ]
2024-01-15 15:10:54 +02:00
example_code = " "
if self . git_provider . is_supported ( " gfm_markdown " ) :
example_code = " <details> <summary> Example code:</summary> \n \n "
example_code + = f " ___ \n \n "
example_code + = f " Existing code: \n ``` { language_name } \n { existing_code } \n ``` \n "
example_code + = f " Improved code: \n ``` { language_name } \n { improved_code } \n ``` \n "
2023-12-01 12:12:49 +02:00
if self . git_provider . is_supported ( " gfm_markdown " ) :
2024-01-15 15:10:54 +02:00
example_code + = " </details> \n "
pr_body + = f """
< tr >
< td >
* * { suggestion_content } * *
[ { relevant_file } [ { relevant_lines_start } - { relevant_lines_end } ] ] ( { code_snippet_link } )
{ example_code }
< / td >
< / tr >
"""
pr_body + = """ </table></td></tr> """
pr_body + = """ </tr></tbody></table> """
# for s in data['code_suggestions']:
# try:
# extension_s = s['relevant_file'].rsplit('.')[-1]
# code_snippet_link = self.git_provider.get_line_link(s['relevant_file'], s['relevant_lines_start'],
# s['relevant_lines_end'])
# label = s['label'].strip()
# data_markdown += f"\n💡 [{label}]\n\n**{s['suggestion_content'].rstrip().rstrip()}**\n\n"
# if code_snippet_link:
# data_markdown += f" File: [{s['relevant_file']} ({s['relevant_lines_start']}-{s['relevant_lines_end']})]({code_snippet_link})\n\n"
# else:
# data_markdown += f"File: {s['relevant_file']} ({s['relevant_lines_start']}-{s['relevant_lines_end']})\n\n"
# if self.git_provider.is_supported("gfm_markdown"):
# data_markdown += "<details> <summary> Example code:</summary>\n\n"
# data_markdown += f"___\n\n"
# language_name = "python"
# if extension_s and (extension_s in extension_to_language):
# language_name = extension_to_language[extension_s]
# data_markdown += f"Existing code:\n```{language_name}\n{s['existing_code'].rstrip()}\n```\n"
# data_markdown += f"Improved code:\n```{language_name}\n{s['improved_code'].rstrip()}\n```\n"
# if self.git_provider.is_supported("gfm_markdown"):
# data_markdown += "</details>\n"
# data_markdown += "\n___\n\n"
#
# pr_body += f"""<tr><td><b>{label}</b></td><td><a href="{code_snippet_link}">{s['relevant_file']}</a></td></tr>"""
# # in the right side of the table, add two collapsable sections with the existing and improved code
# pr_body += f"""<tr><td></td><td><details><summary>Existing code</summary><pre><code>{s['existing_code'].rstrip()}</code></pre></details></td></tr>"""
# pr_body += f"""<tr><td></td><td><details><summary>Improved code</summary><pre><code>{s['improved_code'].rstrip()}</code></pre></details></td></tr>"""
#
#
# except Exception as e:
# get_logger().error(f"Could not parse suggestion: {s}, error: {e}")
self . git_provider . publish_comment ( pr_body )
2023-11-26 11:57:45 +02:00
except Exception as e :
get_logger ( ) . info ( f " Failed to publish summarized code suggestions, error: { e } " )