4

I am looking into calculating the cyclomatic complexity of java methods using Rascal.

One approach to this would be:

  • getting the AST from the method
  • use visit pattern on this tree
  • check for the following keywords which all increase the CC with one: case, catch, do, while, if, for, foreach

Another one is using graph theory and using the formula e-n+2. both e and n can be obtained quite easily using rascal functionality. My problem is how do I go about constructing the control flow graph, I found the following module: analysis::flow::ControlFlow which seems to be a step in the right direction but I am totally lost on where to go from there.

OmG
  • 18,337
  • 10
  • 57
  • 90
Lorenzo.A
  • 67
  • 4
  • The control flow graph construction route is also interesting but a lot more work. I suggest you first read the relevant parts of the "Dragon Book" (Aho, Seti, Ullman) or one of the Appel books "Modern Compiler Construction in ML" for example. But if this was a homework assignment, definitely I would go for Davy's answer. – Jurgen Vinju Oct 17 '16 at 06:58
  • @jurgenv thanks a lot for the suggestions :) It's both for a task and out of interest. Rascal seems like a very useful tool (once you can wrap your mind around it). Just not the type of guy that wants to hand in something that meets the criteria to succeed instead of looking around for better solutions. – Lorenzo.A Oct 19 '16 at 16:45

2 Answers2

5

The easiest way is indeed counting the forking nodes on the AST.

In our publication that explained SLOC and CC do not have a strong correlation to each other (preprint), we have also shared our rascal code to calculate CC (see Figure 2).

Here is the code extracted from the article, first create the file's AST with m3, and search for all methods/code blocks in the file. Per method you call this rascal function that visits the AST and counts certain nodes.

int calcCC(Statement impl) {
    int result = 1;
    visit (impl) {
        case \if(_,_) : result += 1;
        case \if(_,_,_) : result += 1;
        case \case(_) : result += 1;
        case \do(_,_) : result += 1;
        case \while(_,_) : result += 1;
        case \for(_,_,_) : result += 1;
        case \for(_,_,_,_) : result += 1;
        case \foreach(_,_,_) : result += 1;
        case \catch(_,_): result += 1;
        case \conditional(_,_,_): result += 1;
        case \infix(_,"&&",_) : result += 1;
        case \infix(_,"||",_) : result += 1;
    }
    return result;
}
Tarick Welling
  • 3,119
  • 3
  • 19
  • 44
Davy Landman
  • 15,109
  • 6
  • 49
  • 73
  • I was in fact implementing it this way, thanks for the confirmation :) In a perfect situation one would use jurgenv's answer therefore I chose to tag his as the answer. – Lorenzo.A Oct 19 '16 at 16:45
4

For construction control flow graphs in Rascal, there is a paper which explains how to do it in pure Rascal and how to raise the abstraction level using a declarative language called DCFlow: http://link.springer.com/chapter/10.1007%2F978-3-319-11245-9_18

Jurgen Vinju
  • 6,393
  • 1
  • 15
  • 26