Skip to content

Instantly share code, notes, and snippets.

@rlidwka
Last active September 30, 2016 12:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rlidwka/8b904ca00b1e76731270 to your computer and use it in GitHub Desktop.
Save rlidwka/8b904ca00b1e76731270 to your computer and use it in GitHub Desktop.
Looking for a static analysis tool

TL;DR:

I'm testing five linters (jshint, jslint, eslint, gjslint, javascriptlint) - that's all that I could find - for two common and easily detectable errors.

But they don't find any, so I'm asking the community to suggest one that can.


Here is a piece of code. You know that pattern that makes a constructor callable without "new"?

$ cat test.js
function Test(foo) {
  if (!this instanceof Test) return new Test(foo)
}

It was discussed in es-discuss recently.

Can you see anything wrong with it? This poor fella I got the example from didn't.

So we were discussing which linter to use, and I suddenly remembered this pattern. What a nice way to test what linters are capable of!


So, jshint finds one missing semicolon. I know it could be turned off, but I'm looking for a tool to help find programming errors in 3rd party code regardless of the style it was written in. I could tolerate it, but this doesn't find an actual error.

$ jshint test.js
test.js: line 2, col 47, Missing semicolon.

1 error

jslint wants to insert curly braces and strict mode here, and curly braces can't even be turned off. This is something I call TTEACSUO - Tool To Enforce Author's Own Code Style Upon Others. Simply speaking, "opinionated crap".

$ jslint test.js

test.js
 #1 Missing 'use strict' statement.
    if (!this instanceof Test) return new Test() // Line 2, Pos 3
 #2 Expected '{' and instead saw 'return'.
    if (!this instanceof Test) return new Test() // Line 2, Pos 30
 #3 Stopping. (50% scanned).
     // Line 2, Pos 30

Here is eslint. Same thing. Well, this one is actually capable of being configured from scratch, so these errors can be turned off. But I'm looking for the instanceof check, and there isn't one!

$ ../node_modules/.bin/eslint test.js

test.js
  1:0   error  Missing "use strict" statement   strict
  2:2   error  Expected { after 'if' condition  curly
  2:46  error  Missing semicolon                semi

✖ 3 problems

Next is javascriptlint, I have no idea how to install it, so I'll just check it on the website. Semicolon... again? You gotta be kidding me.

1  function Test() {
2    if (!this instanceof Test) return new Test()
   =============================^
   lint warning: block statement without curly braces
3  }
   ^
   lint warning: missing semicolon

And the last one is gjslint, that's Google closure linter. Okay, I don't even expect it to find an error, but I thought Google guys were smart enough to know that semicolons are not required. Duh.

Skipping 1 file(s).
/home/alex/node/lib/test.js:2:(New Error 0010) Missing semicolon at end of line

Found 1 errors, including 1 new errors, in 1 files.

By the way, this was a real-life error. It was fixed in bunyan recently, and that's one of the most used logger libraries out there!

Second error pattern is actually from my own codebase:

assert(arg !== 'all'
    || arg !== 'owner'
    || arg !== 'anonymous'
    || arg !== 'undefined'
    || arg !== 'none'
, 'CONFIG: reserved user/uplink name: ' + arg)

Same story. I'm too tired to write down all linter responses, but all of them made noise about code style, and not a single one of them pointed at the actual error.


It's not just about those two errors, do you know what C++ static analysis tools are capable of? Even this non-obvious one gets found:

GimpBlob *
gimp_blob_square (gdouble xc,
                  gdouble yc,
                  gdouble xp,
                  gdouble yp,
                  gdouble xq,
                  gdouble yq)
{
  GimpBlobPoint points[4];

  /* Make sure we order points ccw */
  if (xp * yq - yq * xp < 0)
  {
    xq = -xq;
    yq = -yq;
  }
  ....
}

With an automatically generated warning There are identical sub-expressions to the left and to the right of the '-' operator.

For javascript there is nothing like this, which is a shame.


Now please, if anybody knows a linter that was able to find some of the actual errors mentioned here (before this article was created, that's about 20 Aug 2014), but doesn't annoy users about semis and other code style preferences, please let me know.

If I missed one, I'll be happy to use it and promote it however I can.


References:

  1. https://mail.mozilla.org/pipermail/es-discuss/2014-August/038998.html - es-discuss about instanceof
  2. http://stackoverflow.com/questions/20790728/negation-of-instanceof-gives-unexpected-results - stackoverflow about instanceof
  3. trentm/node-bunyan#159 - actual instanceof error in a very popular package
  4. rlidwka/sinopia#77 - example of the second error pattern
  5. http://www.viva64.com/en/b/0273/ - C++ static analysis tool I'm comparing to (non-free)
@MatrixFrog
Copy link

The Closure Compiler checks for this now, as of google/closure-compiler@72ad033

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment