diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/NPathComplexityCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/NPathComplexityCheck.java
index aff35858e..808a7ae39 100644
--- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/NPathComplexityCheck.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/NPathComplexityCheck.java
@@ -20,7 +20,10 @@
package com.puppycrawl.tools.checkstyle.checks.metrics;
import java.math.BigInteger;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import com.puppycrawl.tools.checkstyle.api.Check;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
@@ -34,7 +37,7 @@ import com.puppycrawl.tools.checkstyle.api.TokenTypes;
* @author Simon Harris
* @author o_sukhodolsky
*/
-public final class NPathComplexityCheck extends AbstractComplexityCheck {
+public final class NPathComplexityCheck extends Check {
/**
* A key is pointing to the warning message text in "messages.properties"
@@ -45,9 +48,25 @@ public final class NPathComplexityCheck extends AbstractComplexityCheck {
/** Default allowed complexity. */
private static final int DEFAULT_MAX = 200;
- /** Creates new instance of the check. */
- public NPathComplexityCheck() {
- super(DEFAULT_MAX);
+ /** The initial current value. */
+ private static final BigInteger INITIAL_VALUE = BigInteger.ONE;
+
+ /** Stack of values - all but the current value. */
+ private final Deque valueStack = new ArrayDeque<>();
+
+ /** The current value. */
+ private BigInteger currentValue = INITIAL_VALUE;
+
+ /** Threshold to report error for. */
+ private int max = DEFAULT_MAX;
+
+ /**
+ * Set the maximum threshold allowed.
+ *
+ * @param max the maximum threshold
+ */
+ public void setMax(int max) {
+ this.max = max;
}
@Override
@@ -90,6 +109,16 @@ public final class NPathComplexityCheck extends AbstractComplexityCheck {
};
}
+ @Override
+ public int[] getRequiredTokens() {
+ return new int[] {
+ TokenTypes.CTOR_DEF,
+ TokenTypes.METHOD_DEF,
+ TokenTypes.INSTANCE_INIT,
+ TokenTypes.STATIC_INIT,
+ };
+ }
+
@Override
public void visitToken(DetailAST ast) {
switch (ast.getType()) {
@@ -107,8 +136,14 @@ public final class NPathComplexityCheck extends AbstractComplexityCheck {
case TokenTypes.LITERAL_CASE:
visitAddingConditional();
break;
+ case TokenTypes.CTOR_DEF:
+ case TokenTypes.METHOD_DEF:
+ case TokenTypes.INSTANCE_INIT:
+ case TokenTypes.STATIC_INIT:
+ visitMethodDef();
+ break;
default:
- super.visitToken(ast);
+ break;
}
}
@@ -129,16 +164,17 @@ public final class NPathComplexityCheck extends AbstractComplexityCheck {
case TokenTypes.LITERAL_CASE:
leaveAddingConditional();
break;
+ case TokenTypes.CTOR_DEF:
+ case TokenTypes.METHOD_DEF:
+ case TokenTypes.INSTANCE_INIT:
+ case TokenTypes.STATIC_INIT:
+ leaveMethodDef(ast);
+ break;
default:
- super.leaveToken(ast);
+ break;
}
}
- @Override
- protected String getMessageID() {
- return MSG_KEY;
- }
-
/** Visits else, catch or case. */
private void visitAddingConditional() {
pushValue();
@@ -146,8 +182,7 @@ public final class NPathComplexityCheck extends AbstractComplexityCheck {
/** Leaves else, catch or case. */
private void leaveAddingConditional() {
- setCurrentValue(
- getCurrentValue().subtract(BigInteger.ONE).add(popValue()));
+ currentValue = currentValue.subtract(BigInteger.ONE).add(popValue());
}
/** Visits while, do, for, if, try, ? (in ?::) or switch. */
@@ -157,17 +192,39 @@ public final class NPathComplexityCheck extends AbstractComplexityCheck {
/** Leaves while, do, for, if, try, ? (in ?::) or switch. */
private void leaveMultiplyingConditional() {
- setCurrentValue(
- getCurrentValue().add(BigInteger.ONE).multiply(popValue()));
+ currentValue = currentValue.add(BigInteger.ONE).multiply(popValue());
}
- @Override
- protected void visitTokenHook(DetailAST ast) {
- // no code
+ /** Push the current value on the stack. */
+ private void pushValue() {
+ valueStack.push(currentValue);
+ currentValue = INITIAL_VALUE;
}
- @Override
- protected void leaveTokenHook(DetailAST ast) {
- // no code
+ /**
+ * Pops a value off the stack and makes it the current value.
+ * @return pop a value off the stack and make it the current value
+ */
+ private BigInteger popValue() {
+ currentValue = valueStack.pop();
+ return currentValue;
+ }
+
+ /** Process the start of the method definition. */
+ private void visitMethodDef() {
+ pushValue();
+ }
+
+ /**
+ * Process the end of a method definition.
+ *
+ * @param ast the token representing the method definition
+ */
+ private void leaveMethodDef(DetailAST ast) {
+ final BigInteger bigIntegerMax = BigInteger.valueOf(max);
+ if (currentValue.compareTo(bigIntegerMax) > 0) {
+ log(ast, MSG_KEY, currentValue, bigIntegerMax);
+ }
+ popValue();
}
}