March 2018 (version 1.12.0-beta)

1.12.0 Update

Hello!

We're happy to announce new DeepScan updates. While being hard at work to build new features like a team support and improved code viewer, we have been steadily improving our base analyzer.

Please kindly go ahead with the highlights for this release.

Release Summary

This version includes a number of updates that we hope you’ve found some of them helpful.
The key highlights are:

  • New rules - New rules for common pitfalls and improved rules.
  • Analysis improvements - New analysis technique leveraging a function summary and more precision on the instanceof check.

New Rules

To date, we have been hard at work detecting more code issues and providing much more rules.

Improved Rules

COMPARE_INCOMPATIBLE_TYPE_STRICTLY

Previously, this rule only covered the return value of JavaScript built-in functions.
We have extended it to cover general values, so alarms of the type shown below are newly detected:

class FacebookSocialButton extends Component {
  render() {
    const iconClassNames = classnames({
      "fa": true,
      // An COMPARE_INCOMPATIBLE_TYPE_STRICTLY alarm for 'this.props.altIcon':
      //  Property 'this.props.altIcon' has a string value,
      //   but it is incompatibly compared to boolean value true.
      //  The value of expression 'this.props.altIcon' is originated
      //   from the prop type declaration for 'altIcon' at line 109.
      "fa-facebook": this.props.altIcon !== true,
      "fa-facebook-alt": this.props.altIcon,
      [this.props.size]: this.props.size
      });
      ...
}
FacebookSocialButton.propTypes = {
  // 'altIcon' is declared as string type
  altIcon: PropTypes.string,
  ...
};
INSUFFICIENT_NULL_CHECK
  • Detect alarms on property accesses occurring inside JavaScript built-in functions, e.g., Object.keys()

Analysis Improvements

Function summary-based analysis technique

We have added summary-based analysis technique in this update. This technique can summarize a function's behavior on its parameters, e.g., whether a parameter is accessed inside the function body without null check.

With this technique, we have extended NULL_POINTER and INSUFFICIENT_NULL_CHECK rules to detect alarms across multiple functions and modules. For example, an INSUFFICIENT_NULL_CHECK alarm is detected for cm in the following code across three modules:

// src/model/line_widget.js
import { signalLater } from "../util/operation_group.js"
export function addLineWidget(doc, handle, node, options) {
  let widget = new LineWidget(doc, node, options)
  let cm = doc.cm

  // An INSUFFICIENT_NULL_CHECK alarm is detected for 'cm':
  //  Variable 'cm' is null checked here, but afterwards at line 76,
  //   it is passed as the first parameter of 'signalLater()' without null check.
  //  Note that the parameter's property is eventually accessed
  //   in the descendant function 'getHandlers()' at line 23 of src/util/event.js.
  if (cm && widget.noHScroll) cm.display.alignWidgets = true
  ...
  // 'cm' is passed to 'signalLater()' defined at 'src/util/operation_group.js' module.
  signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle))
  return widget
}
// src/util/operation_group.js
import { getHandlers } from "./event.js"
export function signalLater(emitter, type /*, values...*/) {
  // 'emitter' is passed further down to 'getHandlers()'.
  let arr = getHandlers(emitter, type)
  ...
}
// src/util/event.js
export function getHandlers(emitter, type) {
  // Here, 'emitter' is accessed without null check.
  return emitter._handlers && emitter._handlers[type] || noHandlers
}

Precision improvement on the instanceof check

When an instanceof check comes to succeed, it is guaranteed that the left operand is an object.
We have reflected this fact in the analysis engine and it enabled to detect the following alarm:

var ReactNativeComponent = (function(_React$Component) {
    function ReactNativeComponent() {
        if (!(this instanceof ReactNativeComponent))
          throw new TypeError("Cannot call a class as a function");
        var call = _React$Component.apply(this, arguments);
        // CONSTANT_CONDITION alarm:
        //  Condition '!this' is always false at this point
        //  because the else branch of the condition '!(this instanceof ReactNativeComponent)' at line 5612 has been taken.
        if (!this)
          throw new ReferenceError(
            "this hasn't been initialised - super() hasn't been called"
         );
        ...

In the above code, it is quite obvious that !this should have tested before the instanceof check.

Miscellaneous

  • Indicate definiteness of null values in NULL_POINTER issue messages
  • Recognize invariant() calls with multiple arguments as asserting condition
  • Atom package will show a brief rule information to further help your development

    Atom package: Show a rule information directly

Bug Fixes

  • Analyzer hangs when TypeScript as operator is used inside a pattern
  • Analyzer hangs when TypeScript dynamic import has no arguments
  • Analyzer hangs for some TypeScript recursive type definition
  • Pull request check fails when the commit is reset and pushed again