26

I've been looking at using SonarQube to do quality checking on some javascript code, but this code is written using AngularJS.

One of the SonarQube rules checks the number of lines in a function - which seems sensible - but in AngularJS, functions are used to define controllers, services and directives, and these functions can get pretty big. Conceptually, they're really more like class definitions, with other functions nested within them.

Ideally, I'd like SonarQube to check the lengths of the inner functions, and possibly the outer function with the inner ones excluded, but I don't know of any way to do this.

Has anyone else encountered this problem using SonarQube with AngularJS, or does anyone know a good solution?

Dan King
  • 3,412
  • 5
  • 24
  • 23
  • I don't know anything about AngularJS but how do you differentiate outer from inner functions? Naming convention? Something else? – David RACODON - QA Consultant Mar 07 '14 at 21:34
  • By "inner function", I just mean a function that's declared inside another one. In AngularJS, that's typically an anonymous function that is declared and immediately assigned as a property on the 'scope' object, which is passed to the outer function that defines the controller, service or directive in question. It would be nice if Sonar could recognise for example, that a function which does nothing other than declare and assign 10 other 100 line functions, doesn't count in itself as a 1000 line function. – Dan King Mar 08 '14 at 13:43
  • See the "Simple Spicy Controller" example here (it's about half way down the page - you'll need to click the app.js button on that example to see the code), for a very simple example of how controllers are declared in AngularJS: http://docs.angularjs.org/guide/controller – Dan King Mar 08 '14 at 13:44
  • OK, I see. One question though: Why these outer functions may get big? Isn't there any other way to design them? Inner functions of inner funcion? – David RACODON - QA Consultant Mar 08 '14 at 22:28
  • 1
    That's the pattern for using the AngularJS framework. The controller is a function whose job is to assign other functionality to the scope. For a large page or complicated control there could be a number of inner functions involved. In this situation, the controller is really acting a bit more like a class declaration. Instead of using inner functions, you could define the functions you want outside the controller before using the controller to assign them to the scope, but then these functions would be globally-scoped which isn't really what you want. – Dan King Mar 08 '14 at 23:05
  • I don't understand what you mean by "inner functions of inner function" or how that would help? The problem seems to me to be that SonarQube doesn't distinguish between nested (i.e. "inner") and non-nested functions - so that if you nest a function inside another one, SonarQube always counts the length of the inner function as part of the length of the outer one. – Dan King Mar 08 '14 at 23:08
  • Is the issue still relevant? I am evaluating using Sonar and SonarJS for a larger hybrid app. After runing it on our real code i don't see any false positives on this issue in my angular project. I am using Sonar 6.3 sporting the SonarJS 2.21 plugin – r-hold Mar 22 '17 at 15:44

1 Answers1

1

One solution is to declare all your methods separately in your self-executing function.

(function(){
    var controller = function(dependency){
         //...
    },

    someDirective = function(dependency){
        //...
    },

    //Finally, your module
    module = angular.module("MyMod", []);

    module.controller("MyController", ['dependency', controller]);
    module.directive("someDirective", ['dependency', someDirective]);
}());

This definitely can be an uncomfortable pattern for some devs, but it's one way to break your functions into smaller pieces for SonarQube.

Community
  • 1
  • 1
Hylianpuffball
  • 1,553
  • 10
  • 13
  • 1
    Your example doesn't quite solve the problem, but I guess it could do if you declared your scope methods (for example) in your self-executing function but outside the controller function and then just assigned them inside it. But you still have functions nested within a function, it's just that the outer function is self-executing - or does SonarQube ignore that one? – Dan King Jan 14 '15 at 20:51
  • 2
    Having investigated this a bit further, unfortunately SonarQube sees a self-executing function as just another function and applies the number of lines check to this as well, so this doesn't fix the problem at all. Seems like SonarQube really isn't geared up to work properly with Javascript, as this is a common general pattern for limiting scope and really shouldn't be subject to the same limitations as a normal function. – Dan King Jun 12 '15 at 11:37