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

New unnecessary_nesting_linter #2302

Merged
merged 22 commits into from
Nov 22, 2023
Merged

New unnecessary_nesting_linter #2302

merged 22 commits into from
Nov 22, 2023

Conversation

MichaelChirico
Copy link
Collaborator

@MichaelChirico MichaelChirico commented Nov 17, 2023

Part of #884

@codecov-commenter
Copy link

codecov-commenter commented Nov 17, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (05baf80) 99.40% compared to head (e63967b) 99.40%.

❗ Current head e63967b differs from pull request most recent head 2efcafb. Consider uploading reports for the commit 2efcafb to get more accurate results

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2302   +/-   ##
=======================================
  Coverage   99.40%   99.40%           
=======================================
  Files         122      123    +1     
  Lines        5523     5584   +61     
=======================================
+ Hits         5490     5551   +61     
  Misses         33       33           

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

# NB: print() is intentionally excluded since its usage is usually a mistake (?print_linter)
signal_calls <- c(
exit_calls,
"warning", "warn", "message", "cat", "LOG", "stopifnot"
Copy link
Collaborator

Choose a reason for hiding this comment

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

LOG should not be default, and probably we should have an arg for configuration.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yep... left it in here as a reminder to discuss what sort of parameterization we should build in here, WDYT?

allow_signal_calls = c("warning", "message", "cat", "stopifnot")?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not 100% sure yet.

Copy link
Collaborator

Choose a reason for hiding this comment

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

So, just to understand this: These functions explicitly allow a parallel branch in if statements with a single control-flow breaking statement?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Right... they're allowed to pair with "exit" clauses, but can't cause a lint by themselves -- nested code using them can't always be unnested. IOW they can remove a lint, but not cause a lint.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

won't lint -- only the terminal call is examined

Copy link
Collaborator

Choose a reason for hiding this comment

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

So

if (A) {
  stop()
} else {
  warning()
  do()
}

Would lint?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Of course, one could always disable this behavior (and always force unnesting if possibe) by passing e.g. character() to the argument accepting a vector of calls.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm just wondering how intuitive the exception logic is.

R/unnecessary_nesting_linter.R Show resolved Hide resolved
R/unnecessary_nesting_linter.R Show resolved Hide resolved
R/unnecessary_nesting_linter.R Show resolved Hide resolved
# NB: print() is intentionally excluded since its usage is usually a mistake (?print_linter)
signal_calls <- c(
exit_calls,
"warning", "warn", "message", "cat", "LOG", "stopifnot"
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not 100% sure yet.

@AshesITR
Copy link
Collaborator

I think the path forward is to carve out an exception when the only expression inside { is an assignment. Shall we mark that with a parameter to unnecessary_nesting_linter()?

SGTM. Should default to not linting (so all_linters() doesn't create a conflicting configuration).
Argument allow_assignment = TRUE?

@AshesITR
Copy link
Collaborator

I think the exceptions need some additional thought. Two options:

  1. Remove exceptions for now and make a follow up issue.
  2. Flesh out the interface and what should be eligible for exception.

Which do you prefer?

@MichaelChirico
Copy link
Collaborator Author

MichaelChirico commented Nov 21, 2023

I think the exceptions need some additional thought. Two options:

  1. Remove exceptions for now and make a follow up issue.
  2. Flesh out the interface and what should be eligible for exception.

Which do you prefer?

let's go with one, I'm for making these PRs as sleek as possible in general:

#2325

R/unnecessary_nesting_linter.R Outdated Show resolved Hide resolved
R/unnecessary_nesting_linter.R Outdated Show resolved Hide resolved
R/unnecessary_nesting_linter.R Outdated Show resolved Hide resolved
or self::IF
or self::WHILE
or self::REPEAT
or self::expr/SYMBOL_FUNCTION_CALL[text() = 'switch']
Copy link
Collaborator

Choose a reason for hiding this comment

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

Parameterize the list of allowed functions?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Have something specific in mind? Per the comment, switch() is included here as a control flow which happens to be a function, so it's treated the same as if/for/while/repeat.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Those discussed in #2326 come to mind.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Let's follow up in #2334, removed the exception for switch() for now.

@IndrajeetPatil IndrajeetPatil merged commit 609750d into main Nov 22, 2023
20 checks passed
@IndrajeetPatil IndrajeetPatil deleted the unnecessary_nesting branch November 22, 2023 06:25
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.

4 participants