-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Analyzer should warn on a mistaken JavaScript-function-body #50900
Comments
+1. We really should solve some of these void issues soon. They keep cropping up. I'll note this is a very similar request to dart-lang/linter#2780. I wrote:
I think I intended it to be more like your suggestion though, with the |
I see this as a warning, enabled-by-default. I can't think of false positives... |
That all begs the question: Do we want a very specific warning for only this case, or do we want a more general warning about the use of collection literals where the value can't be accessed? Are there enough cases of the more general warning to make it worth the extra effort? |
I discussed the downsides of a more general diagnostic at dart-lang/linter#2780 (comment). I do think this specific warning would be great to have. Any time this issue comes up (the javascript-function-body thing), it is always for this specific case. I think a more general warning involving collection-literals-of-void at large would be correct (have none-to-few false positives), but I don't know of real-world cases that would need to be guarded by a more general warning. I think it would be very pragmatic to enable this specific rule. |
Ok, thanks. |
I'm surprised- why isn't this caught by the [1, 2, 3].forEach((x) => {
print('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed $x')
});``` We are a passing a function that returns a |
It's hard to tell what I believe the case for the example you give, @oprypin, is that we infer a static type of Also, it looks like, from this line in the impl, the void_checks rule does not concern itself with arrow functions ( |
This works beautifully 🤩 |
Looking forward to having this added to the recommended set of lints! |
https://dart-review.googlesource.com/c/sdk/+/279962/comment/453f8d4b_d7b5b4af/ This check as implemented intentionally flags only foo(() => {someAction()}) However I am seeing that people have written code as follows and weren't alarmed even by the presence of commas: foo(() => {someAction(), anotherAction()}) So could we consider also flagging cases with any length? |
Does JavaScript allow commas in its function bodies? It's simple to rewrite the first case by removing the curly braces, but what would you expect users to write in place of the second case? |
I have been applying the fix of removing foo(() => {someAction(), anotherAction()}) foo(() {
someAction();
anotherAction();
}) (and so yes, I also disagree with how the suggested fix was implemented in https://dart-review.googlesource.com/c/sdk/+/282601) |
I suppose actually it does. JavaScript has this strange comma operator... But I don't think people wrote the commas there because they knew it from JavaScript, maybe they did it because Dart "for some reason" was complaining about a semicolon there |
Yup. The JavaScript It has one reasonable use, in the increment section of a If you recognize the usage as mistaken, the rewrite is to remove the |
I think JavaScript doesn't allow commas in its function bodies, for example: var f = () => {
console.log('abc'),
return 1;
}
console.log(f()); doesn't work. Changing the comma to a semicolon, or even removing it, would make it compilable. Regardless of the commas in JavaScript, the main point about reporting the hint is whether the user intended to have a set, or it was inadvertently written. The reported hint was explicitly made to trigger with only a single expression, since we are almost sure that the user didn't want to create a set. This was also mentioned in the OP. I think it should be expanded to cover multiple expressions, as even if the user meant to create a
Regarding the fix for a single expression, I am not seeing the harm of retaining the Changing it to a block |
It allows: var f = () => {
console.log('abc'),
console.log('def')
} An example with
JavaScript has this syntax:
And Dart, correspondingly:
The user wrote something that corresponds to option 2, why does the fix change it to option 1? |
The reason var f = () => {
console.log('abc'),
return 1;
} doesn't work is that About using |
…on't list these locally) dart-lang/sdk#50900 dart-lang/sdk#51205
I think it would be a mistake to impose this restriction -- I use I pointed out in my dup #51698 that the effect of this problem can result in some pretty weird errors, which don't indicate what is going wrong -- such as when you use The errors can get so weird that I really recommend this warning be turned on by default in the linter. |
I think I have seen VS Code rewrite ("fix" but really break) code that the programmer thought they were writing as a block, but the compiler and linter took to be a set, due to In addition to a lint that specifies that a() {}
b() {}
x() => {
a(); // Error here
b();
} the error is (currently):
I would prefer something explicit like:
I wanted to point out the similarity of this issue to a couple of others:
These two bugs, as well as this one, are all about detecting cases where the syntax allows programmers to make innocent mistakes with high likelihood, where the likelihood of intentional use of this syntax is either zero or close to zero, and where the warnings or errors that result from the mistake are mystifying, and can occur far from the problem. Hopefully these issues can all get fixed with warnings, at the least! |
I just noticed this bug was closed. However, The patch hasn't landed yet. The last update was May 24th by Samuel Rawlins:
@asashour Any chance this could get merged? |
Bug: #50900 Change-Id: Id09e102c2cc12c9043d3f6c22b3af3babf18920e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/284021 Reviewed-by: Nate Biggs <[email protected]> Reviewed-by: Oleh Prypin <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Oleh Prypin <[email protected]>
People used to writing JavaScript sometimes end up writing Dart code like:
The issue is using a
=> { expression }
"JavaScript function literal body" and thinking it just evaluatesexpression
.The
{...}
is a set literal in Dart, so it also allocates a new set.This is particularly easy to do where the function returns
void
, because of a combination of conveniences:void
, even aSet<void>
.void
function, but a=>
function disables that warning, because people like to use=> anyExpression
as a shorthand for{ \n anyExpression; \n }
.void
-typed expression, but not if it occurs in a context with typevoid
. Thevoid
expression inside the (inferred)<void>{...}
set literal also does not warn about using the value of avoid
expression.So it's the perfect storm of looking the other way when you do useless things, combined with the syntax meaning something else in a nearby language.
I'd recommend a warning/lint/hint/suggestion iff:
(args) => { singleExpression }
as a function literal, andvoid
.It could possibly be part of a more general warning, about using a literal (which is known to not have any side effects) in a
void
context (so the resulting value can also be assumed to not be used), which means the the allocation is unnecessary.Could also be an
unnecessary_literal
orunnecessary_allocation
lint, but this is such a fundamental mistake that I'd like a warning to be enabled by default.The text was updated successfully, but these errors were encountered: