SonarJS
SonarJS copied to clipboard
Rule Idea: Suggest β-reductions on useless immediately eliminated expressions
For each datatype in JS/TS, there is a way to introduce terms of that type, and then there are ways to eliminate terms of that type, performing some calculation, or retrieving a value from the data structure.
For example:
- Strings are introduced by string literals:
"hello world"
, and can be eliminated by indexing:s[42]
- Functions can be introduced by arrow expressions:
((x) => x * x)
, and can be eliminated by application:f(x)
- Arrays can be introduced by array literals:
[1, 2, 3]
, and eliminated by indexing:a[42]
- Objects can be introduced by object literals:
{ a: 1, b: 2 }
, and eliminated by indexing:obj['a']
If an introduction is immediately followed by elimination, then often β-reductions are applicable (at least as long there are no side-effects). Sometimes an introduction followed by elimination is useful, sometimes it's not:
- For functions, expressions of shape
((x) => body(x))(arg)
are known as IIFE (immediately invoked function expressions); These are useful, because the body of the function introduces a new scope, and also because thearg
is eagerly evaluated only once.
However, for many other data types, introduction followed by elimination seems much less useful, and is likely a typo:
-
Immediately eliminated array literals: Creating an array literal, and then immediately indexing into it with a constant index is quite useless. For example,
[10, 20, 30][2]
can be immediately β-reduced to just30
-
Immediately eliminated string literals: Similarly, indexing with constants into string literals is likely a typo:
"hello"[1]
can be reduced to just'e'
-
Immediately eliminated object literals: Analogously to arrays,
{ a: 1, b: 2 }['a']
can be reduced to just1
, and is likely a typo. It must be kept in mind, however, that this applies only to member accesses as expressions; if a member access appears inside of a method invocation, the object is bound as the receiver, and can therefore not be eliminated:{a: function() { return this.b; }, b:"bound in 'this'"}['a']() === "bound in 'this'"
.
We propose to introduce a rule that would cover at least the last three cases.
Link to the original discuss-topic: Dereferencing an array literal with a literal can be a code smell
@andrey-tyukin-sonarsource can you please link original discussion leading to this (even if private)
We might define rule in a generic way (like this ticket title but more user-friendly), and report only on member access with literal on another literal (string, array, object).
No much traction on this rule and the scope is not clear. Closing as won't fix