-
Notifications
You must be signed in to change notification settings - Fork 186
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
Handle comparison to negative non-integer in expect_identical_linter #2411
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #2411 +/- ##
==========================================
+ Coverage 98.15% 98.65% +0.49%
==========================================
Files 125 125
Lines 5738 5631 -107
==========================================
- Hits 5632 5555 -77
+ Misses 106 76 -30 ☔ View full report in Codecov by Sentry. |
R/expect_identical_linter.R
Outdated
or following-sibling::expr[ | ||
OP-MINUS | ||
and count(expr) = 1 | ||
and expr[NUM_CONST[contains(text(), '.')]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and expr[NUM_CONST[contains(text(), '.')]] | |
and expr/NUM_CONST[contains(text(), '.')] |
nit: I've gravitated to this style to save a few characters (and also to avoid counting+matching nested ]
visually)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is the cut-off?
From what I understand, I could also write
expr[1][SYMBOL_FUNCTION_CALL[text() = 'c']]
as
expr[1]/SYMBOL_FUNCTION_CALL/text() = 'c'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the last condition belongs in []
-- otherwise it can get hard to visually parse operator presence of =
vs. nearby logical operators like and
/or
. IINM occasionally we have to let /text()
"out" e.g. to compare to the text()
of another node, but it's best avoided.
We don't really have an XPath style guide, so these are just my thoughts from writing many of these, you or other lintr authors may disagree.
R/expect_identical_linter.R
Outdated
@@ -69,6 +69,11 @@ expect_identical_linter <- function() { | |||
and expr[NUM_CONST[contains(text(), '.')]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I saw this too -- so we haven't fully restored parity yet in this PR.
expect_equal(x, 1.02) # no lint
expect_equal(x, c(1.02)) # no lint
expect_equal(x, -1.02) # no lint
expect_equal(x, c(-1.02)) # lint!
Let's at least get parity in this PR. I would put all of the conditions on following-sibling::expr[]
together btw, like:
following-sibling::expr[
(
expr[1]/SYMBOL_FUNCTION_CALL[text() = 'c']
and expr/NUM_CONST[contains(text(), '.')]
) or (
NUM_CONST[contains(text(), '.')]
) or (
OP-MINUS ...
)
]
Since NUM_CONST[contains(text(), '.')]
is getting repeated so much let's extract it to a variable too to save space.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, could you also test if the following lints?
expect_equal(x, c(1.02, y))
I think it's something to possible address in follow-up. I'm wondering if maybe it was intentional not to lint c(1.02, y)
because there's some part of the expectation that uses an "exact" number so we "should" skip linting on the same principle as just 1.02
? In which case we shouldn't lint 1.01-y
either 🤔
@AshesITR any thoughts? This cut-out does feel a bit arbitrary, probably by necessity at some level. Wondering how to close the loop here for this PR, and what can be deferred to a more holistic follow-up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lintr::lint(
text = "expect_equal(x, c(1.02, y))",
linters = lintr::expect_identical_linter()
)
Created on 2023-12-11 with reprex v2.0.2
It doesn't lint.
Co-authored-by: Michael Chirico <[email protected]>
ebcebc8
to
df79a10
Compare
All tests are now passing. I'm not super happy about the complexity of this xpath but I can't think of something simpler at the moment. Please let me know if you have a better way in mind. |
#963 may be a good way to simplify the code eventually. |
@@ -30,6 +30,10 @@ test_that("expect_identical_linter skips cases likely testing numeric equality", | |||
lint_msg <- rex::rex("Use expect_identical(x, y) by default; resort to expect_equal() only when needed") | |||
|
|||
expect_lint("expect_equal(x, 1.034)", NULL, linter) | |||
expect_lint("expect_equal(x, -1.034)", NULL, linter) | |||
expect_lint("expect_equal(x, c(-1.034))", NULL, linter) | |||
expect_lint("expect_equal(x, -c(1.034))", NULL, linter) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this case relevant in practice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm on the fence.
On the one hand, it should be caught be unnecessary_concatenation_linter()
and converted to the standard case. On the other hand, it's not just a false negative; not treating this case would lead us to produce incorrect advice.
Fix #2410