Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JENKINS-42268] CyclomaticComplexity lint defect initial approach
  • Loading branch information
v1v committed Jul 29, 2017
1 parent a31601c commit 813809f
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
@@ -0,0 +1,107 @@
package org.jenkins.ci.plugins.jenkinslint.check;

import hudson.matrix.MatrixProject;
import hudson.maven.MavenModuleSet;
import hudson.model.Item;
import hudson.model.Project;
import hudson.tasks.Builder;
import jenkins.model.Jenkins;
import org.jenkins.ci.plugins.jenkinslint.model.AbstractCheck;

import java.util.List;
import java.util.logging.Level;

/**
* @author Victor Martinez
*/
public class CyclomaticComplexityChecker extends AbstractCheck {

private final int THRESHOLD = 4;

public CyclomaticComplexityChecker() {
super();
this.setDescription(Messages.CyclometicComplexityCheckerDesc());
this.setSeverity(Messages.CyclometicComplexityCheckerSeverity());
}

public boolean executeCheck(Item item) {
boolean found = false;
if (Jenkins.getInstance().pluginManager.getPlugin("conditional-buildstep") != null) {

int cyclomatic = 0;
if (Jenkins.getInstance().pluginManager.getPlugin("maven-plugin") != null) {
if (item instanceof MavenModuleSet) {
cyclomatic = totalCyclomatic(((MavenModuleSet) item).getPrebuilders());
found = cyclomatic > THRESHOLD;
}
}
if (item instanceof Project) {
cyclomatic = totalCyclomatic(((Project) item).getBuilders());
found = cyclomatic > THRESHOLD;
}
if (item instanceof MatrixProject) {
cyclomatic = totalCyclomatic(((MatrixProject) item).getBuilders());
found = cyclomatic > THRESHOLD;
}

LOG.log(Level.INFO, "Cyclomatic complexity of " + item.getName() + " is " + cyclomatic);

} else {
LOG.log(Level.INFO, "Conditional BuildStep plugin is not installed");
}
return found;
}

private int totalCyclomatic(List<Builder> builders) {
int cyclomatic = 0;
if (builders != null && builders.size() > 0 ) {
for (Builder builder : builders) {
if (builder.getClass().getName().endsWith("ConditionalBuilder")) {
cyclomatic += cyclomatic(builder, 0);
}
}
}
return cyclomatic;
}

private int conditionalCyclomatic(Object builder) {
int cyclomatic = 0;
try {
Object getConditionalbuilders = builder.getClass().getMethod("getConditionalbuilders", null).invoke(builder);
if (getConditionalbuilders instanceof List) {
for (Object conditional : ((List) getConditionalbuilders)) {
cyclomatic += cyclomatic(conditional, 0);
}
}
} catch (Exception e) {
LOG.log(Level.WARNING, "Exception " + e.getMessage(), e.getCause());
cyclomatic = 0;
}
return cyclomatic;
}

private int cyclomatic(Object builder, int cyclomatic) {
try {
Object runCondition = builder.getClass().getMethod("getRunCondition", null).invoke(builder);
switch (runCondition.getClass().getSimpleName()) {
case "And":
cyclomatic += conditionalCyclomatic(builder);
break;
case "Or":
cyclomatic += conditionalCyclomatic(builder);
break;
case "Not":
cyclomatic += conditionalCyclomatic(builder);
break;
default:
cyclomatic++;
break;
}
} catch (Exception e) {
LOG.log(Level.WARNING, "Exception " + e.getMessage(), e.getCause());
}
return cyclomatic;
}


}
Expand Up @@ -5,6 +5,12 @@ ArtifactCheckerDesc=\

ArtifactCheckerSeverity=Medium

CyclometicComplexityCheckerDesc=\
Cyclomatic Complexity in Jenkins job over 5 indicates a higher complexity. \
<br/>It's recommended to simplify those jenkins jobs by splitting them for instance..\
CyclometicComplexityCheckerSeverity=High
CleanupWorkspaceCheckerDesc=\
There are some builds which demand a lot of disc space. Some builds \
might run out of space during the build itself and cause build errors. \
Expand Down

0 comments on commit 813809f

Please sign in to comment.