Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enhance code review output with collapsible code snippets #1403

Merged
merged 4 commits into from
Dec 20, 2024

Conversation

mrT23
Copy link
Collaborator

@mrT23 mrT23 commented Dec 19, 2024

User description

…ariable links


PR Type

Enhancement


Description

  • Enhanced PR review output with collapsible code snippets using
    tags
  • Added clickable links to variables in issue content for better navigation
  • Implemented file language detection and code snippet extraction functionality
  • Refactored code by moving file language detection to a separate utility function
  • Updated key issues description to focus on high-priority concerns

Changes walkthrough 📝

Relevant files
Enhancement
utils.py
Enhanced markdown output with code snippets and variable links

pr_agent/algo/utils.py

  • Added collapsible code snippets in review output using
    tags
  • Added variable links in issue content with reference links
  • Added new function extract_relevant_lines_str() to extract code
    snippets
  • Added set_file_languages() function to determine file languages
  • +71/-13 
    github_provider.py
    Refactored file language detection logic                                 

    pr_agent/git_providers/github_provider.py

  • Moved file language detection logic to utils.py
  • Imported and used new set_file_languages() function
  • +2/-13   
    pr_reviewer.py
    Added support for code snippets in PR review                         

    pr_agent/tools/pr_reviewer.py

  • Added files parameter to convert_to_markdown_v2 call to support code
    snippets
  • +3/-1     
    Documentation
    pr_reviewer_prompts.toml
    Updated key issues description in reviewer prompts             

    pr_agent/settings/pr_reviewer_prompts.toml

  • Updated description for key_issues_to_review field to emphasize
    high-priority issues
  • +1/-1     

    💡 PR-Agent usage: Comment /help "your question" on any pull request to receive relevant information

    Copy link
    Contributor

    qodo-merge-pro-for-open-source bot commented Dec 19, 2024

    PR Reviewer Guide 🔍

    (Review updated until commit c2f1f2d)

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Possible Issue

    The extract_relevant_lines_str function may return an empty string or fail silently if no content is found in the file or an exception occurs. This could lead to incomplete or misleading markdown output. Consider adding more robust error handling or user feedback.

    def extract_relevant_lines_str(end_line, files, relevant_file, start_line):
        try:
            relevant_lines_str = ""
            if files:
                files = set_file_languages(files)
                for file in files:
                    if file.filename.strip() == relevant_file:
                        if not file.head_file:
                            get_logger().warning(f"No content found in file: {file.filename}")
                            return ""
                        relevant_file_lines = file.head_file.splitlines()
                        relevant_lines_str = "\n".join(relevant_file_lines[start_line - 1:end_line])
                        relevant_lines_str = f"```{file.language}\n{relevant_lines_str}\n```"
                        break
            return relevant_lines_str
        except Exception as e:
            get_logger().exception(f"Failed to extract relevant lines: {e}")
            return ""
    Code Clarity

    The logic for generating the markdown string in convert_to_markdown_v2 has become more complex with nested conditions. Consider refactoring to improve readability and maintainability.

    if issue_header.lower() == 'possible bug':
        issue_header = 'Possible Issue'  # Make the header less frightening
    issue_content = issue.get('issue_content', '').strip()
    start_line = int(str(issue.get('start_line', 0)).strip())
    end_line = int(str(issue.get('end_line', 0)).strip())
    
    relevant_lines_str = extract_relevant_lines_str(end_line, files, relevant_file, start_line)
    if git_provider:
        reference_link = git_provider.get_line_link(relevant_file, start_line, end_line)
    else:
        reference_link = None
    
    if gfm_supported:
        if reference_link is not None and len(reference_link) > 0:
            if relevant_lines_str:
                issue_str = f"<details><summary><a href='{reference_link}'><strong>{issue_header}</strong></a>\n\n{issue_content}</summary>\n\n{relevant_lines_str}\n\n</details>"
            else:
                issue_str = f"<a href='{reference_link}'><strong>{issue_header}</strong></a><br>{issue_content}"
    Schema Update

    The changes to the KeyIssuesComponentLink and Review schema fields may impact downstream consumers of this data. Ensure all dependent components are updated accordingly.

        issue_header: str = Field(description="One or two word title for the the issue. For example: 'Possible Bug', etc.")
        issue_content: str = Field(description="A short and concise summary of what should be further inspected and validated during the PR review process for this issue. Do not reference line numbers in this field.")
        start_line: int = Field(description="The start line that corresponds to this issue in the relevant file")
        end_line: int = Field(description="The end line that corresponds to this issue in the relevant file")
    
    {%- if related_tickets %}
    
    class TicketCompliance(BaseModel):
        ticket_url: str = Field(description="Ticket URL or ID")
        ticket_requirements: str = Field(description="Repeat, in your own words, all ticket requirements, in bullet points")
        fully_compliant_requirements: str = Field(description="A list, in bullet points, of which requirements are met by the PR code. Don't explain how the requirements are met, just list them shortly. Can be empty")
        not_compliant_requirements: str = Field(description="A list, in bullet points, of which requirements are not met by the PR code. Don't explain how the requirements are not met, just list them shortly. Can be empty")
        overall_compliance_level: str = Field(description="Overall give this PR one of these three values in relation to the ticket: 'Fully compliant', 'Partially compliant', or 'Not compliant'")
    {%- endif %}
    
    class Review(BaseModel):
    {%- if related_tickets %}
        ticket_compliance_check: List[TicketCompliance] = Field(description="A list of compliance checks for the related tickets")
    {%- endif %}
    {%- if require_estimate_effort_to_review %}
        estimated_effort_to_review_[1-5]: int = Field(description="Estimate, on a scale of 1-5 (inclusive), the time and effort required to review this PR by an experienced and knowledgeable developer. 1 means short and easy review , 5 means long and hard review. Take into account the size, complexity, quality, and the needed changes of the PR code diff.")
    {%- endif %}
    {%- if require_score %}
        score: str = Field(description="Rate this PR on a scale of 0-100 (inclusive), where 0 means the worst possible PR code, and 100 means PR code of the highest quality, without any bugs or performance issues, that is ready to be merged immediately and run in production at scale.")
    {%- endif %}
    {%- if require_tests %}
        relevant_tests: str = Field(description="yes\\no question: does this PR have relevant tests added or updated ?")
    {%- endif %}
    {%- if question_str %}
        insights_from_user_answers: str = Field(description="shortly summarize the insights you gained from the user's answers to the questions")
    {%- endif %}
        key_issues_to_review: List[KeyIssuesComponentLink] = Field("A short and diverse list (0-3 issues) of high-priority bugs, problems or performance concerns introduced in the PR code, which the PR reviewer should further focus on and validate during the review process.")
    {%- if require_security_review %}

    Copy link
    Contributor

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Score
    Possible issue
    Validate numeric parameters to prevent index errors and ensure logical consistency

    Add input validation for start_line and end_line parameters to ensure they are valid
    line numbers (positive integers with start_line <= end_line).

    pr_agent/algo/utils.py [298-302]

     def extract_relevant_lines_str(end_line, files, relevant_file, start_line):
         try:
    +        if not isinstance(start_line, int) or not isinstance(end_line, int) or start_line < 1 or start_line > end_line:
    +            get_logger().warning(f"Invalid line numbers: start_line={start_line}, end_line={end_line}")
    +            return ""
             relevant_lines_str = ""
             if files:
                 files = set_file_languages(files)
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    Why: This is a critical validation that prevents potential index errors and logical inconsistencies that could cause runtime errors when accessing file lines.

    8
    Add input validation to prevent index errors when accessing list elements

    In set_file_languages(), add validation for the case where diff_files is empty or
    None to prevent potential index errors when accessing diff_files[0].

    pr_agent/algo/utils.py [1173-1177]

     def set_file_languages(diff_files) -> List[FilePatchInfo]:
         try:
    +        if not diff_files:
    +            get_logger().warning("Empty diff_files provided to set_file_languages")
    +            return []
             # if the language is already set, do not change it
             if hasattr(diff_files[0], 'language') and diff_files[0].language:
                 return diff_files
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    Why: The suggestion prevents a potential IndexError by validating the diff_files input before accessing its first element, which could cause crashes in production.

    7
    General
    Add input validation with proper error logging for empty or missing input parameters

    Add error handling for the case where files is None or empty in
    extract_relevant_lines_str(). Currently, it silently returns an empty string which
    could mask potential issues.

    pr_agent/algo/utils.py [298-302]

     def extract_relevant_lines_str(end_line, files, relevant_file, start_line):
         try:
    +        if not files:
    +            get_logger().warning("No files provided to extract_relevant_lines_str")
    +            return ""
             relevant_lines_str = ""
    -        if files:
    -            files = set_file_languages(files)
    +        files = set_file_languages(files)
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    Why: The suggestion addresses a potential bug by adding proper validation and logging for empty input files, which could prevent silent failures and improve debugging capabilities.

    7
    • Author self-review: I have reviewed the PR code suggestions, and addressed the relevant ones.

    @mrT23
    Copy link
    Collaborator Author

    mrT23 commented Dec 19, 2024

    Persistent review updated to latest commit 7e8361b

    5 similar comments
    @mrT23
    Copy link
    Collaborator Author

    mrT23 commented Dec 19, 2024

    Persistent review updated to latest commit 7e8361b

    @mrT23
    Copy link
    Collaborator Author

    mrT23 commented Dec 19, 2024

    Persistent review updated to latest commit 7e8361b

    @mrT23
    Copy link
    Collaborator Author

    mrT23 commented Dec 19, 2024

    Persistent review updated to latest commit 7e8361b

    @mrT23
    Copy link
    Collaborator Author

    mrT23 commented Dec 19, 2024

    Persistent review updated to latest commit 7e8361b

    @mrT23
    Copy link
    Collaborator Author

    mrT23 commented Dec 19, 2024

    Persistent review updated to latest commit 7e8361b

    @mrT23
    Copy link
    Collaborator Author

    mrT23 commented Dec 19, 2024

    Persistent review updated to latest commit 989670b

    @mrT23
    Copy link
    Collaborator Author

    mrT23 commented Dec 19, 2024

    Persistent review updated to latest commit 3ab2cac

    @mrT23 mrT23 changed the title feat: enhance code review output with collapsible code snippets and v… feat: enhance code review output with collapsible code snippets Dec 19, 2024
    @mrT23 mrT23 merged commit c9f02e6 into main Dec 20, 2024
    2 checks passed
    @mrT23 mrT23 deleted the tr/re_review branch December 20, 2024 14:38
    @mrT23
    Copy link
    Collaborator Author

    mrT23 commented Dec 24, 2024

    Persistent review updated to latest commit c2f1f2d

    @mrT23
    Copy link
    Collaborator Author

    mrT23 commented Dec 30, 2024

    /review --config.base_url="abc"

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    2 participants