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

PLR1702 spam #15570

Open
beauxq opened this issue Jan 18, 2025 · 5 comments · May be fixed by #15578
Open

PLR1702 spam #15570

beauxq opened this issue Jan 18, 2025 · 5 comments · May be fixed by #15578
Labels
diagnostics Related to reporting of diagnostics. needs-design Needs further design before implementation

Comments

@beauxq
Copy link

beauxq commented Jan 18, 2025

If a function has nested blocks to violate PLR1702, almost the entire function is marked for it, including lines that are not violations.

Even lines that are only nested 2 or 3 deep are marked with squigglies.

Even when there are multiple lines in a block nested 9 deep, I think it would be enough to only mark the first line of that deeply nested block.

Image

@beauxq
Copy link
Author

beauxq commented Jan 18, 2025

PLR1702 is currently marking every line inside this function:

def foo():
    while a:  # should not be marked - not a violation
        if b:  # should not be marked - not a violation
            for c in range(3):  # should not be marked - not a violation
                if d:  # should not be marked - not a violation
                    while e:  # should not be marked - not a violation
                        if f:  # should not be marked - not a violation
                            for g in z:  # not bad to mark this line, but not needed if only marking the max
                                print(p)  # this line should be marked
                                pass  # this line doesn't need to be marked, because the previous line is marked
        else:  # should not be marked - not a violation
            print(q)  # should not be marked - not a violation

@dylwil3 dylwil3 added diagnostics Related to reporting of diagnostics. needs-mre Needs more information for reproduction labels Jan 18, 2025
@dylwil3
Copy link
Collaborator

dylwil3 commented Jan 18, 2025

That sounds annoying, I'm sorry! When I run this locally or in the playground, I only see a single diagnostic, though the whole range is highlighted. Similarly, when I use the VSCode extension, I see the entire block highlighted but the pop-up only displays a single diagnostic no matter where I hover.

Could you help me reproduce what you're seeing? What's your setup - how are you calling Ruff, and what version are you using?

Playground link

VSCode:

Image

Terminal:

cat tmp.py
def foo():
    while a:  # should not be marked - not a violation
        if b:  # should not be marked - not a violation
            for c in range(3):  # should not be marked - not a violation
                if d:  # should not be marked - not a violation
                    while e:  # should not be marked - not a violation
                        if f:  # should not be marked - not a violation
                            for g in z:  # not bad to mark this line, but not needed if only marking the max
                                print(p)  # this line should be marked
                                pass  # this line doesn't need to be marked, because the previous line is marked
        else:  # should not be marked - not a violation
            print(q)  # should not be marked - not a violationuvx ruff check tmp.py --isolated --select PLR --preview --no-cache
tmp.py:2:5: PLR1702 Too many nested blocks (7 > 5)
   |
 1 |   def foo():
 2 | /     while a:  # should not be marked - not a violation
 3 | |         if b:  # should not be marked - not a violation
 4 | |             for c in range(3):  # should not be marked - not a violation
 5 | |                 if d:  # should not be marked - not a violation
 6 | |                     while e:  # should not be marked - not a violation
 7 | |                         if f:  # should not be marked - not a violation
 8 | |                             for g in z:  # not bad to mark this line, but not needed if only marking the max
 9 | |                                 print(p)  # this line should be marked
10 | |                                 pass  # this line doesn't need to be marked, because the previous line is marked
11 | |         else:  # should not be marked - not a violation
12 | |             print(q)  # should not be marked - not a violation
   | |____________________^ PLR1702
   |

Found 1 error.

@beauxq
Copy link
Author

beauxq commented Jan 18, 2025

Here's an example with multiple diagnostics.
But I think the multiple diagnostics is not as big of a problem as everything being highlighted.

def foo():
    while a:  # should not be marked - not a violation
        if b:  # should not be marked - not a violation
            for c in range(3):  # should not be marked - not a violation
                if d:  # should not be marked - not a violation
                    while e:  # should not be marked - not a violation
                        if f:  # should not be marked - not a violation
                            for g in z:  # not bad to mark this line, but not needed if only marking the max
                                print(p)  # this line should be marked
                                pass  # this line doesn't need to be marked, because the previous line is marked
                        else:
                            if h:
                                print(r)
        else:  # should not be marked - not a violation
            print(q)  # should not be marked - not a violation

@beauxq
Copy link
Author

beauxq commented Jan 18, 2025

In the original example of the first screenshot, there 250 lines all completely highlighted, making it difficult to see other diagnostics.
That's not helpful highlighting.

If there are 5 violations, highlighting 5 lines is enough.

@dylwil3 dylwil3 removed the needs-mre Needs more information for reproduction label Jan 18, 2025
@dylwil3
Copy link
Collaborator

dylwil3 commented Jan 18, 2025

Thank you, that's helpful!

I think there's a small design question about how to handle this situation, and we should be conscious of whether we are creating a breaking change by modifying where a suppression comment can go. But I agree that we can do better here.

@dylwil3 dylwil3 added the needs-design Needs further design before implementation label Jan 18, 2025
@InSyncWithFoo InSyncWithFoo linked a pull request Jan 19, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
diagnostics Related to reporting of diagnostics. needs-design Needs further design before implementation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants