背景 - 下面的问题
我刚开始在Java for Java中实现一个度量套件,但我担心我的方法不合适。
目前我正在为目录中的每个文件使用JDT ASTParser。这开始很好,我能够收集行数和每个类的每个方法的平均行数。这是通过一个MethodVisitor类完成的,该类扩展了ASTVisitor并包含一个方法访问(MethodDeclaration节点)。
我现在正在尝试为每种方法计算Cyclomatic Complexity。我已经拆分了方法体并且有一个ComplexityVisitor,它包含一个访问(IfStatement节点)和一个访问(ReturnStatement节点)。
使用这个结构我知道代码中有一个if语句,但我不确定如何知道有多少级别的“if else”。我能找到的唯一有用的方法是node.getElseStatement(),但这会返回一个基本上(或者在我看来)字符串的内容,因此必须使用正则表达式来知道语句可以采用的路径数。
所以我的问题是:
使用eclipses ASTParser时,有没有办法推断“if - else if - else”语句中有多少级别?
或
我是否应该寻找更清洁的解决方案,例如IJavaElement,或者自己解析代码,将关键字放到列表中然后循环回来。
一些示例代码 - 非常多地处于测试阶段
public class Test {
private static List<ClassInfo> klasses = new ArrayList<ClassInfo>();
// Called for every file where str is what the file contains
public static void parse(String str) {
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setSource(str.toCharArray());
parser.setKind(ASTParser.K_COMPILATION_UNIT);
final CompilationUnit cu = (CompilationUnit) parser.createAST(null);
ClassVisitor cv = new ClassVisitor();
cu.accept(cv);
MethodVisitor methodsVisitor = new MethodVisitor(cu);
cu.accept(methodsVisitor);
ClassInfo klass = new ClassInfo(cv.getClassName(),
cu.getLineNumber(cu.getLength() - 1),
methodsVisitor.getNumberOfMethods(),
methodsVisitor.getAverageLinesPerMethod(),
methodsVisitor.getMethods());
for(int i = 0; i < klass.methods.size(); i++){
parser.setSource(klass.methods.get(i).body.toCharArray());
CyclomaticComplexityVisitor ccv = new CyclomaticComplexityVisitor();
cu.accept(ccv);
}
klasses.add(klass);
}
-
public class MethodVisitor extends ASTVisitor {
private CompilationUnit cu;
private int numberOfMethods;
private int lineCount;
private List<MethodInfo> methods = new ArrayList<MethodInfo>();
public MethodVisitor(CompilationUnit cu){
this.cu = cu;
}
public boolean visit(MethodDeclaration node){
int startPos = cu.getLineNumber(node.getStartPosition());
int endPos = cu.getLineNumber(node.getStartPosition() + node.getLength());
lineCount += (endPos - startPos);
numberOfMethods++;
String methodBody = node.getBody().toString();
MethodInfo m = new MethodInfo(node.getName().getIdentifier(),
(endPos - startPos),
node.getReturnType2());
m.body = methodBody;
methods.add(m);
return true;
}
-
public class CyclomaticComplexityVisitor extends ASTVisitor {
private int complexityScore = 0;
private int edges = 0;
private int nodes = 0;
private int exitPoints = 1;
private boolean firstReturn = true;
public boolean visit(IfStatement node){
System.out.println("THERE WAS AN IF");
String statement = node.toString();
System.out.println(statement);
return true;
}
public boolean visit(ReturnStatement node){
if (firstReturn) {
firstReturn = false;
} else {
exitPoints++;
}
return true;
}
干杯
答案 0 :(得分:2)
我不确定这是否能解答您的问题,但是为了计算McCabe的Cyclomatic Complexity(McCC)指标,您不需要关心if-else-if嵌套级别。你只需要计算&#34;分支&#34;的数量。说明并最后添加1。请参阅User's Guide工具的SourceMeter中的定义:
McCabe的Cyclomatic Complexity(McCC) 方法:方法的复杂性表示为其中的独立控制流路径的数量。它表示源代码中可能的执行路径数的下限,同时它是实现完整分支测试覆盖所需的最小测试用例数的上限。度量的值计算为以下指令的数量加1:if,for,foreach,while,do-while,case标签(属于switch指令),catch,条件语句(?:)。此外, 逻辑“和”(&amp;&amp;)和逻辑“或”(||)表达式也将值加1,因为它们的短路评估可能会导致分支,具体取决于第一个操作数。不包括以下说明:else,switch,default label(属于switch指令),try,finally。