Merge branch 'docs-metrics' of https://github.com/oowekyala/pmd into pr-548

This commit is contained in:
Andreas Dangel
2017-08-13 12:05:51 +02:00
7 changed files with 406 additions and 193 deletions

View File

@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.metrics.impl.visitors;
import org.apache.commons.lang3.mutable.MutableInt;
import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTAssertStatement;
import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement;
import net.sourceforge.pmd.lang.java.ast.ASTCatchStatement;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
@ -220,4 +221,10 @@ public class DefaultNcssVisitor extends JavaParserVisitorAdapter {
return super.visit(node, data);
}
@Override
public Object visit(ASTAssertStatement node, Object data) {
((MutableInt) data).increment();
return super.visit(node, data);
}
}

View File

@ -16,51 +16,46 @@
metrics="true"
externalInfoUrl="${pmd.website.baseurl}/rules/java/codesize.html#CyclomaticComplexity">
<description>
<![CDATA[
Complexity directly affects maintenance costs is determined by the number of decision points in a method
plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls.
Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote
high complexity, and 11+ is very high complexity.
]]>
The complexity of methods directly affects maintenance costs and readability. Concentrating too much decisional logic
in a single method makes its behaviour hard to read and change.
Cyclomatic complexity assesses the complexity of a method by counting the number of decision points in a method,
plus one for the method entry. Decision points are places where the control flow jumps to another place in the
program. As such, they include all control flow statements, such as `if`, `while`, `for`, and `case`. For more
details on the calculation, see the documentation of the [Cyclo metric](/pmd_java_metrics_index.html#cyclomatic-complexity-cyclo).
Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote
high complexity, and 11+ is very high complexity.
Reported methods should be broken down into several smaller methods. Reported classes should probably be broken down
into subcomponents.
</description>
<priority>3</priority>
<example>
<![CDATA[
public class Foo { // This has a Cyclomatic Complexity = 12
1 public void example() {
2 if (a == b) {
3 if (a1 == b1) {
fiddle();
4 } else if a2 == b2) {
fiddle();
} else {
fiddle();
}
5 } else if (c == d) {
6 while (c == d) {
fiddle();
}
7 } else if (e == f) {
8 for (int n = 0; n < h; n++) {
fiddle();
}
} else{
switch (z) {
9 case 1:
fiddle();
break;
10 case 2:
fiddle();
break;
11 case 3:
fiddle();
break;
12 default:
fiddle();
break;
}
class Foo {
void baseCyclo() { // Cyclo = 1
highCyclo();
}
void highCyclo() { // Cyclo = 10: reported!
int x = 0, y = 2;
boolean a = false, b = true;
if (a && (y == 1 ? b : true)) { // +3
if (y == x) { // +1
while (true) { // +1
if (x++ < 20) { // +1
break; // +1
}
}
} else if (y == t && !d) { // +2
x = a ? y : x; // +1
} else {
x = 2;
}
}
}
}
]]>
</example>
@ -71,24 +66,38 @@ public class Foo { // This has a Cyclomatic Complexity = 12
since="3.9"
class="net.sourceforge.pmd.lang.java.metrics.rule.NcssCountRule"
metrics="true"
externalInfoUrl="${pmd.website.baseurl}/rules/java/codesize.html#NcssTypeCount">
externalInfoUrl="${pmd.website.baseurl}/rules/java/codesize.html#NcssCount">
<description>
This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines
of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm,
lines of code that are split are counted as one.
This rule uses the NCSS (Non-Commenting Source Statements) metric to determine the number of lines
of code in a class, method or constructor. NCSS ignores comments, blank lines, and only counts actual
statements. For more details on the calculation, see the documentation ofthe[NCSSmetric](/pmd_java_metrics_index.html#non-commenting-source-statements-ncss).
</description>
<priority>3</priority>
<example>
<![CDATA[
public class Foo extends Bar {
public Foo() { //this class only has 4 NCSS lines
super();
import java.util.Collections; // +0
import java.io.IOException; // +0
class Foo { // +1, total Ncss = 12
public void bigMethod() // +1
throws IOException {
int x = 0, y = 2; // +1
boolean a = false, b = true; // +1
if (a || b) { // +1
try { // +1
do { // +1
x += 2; // +1
} while (x < 12);
super.foo();
System.exit(0); // +1
} catch (IOException ioe) { // +1
throw new PatheticFailException(ioe); // +1
}
} else {
assert false; // +1
}
}
}
]]>
@ -103,41 +112,51 @@ public class Foo extends Bar {
externalInfoUrl="${pmd.website.baseurl}/rules/java/codesize.html#NPathComplexity">
<description>
The NPath complexity of a method is the number of acyclic execution paths through that method.
While cyclomatic complexity counts the number of decision points in a method, NPath counts the number of
full paths from the beginning to the end of the block of the method. That metric grows exponentially, as
it multiplies the complexity of statements in the same block. For more details on the calculation, see the
documentation of the [NPath metric](/pmd_java_metrics_index.html#npath-complexity-npath).
A threshold of 200 is generally considered the point where measures should be taken to reduce
complexity and increase readability.
</description>
<priority>3</priority>
<example>
<![CDATA[
void bar() { // This is something more complex than it needs to be,
if (y) { // it should be broken down into smaller methods or functions
for (j = 0; j < m; j++) {
if (j > r) {
doSomething();
while (f < 5 ) {
anotherThing();
f -= 27;
}
} else {
tryThis();
}
public class Foo {
public static void bar() { // Ncss = 252: reported!
boolean a, b = true;
try { // 2 * 2 + 2 = 6
if (true) { // 2
List buz = new ArrayList();
}
for(int i = 0; i < 19; i++) { // * 2
List buz = new ArrayList();
}
} catch(Exception e) {
if (true) { // 2
e.printStackTrace();
}
}
if ( r - n > 45) {
while (doMagic()) {
findRabbits();
}
while (j++ < 20) { // * 2
List buz = new ArrayList();
}
try {
doSomethingDangerous();
} catch (Exception ex) {
makeAmends();
} finally {
dontDoItAgain();
switch(j) { // * 7
case 1:
case 2: break;
case 3: j = 5; break;
case 4: if (b && a) { bar(); } break;
default: break;
}
do { // * 3
List buz = new ArrayList();
} while (a && j++ < 30);
}
}
]]>
</example>
</rule>

View File

@ -104,6 +104,7 @@
e.printStackTrace();
} catch (ThemAll pokemon) {
pokemon.train();
assert pokemon.level > 12;
} finally {
// Do nothing
}
@ -125,11 +126,11 @@
<rule-property name="reportClasses">true</rule-property>
<expected-problems>5</expected-problems>
<expected-messages>
<message>'com.company.money.Foo' has value 65 highest 20.</message>
<message>'com.company.money.Foo' has value 66 highest 21.</message>
<message>'com.company.money.Foo#Foo()' has value 2.</message>
<message>'com.company.money.Foo#Foo(int)' has value 13.</message>
<message>'com.company.money.Foo#foo()' has value 14.</message>
<message>'com.company.money.Foo#main(String)' has value 20.</message>
<message>'com.company.money.Foo#main(String)' has value 21.</message>
</expected-messages>
<code-ref id="full-example"/>
</test-code>
@ -140,11 +141,11 @@
<rule-property name="metricVersion">javaNcss</rule-property>
<expected-problems>5</expected-problems>
<expected-messages>
<message>'com.company.money.Foo' has value 68 highest 20.</message>
<message>'com.company.money.Foo' has value 69 highest 21.</message>
<message>'com.company.money.Foo#Foo()' has value 2.</message>
<message>'com.company.money.Foo#Foo(int)' has value 13.</message>
<message>'com.company.money.Foo#foo()' has value 14.</message>
<message>'com.company.money.Foo#main(String)' has value 20.</message>
<message>'com.company.money.Foo#main(String)' has value 21.</message>
</expected-messages>
<code-ref id="full-example"/>
</test-code>