package org.sonar.java.bytecode.check;
import org.sonar.check.IsoCategory;
+import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.java.bytecode.asm.AsmClass;
import org.sonar.squid.api.SourceClass;
import org.sonar.squid.measures.Metric;
-@Rule(key = "DIT", name = "DIT", isoCategory = IsoCategory.Maintainability)
+@Rule(key = "MaximumInheritanceDepth", name = "Avoid too deep inheritance tree", isoCategory = IsoCategory.Maintainability,
+ priority = Priority.MAJOR, description = "<p>Inheritance is certainly one of the most valuable concept of object-oriented "
+ + "programming. It's a way to compartmentalize and reuse code by creating collections of attributes and behaviors called "
+ + "classes which can be based on previously created classes. But abusing of this concept by creating a deep inheritance tree "
+ + "can lead to very complex and unmaintainable source code.</p>"
+ + "<p>Most of the time a too deep inheritance tree is due to bad object oriented design which has led to systematically use "
+ + "'inheritance' when 'composition' would suit better.</p>")
public class DITCheck extends BytecodeCheck {
- @RuleProperty(description = "Threshold.")
- private Integer threshold;
+ @RuleProperty(description = "Maximum depth of the inheritance tree.", defaultValue = "5")
+ private Integer max;
@Override
public void visitClass(AsmClass asmClass) {
SourceClass sourceClass = getSourceClass(asmClass);
int dit = sourceClass.getInt(Metric.DIT);
- if (dit > threshold) {
- CheckMessage message = new CheckMessage(this, "Depth of inheritance exceeds " + threshold + ".");
+ if (dit > max) {
+ CheckMessage message = new CheckMessage(this, "This class has " + dit
+ + " parents which makes it complex to understand and to maintain.");
message.setLine(sourceClass.getStartAtLine());
+ message.setCost(dit - max);
getSourceFile(asmClass).log(message);
}
}
- public void setThreshold(int threshold) {
- this.threshold = threshold;
+ public void setMax(int max) {
+ this.max = max;
}
}
squid = new Squid(new JavaSquidConfiguration());
squid.register(JavaAstScanner.class).scanDirectory(getFile("/bytecode/unusedProtectedMethod/src"));
DITCheck check = new DITCheck();
- check.setThreshold(1);
+ check.setMax(1);
squid.registerVisitor(check);
squid.register(BytecodeScanner.class).scanDirectory(getFile("/bytecode/unusedProtectedMethod/bin"));
}
@Test
- public void testDepthOfInheritanceExceedsThreshold() {
+ public void testDepthOfInheritanceGreaterThanMaximum() {
SourceFile file = (SourceFile) squid.search("UnusedProtectedMethod.java");
assertThat(file.getCheckMessages().size(), is(1));
CheckMessage message = file.getCheckMessages().iterator().next();
}
@Test
- public void testDepthOfInheritanceNotExceedsThreshold() {
+ public void testDepthOfInheritanceLowerThanMaximum() {
SourceFile file = (SourceFile) squid.search("Job.java");
assertThat(file.getCheckMessages().size(), is(0));
}