About Talks Articles

Detecting Nested Ternary Conditionals

3 min read

Nested ternary conditional operators can be useful. In some cases, e.g. to promote better code readability, you may want to outlaw that practice. Armed with a code parser, a simplistic code analysis allows such a pattern detection.

Once somebody understands the power of the ternary operation, it is very tempted to harness it in multiple ways. Sometimes it leads to something (still) logical and readable, e.g.:

var str = (age < 1) ? "baby" :
    (age < 5) ? "toddler" :
    (age < 18) ? "child": "adult";

The corresponding syntax tree of that code, produced by Esprima online parser, looks like this (some branches are collapsed):

In other cases, complicated and deep ternary operator abuse is a pattern you want to detect. Fortunately it is rather easy once you obtain the syntax tree. Such a tool is included in Esprima examples subdirectory, detectnestedternary.js (100 lines). Use Node.js to launch it as

node detectnestedternary.js /some/path

An exemplary output of the script if you run it against our example code above:

Line 1 : Nested ternary for "age < 1"
  Line 2 : Nested ternary for "age < 5"

The working principle of this script is very similar to previous example of Boolean traps detection I have already covered before. In fact, we will use the same syntax tree traversal function. All we have to do differently is to change the analyzer. Here we need to see if a ternary condition is immediately followed another ternary condition in either its consequent or alternate code path. Pretty easy to achieve:

function checkConditional(node) {
    var condition;
    if (node.consequent.type === 'ConditionalExpression' ||
            node.alternate.type === 'ConditionalExpression') {
        condition = content.substring(node.test.range[], node.test.range[1]);
        if (condition.length > 20) {
            condition = condition.substring(, 20) + '...';
        condition = '"' + condition + '"';
        report(node, 'Nested ternary for ' + condition);

To improve the report, the condition which triggers this nested conditionals is also printed out. Here we use Esprima’s feature of locating the range of that particular syntax node, this enables us to extract the portion of the source corresponding to that condition.

As an exercise for the reader, tweak the analyzer so that it triggers the warning only if the nesting goes deeper than a certain threshold. This way, the first ternary in the simple age detection case illustrated above may be skipped. You may also want to check the situation where the nested ternary is enclosed in another expression, i.e. it does not immediately show up as the direct child one (consequent or alternate).

Needless to say, not every use of nested ternary operators is bad. Set the criteria, look for the code pattern, and then guard yourself against unreadable and confusing code!

Related posts:

♡ this article? Explore more articles and follow me Twitter.

Share this on Twitter Facebook Google+

comments powered by Disqus