diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/DefaultNpathVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/DefaultNpathVisitor.java index bcbe3a3fe..86ca22c81 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/DefaultNpathVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/metrics/impl/visitors/DefaultNpathVisitor.java @@ -171,7 +171,16 @@ public Object visit(ASTSwitchStatement node, Object data) { @Override public Object visit(ASTConditionalExpression node, Object data) { - return node.isTernary() ? sumChildrenComplexities(node, data) + 2 : 1; + // bool comp of guard clause + complexity of last two children (= total - 1) + + if (node.isTernary()) { + ASTExpression wrapper = new ASTExpression(Integer.MAX_VALUE); + wrapper.jjtAddChild(node.jjtGetChild(0), 0); + int boolCompTernary = CycloMetric.booleanExpressionComplexity(wrapper); + + return boolCompTernary + sumChildrenComplexities(node, data) - 1; + } + return 1; } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml index 8c2387f79..2b5bebe73 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/metrics/impl/xml/NPathTest.xml @@ -5,13 +5,13 @@ public class Foo { public static void bar() { boolean a, b = true; - try { // total 6 + try { // total 8 if (true) { // 2 List buz = new ArrayList(); } - for(int i = 0; i < 19; i++) { // 2 - List buz = new ArrayList(); + for(int i = 0; i < 19; i++) { // 3 + List buz = a ? new ArrayList() : null; } } catch(Exception e) { if (true) { // 2 @@ -23,8 +23,12 @@ public class Foo { if (true || a && b) { // 4 j = 10; return; + } else { + j = 12; } + j = a || b ? j + 1 : j; // 3 + while (j++ < 20) { // 2 List buz = new ArrayList(); } @@ -53,7 +57,7 @@ public class Foo { Full example 1 - '.Foo#bar()' has value 2016. + '.Foo#bar()' has value 8064. @@ -266,11 +270,11 @@ class Bar { ]]> - test case for bug 3484404 (Invalid NPath calculation in return statement) + Test case for bug 3484404 (Invalid NPath calculation in return statement) 3 - '.Bar#x(boolean, boolean)' has value 25. - '.Bar#y(boolean, boolean)' has value 25. + '.Bar#x(boolean, boolean)' has value 4. + '.Bar#y(boolean, boolean)' has value 4. '.Bar#z(int, int)' has value 1. @@ -300,4 +304,156 @@ class Bar { ]]> + + NPath should count the boolean complexity of ternaries + 1 + + '.Test#method(Date)' has value 4. + + + + + + #01 NPath should count ternaries like if - else constructs (https://stackoverflow.com/q/5079923/6245827) + 1 + + '.Test#method(Date)' has value 2. + + + + + + #02 NPath should count ternaries like if - else constructs (https://stackoverflow.com/q/5079923/6245827) + 1 + + '.Test#method(Date)' has value 2. + + + + + + #1 NPath should count ternaries like if - else constructs (https://stackoverflow.com/q/5079923/6245827) + 6 + 1 + + '.SOFExample#usefulMethod(List)' has value 272. + + magicMap = new HashMap(); + protected static final long UNKNOWN = 0L; + private static final class MyCal { long aTime; long bTime; long cTime; long dTime;} + + public void usefulMethod(final List myCals) { + + final Date a = magicMap.get("a"); + final Date b = magicMap.get("b"); + final Date c = magicMap.get("c"); + final Date d = magicMap.get("d"); + + final long aTime = a == null ? UNKNOWN : a.getTime(); + final long bTime = b == null ? UNKNOWN : b.getTime(); + final long cTime = c == null ? UNKNOWN : c.getTime(); + final long dTime = d == null ? UNKNOWN : d.getTime(); + + for (MyCal myCal : myCals) { + if(myCal.aTime == UNKNOWN) myCal.aTime = aTime; + if(myCal.bTime == UNKNOWN) myCal.bTime = bTime; + if(myCal.cTime == UNKNOWN) myCal.cTime = cTime; + if(myCal.dTime == UNKNOWN) myCal.dTime = dTime; + } + } + } + ]]> + + + + #2 NPath should count ternaries like if - else constructs (https://stackoverflow.com/q/5079923/6245827) + 6 + 1 + + '.SOFExample#usefulMethod(List)' has value 272. + + magicMap = new HashMap(); + protected static final long UNKNOWN = 0L; + private static final class MyCal { long aTime; long bTime; long cTime; long dTime;} + + public void usefulMethod(final List myCals) { + + final Date a = magicMap.get("a"); + final Date b = magicMap.get("b"); + final Date c = magicMap.get("c"); + final Date d = magicMap.get("d"); + + final long aTime; + if (a == null) { + aTime = a.getTime(); + } else { + aTime = UNKNOWN; + } + + final long bTime; + if (b == null) { + bTime = b.getTime(); + } else { + bTime = UNKNOWN; + } + + final long cTime; + if (c == null) { + cTime = c.getTime(); + } else { + cTime = UNKNOWN; + } + + final long dTime; + if (d == null) { + dTime = d.getTime(); + } else { + dTime = UNKNOWN; + } + + for (MyCal myCal : myCals) { + if(myCal.aTime == UNKNOWN) myCal.aTime = aTime; + if(myCal.bTime == UNKNOWN) myCal.bTime = bTime; + if(myCal.cTime == UNKNOWN) myCal.cTime = cTime; + if(myCal.dTime == UNKNOWN) myCal.dTime = dTime; + } + } + } + ]]> + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/metrics/xml/NPathComplexity.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/metrics/xml/NPathComplexity.xml index 491811515..d72c8b90f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/metrics/xml/NPathComplexity.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/metrics/xml/NPathComplexity.xml @@ -160,11 +160,11 @@ class Bar { test case for bug 3484404 (Invalid NPath calculation in return statement) - 5 + 4 2 - The method 'x(boolean, boolean)' has an NPath complexity of 25 - The method 'y(boolean, boolean)' has an NPath complexity of 25 + The method 'x(boolean, boolean)' has an NPath complexity of 4 + The method 'y(boolean, boolean)' has an NPath complexity of 4 diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 0fc7526c0..72fcbc4d9 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -168,4 +168,5 @@ All existing rules have been updated to reflect these changes. If you have custo * [#548](https://github.com/pmd/pmd/pull/548): \[java] Metrics documentation - [Clément Fournier](https://github.com/oowekyala) * [#550](https://github.com/pmd/pmd/pull/550): \[java] Add basic resolution to type inference - [Bendegúz Nagy](https://github.com/WinterGrascph) * [#555](https://github.com/pmd/pmd/pull/555): \[java] Changed metrics/CyclomaticComplexityRule to use WMC when reporting classes - [Clément Fournier](https://github.com/oowekyala) +* [#557](https://github.com/pmd/pmd/pull/557): \[java] Fix NPath metric not counting ternaries correctly - [Clément Fournier](https://github.com/oowekyala)