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

https://github.com/jackdewinter/pymarkdown/issues/1250 #1251

Merged
merged 15 commits into from
Nov 5, 2024

Conversation

jackdewinter
Copy link
Owner

@jackdewinter jackdewinter commented Nov 4, 2024

closes #1250

Summary by Sourcery

Enhance the Markdown transformation logic to better handle spacing for fenced code blocks within nested lists and block quotes, and add comprehensive test cases to ensure coverage of these scenarios.

Enhancements:

  • Improve the handling of spacing adjustments in the Markdown transformation process, particularly for complex nested structures involving lists and block quotes.

Documentation:

Tests:

  • Add new test cases to cover various scenarios involving fenced code blocks within lists and block quotes, addressing specific edge cases.

Copy link
Contributor

sourcery-ai bot commented Nov 4, 2024

Reviewer's Guide by Sourcery

This PR fixes issues with the MD031 rule (fenced code blocks should be surrounded by blank lines) when handling nested containers and container drops. The changes improve the handling of leading spaces and indentation in various container scenarios.

Updated class diagram for PendingContainerAdjustment

classDiagram
    class PendingContainerAdjustment {
        int insert_index
        string leading_space_to_insert
        bool do_insert
        bool do_special
    }
Loading

Updated class diagram for RuleMd031

classDiagram
    class RuleMd031 {
        List~List~PendingContainerAdjustment~~ __container_adjustments
        int __fix_count
        Optional~MarkdownToken~ __removed_container_stack_token
        List~MarkdownToken~ __x1
        List~List~PendingContainerAdjustment~~ __x2
        List~int~ __x3
        Optional~List~PendingContainerAdjustment~~ __removed_container_adjustments
        List~MarkdownToken~ __last_end_container_tokens
        LeadingSpaceIndexTracker __leading_space_index_tracker
        void starting_new_file()
        void __fix_spacing_special_case(PluginScanContext context, MarkdownToken token)
        void __fix_spacing_block_quote(MarkdownToken token, bool upgrade_kludge)
        bool __fix_spacing_one_container(PluginScanContext context, MarkdownToken token, bool upgrade_kludge)
        void __fix_spacing_with_fenced_and_list_end(PluginScanContext context, MarkdownToken token, MarkdownToken new_token)
        void __fix_spacing_with_special_list_fix(PluginScanContext context, MarkdownToken token, MarkdownToken new_token)
        void __fix_spacing_with_else(PluginScanContext context, MarkdownToken token, MarkdownToken new_token)
        bool __calc_kludge_one(bool at_least_one_container)
        bool __calc_2(PluginScanContext context, bool did_process_removals)
        Tuple~bool, bool~ __calc_3(PluginScanContext context, bool did_process_removals, bool at_least_one_container, bool upgrade_kludge)
        bool __apply_tailing_block_quote_fix(int modify_index, PluginScanContext context)
        void __fix_spacing(PluginScanContext context, MarkdownToken token, bool special_case)
        void __handle_fenced_code_block(PluginScanContext context, MarkdownToken token, bool special_case)
        void __process_pending_container_end_adjustment(PluginScanContext context, List~PendingContainerAdjustment~ next_container_adjustment_list)
        void __process_pending_container_end_tokens(PluginScanContext context, List~PendingContainerAdjustment~ next_container_adjustment_list)
        void next_token(PluginScanContext context, MarkdownToken token)
    }
Loading

Updated class diagram for TransformContainers

classDiagram
    class TransformContainers {
        static Optional~string~ __abcd_final_list_second_half(List~MarkdownToken~ removed_tokens, List~int~ removed_token_indices, List~MarkdownToken~ container_stack, Optional~string~ possible_prefix)
        static Optional~string~ __abcd_final_list(List~MarkdownToken~ removed_tokens, List~int~ removed_token_indices, List~MarkdownToken~ container_stack)
        static Optional~string~ __abcd_final(List~MarkdownToken~ removed_tokens, List~int~ removed_token_indices, List~MarkdownToken~ container_stack)
    }
Loading

File-Level Changes

