001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2016 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.checks.metrics; 021 022import java.math.BigInteger; 023import java.util.ArrayDeque; 024import java.util.Deque; 025 026import com.puppycrawl.tools.checkstyle.api.AbstractCheck; 027import com.puppycrawl.tools.checkstyle.api.DetailAST; 028import com.puppycrawl.tools.checkstyle.api.TokenTypes; 029 030/** 031 * Base class for checks the calculate complexity based around methods. 032 * @deprecated Checkstyle will not support abstract checks anymore. Use 033 * {@link AbstractCheck} instead. 034 * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a> 035 * @author Oliver Burn 036 * @noinspection AbstractClassNeverImplemented 037 */ 038@Deprecated 039public abstract class AbstractComplexityCheck 040 extends AbstractCheck { 041 /** The initial current value. */ 042 private static final BigInteger INITIAL_VALUE = BigInteger.ONE; 043 044 /** Stack of values - all but the current value. */ 045 private final Deque<BigInteger> valueStack = new ArrayDeque<>(); 046 047 /** The current value. */ 048 private BigInteger currentValue = BigInteger.ZERO; 049 050 /** Threshold to report error for. */ 051 private int max; 052 053 /** 054 * Creates an instance. 055 * @param max the threshold of when to report an error 056 */ 057 protected AbstractComplexityCheck(int max) { 058 this.max = max; 059 } 060 061 /** 062 * Gets the message ID to log violations with. 063 * @return the message ID to log violations with 064 */ 065 protected abstract String getMessageID(); 066 067 /** 068 * Hook called when visiting a token. Will not be called the method 069 * definition tokens. 070 * 071 * @param ast the token being visited 072 */ 073 protected abstract void visitTokenHook(DetailAST ast); 074 075 /** 076 * Hook called when leaving a token. Will not be called the method 077 * definition tokens. 078 * 079 * @param ast the token being left 080 */ 081 protected abstract void leaveTokenHook(DetailAST ast); 082 083 @Override 084 public final int[] getRequiredTokens() { 085 return new int[] { 086 TokenTypes.CTOR_DEF, 087 TokenTypes.METHOD_DEF, 088 TokenTypes.INSTANCE_INIT, 089 TokenTypes.STATIC_INIT, 090 }; 091 } 092 093 /** 094 * Set the maximum threshold allowed. 095 * 096 * @param max the maximum threshold 097 */ 098 public final void setMax(int max) { 099 this.max = max; 100 } 101 102 @Override 103 public void visitToken(DetailAST ast) { 104 switch (ast.getType()) { 105 case TokenTypes.CTOR_DEF: 106 case TokenTypes.METHOD_DEF: 107 case TokenTypes.INSTANCE_INIT: 108 case TokenTypes.STATIC_INIT: 109 visitMethodDef(); 110 break; 111 default: 112 visitTokenHook(ast); 113 } 114 } 115 116 @Override 117 public void leaveToken(DetailAST ast) { 118 switch (ast.getType()) { 119 case TokenTypes.CTOR_DEF: 120 case TokenTypes.METHOD_DEF: 121 case TokenTypes.INSTANCE_INIT: 122 case TokenTypes.STATIC_INIT: 123 leaveMethodDef(ast); 124 break; 125 default: 126 leaveTokenHook(ast); 127 } 128 } 129 130 /** 131 * Gets the current value. 132 * @return the current value 133 */ 134 protected final BigInteger getCurrentValue() { 135 return currentValue; 136 } 137 138 /** 139 * Set the current value. 140 * @param value the new value 141 */ 142 protected final void setCurrentValue(BigInteger value) { 143 currentValue = value; 144 } 145 146 /** 147 * Increments the current value by a specified amount. 148 * 149 * @param amount the amount to increment by 150 */ 151 protected final void incrementCurrentValue(BigInteger amount) { 152 currentValue = currentValue.add(amount); 153 } 154 155 /** Push the current value on the stack. */ 156 protected final void pushValue() { 157 valueStack.push(currentValue); 158 currentValue = INITIAL_VALUE; 159 } 160 161 /** 162 * Pops a value off the stack and makes it the current value. 163 * @return pop a value off the stack and make it the current value 164 */ 165 protected final BigInteger popValue() { 166 currentValue = valueStack.pop(); 167 return currentValue; 168 } 169 170 /** Process the start of the method definition. */ 171 private void visitMethodDef() { 172 pushValue(); 173 } 174 175 /** 176 * Process the end of a method definition. 177 * 178 * @param ast the token representing the method definition 179 */ 180 private void leaveMethodDef(DetailAST ast) { 181 final BigInteger bigIntegerMax = BigInteger.valueOf(max); 182 if (currentValue.compareTo(bigIntegerMax) > 0) { 183 log(ast, getMessageID(), currentValue, bigIntegerMax); 184 } 185 popValue(); 186 } 187}