SonarJS icon indicating copy to clipboard operation
SonarJS copied to clipboard

Rule Idea: Suggest β-reductions on useless immediately eliminated expressions

Open andrey-tyukin-sonarsource opened this issue 3 years ago • 2 comments

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 the arg 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 just 30
  • 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 just 1, 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)

saberduck avatar May 28 '21 09:05 saberduck

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).

vilchik-elena avatar Apr 25 '22 08:04 vilchik-elena

No much traction on this rule and the scope is not clear. Closing as won't fix

vilchik-elena avatar Oct 18 '22 15:10 vilchik-elena