Change Details Files
Added support for handling special cases in block quote and list container drops
  • Added do_special flag to PendingContainerAdjustment class
  • Added tracking of last end container tokens
  • Implemented new helper methods to handle different container drop scenarios
  • Added state tracking variables for container adjustments and indices
pymarkdown/plugins/rule_md_031.py
Improved container stack handling in transform containers
  • Split __abcd_final_list method into two parts for better organization
  • Added container stack parameter to handle list-only scenarios
  • Fixed indentation calculation for 3+ container drops
pymarkdown/transform_markdown/transform_containers.py
Added new test cases and updated existing ones
  • Added test cases for fenced blocks in nested lists and block quotes
  • Updated test skip flags for fixed scenarios
  • Added test coverage for new container drop handling
test/test_markdown_extra.py
test/rules/test_md031.py

Assessment against linked issues

Issue Objective Addressed Explanation
#1250 Fix cases where dropping two containers on a single line produces incorrect Markdown for MD031

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time. You can also use
    this command to specify where the summary should be inserted.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @jackdewinter - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider refactoring the state tracking in rule_md_031.py to use a cleaner state machine design rather than multiple parallel lists (x1, x2, x3) for tracking container state
Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟢 Security: all looks good
  • 🟡 Testing: 2 issues found
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@@ -53,9 +54,13 @@ def __init__(self) -> None:
self.__container_adjustments: List[List[PendingContainerAdjustment]] = []
self.__fix_count = 0
self.__removed_container_stack_token: Optional[MarkdownToken] = None
self.__x1: List[MarkdownToken] = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider using more descriptive names for __x1, __x2, and __x3 variables

These variables appear to represent removed tokens, container adjustments, and leading space indices respectively. More descriptive names would improve code readability and maintainability.

        self.__removed_tokens: List[MarkdownToken] = []

is_kludge_one = not any(i.is_block_quote_start for i in self.__x1[:-1])
return is_kludge_one

def __calc_2(self, context: PluginScanContext, did_process_removals: bool) -> bool:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Rename __calc_2 and __calc_3 methods to better describe their purpose

The current method names are not descriptive of their functionality. Consider names that indicate what these methods are calculating or processing.

    def __check_list_indentation(self, context: PluginScanContext, did_process_removals: bool) -> bool:

@pytest.mark.gfm
def test_extra_050c0():
"""
TBD
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (testing): Test descriptions are missing

Several test functions have 'TBD' as their docstring. Please add descriptive docstrings that explain what each test is verifying. This helps other developers understand the test cases and makes maintenance easier.

Comment on lines 9309 to 9310
# Act & Assert
act_and_assert(source_markdown, expected_gfm, expected_tokens, show_debug=False)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Consider parameterizing similar tests

There are multiple similar test cases that differ mainly in their input data. Consider using pytest's parameterize feature to reduce code duplication and make it easier to add new test cases.

@pytest.mark.parametrize(
    "source_markdown,expected_gfm,expected_tokens",
    [
        (source_markdown, expected_gfm, expected_tokens),
        # Add more test cases here as needed
    ],
)
def test_markdown_parsing(source_markdown, expected_gfm, expected_tokens):
    act_and_assert(source_markdown, expected_gfm, expected_tokens, show_debug=False)

Copy link

codecov bot commented Nov 4, 2024

Codecov Report

Attention: Patch coverage is 98.91304% with 1 line in your changes missing coverage. Please review.

Project coverage is 99.98%. Comparing base (50a1e94) to head (ecef8f0).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pymarkdown/plugins/rule_md_031.py 98.91% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1251      +/-   ##
==========================================
- Coverage   99.98%   99.98%   -0.01%     
==========================================
  Files         191      191              
  Lines       21123    21194      +71     
  Branches     2701     2715      +14     
==========================================
+ Hits        21120    21190      +70     
  Misses          1        1              
- Partials        2        3       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jackdewinter jackdewinter merged commit 2a9931e into main Nov 5, 2024
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Md031 fix: Some double drop cases are not producing the correct Markdown.
1 participant