001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2017 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 // -@cs[AbbreviationAsWordInName] Should be removed at 7.0 version, 066 // we keep for some time to avoid breaking of compatibility 067 protected abstract String getMessageID(); 068 069 /** 070 * Hook called when visiting a token. Will not be called the method 071 * definition tokens. 072 * 073 * @param ast the token being visited 074 */ 075 protected abstract void visitTokenHook(DetailAST ast); 076 077 /** 078 * Hook called when leaving a token. Will not be called the method 079 * definition tokens. 080 * 081 * @param ast the token being left 082 */ 083 protected abstract void leaveTokenHook(DetailAST ast); 084 085 @Override 086 public final int[] getRequiredTokens() { 087 return new int[] { 088 TokenTypes.CTOR_DEF, 089 TokenTypes.METHOD_DEF, 090 TokenTypes.INSTANCE_INIT, 091 TokenTypes.STATIC_INIT, 092 }; 093 } 094 095 /** 096 * Set the maximum threshold allowed. 097 * 098 * @param max the maximum threshold 099 */ 100 public final void setMax(int max) { 101 this.max = max; 102 } 103 104 @Override 105 public void visitToken(DetailAST ast) { 106 switch (ast.getType()) { 107 case TokenTypes.CTOR_DEF: 108 case TokenTypes.METHOD_DEF: 109 case TokenTypes.INSTANCE_INIT: 110 case TokenTypes.STATIC_INIT: 111 visitMethodDef(); 112 break; 113 default: 114 visitTokenHook(ast); 115 } 116 } 117 118 @Override 119 public void leaveToken(DetailAST ast) { 120 switch (ast.getType()) { 121 case TokenTypes.CTOR_DEF: 122 case TokenTypes.METHOD_DEF: 123 case TokenTypes.INSTANCE_INIT: 124 case TokenTypes.STATIC_INIT: 125 leaveMethodDef(ast); 126 break; 127 default: 128 leaveTokenHook(ast); 129 } 130 } 131 132 /** 133 * Gets the current value. 134 * @return the current value 135 */ 136 protected final BigInteger getCurrentValue() { 137 return currentValue; 138 } 139 140 /** 141 * Set the current value. 142 * @param value the new value 143 */ 144 protected final void setCurrentValue(BigInteger value) { 145 currentValue = value; 146 } 147 148 /** 149 * Increments the current value by a specified amount. 150 * 151 * @param amount the amount to increment by 152 */ 153 protected final void incrementCurrentValue(BigInteger amount) { 154 currentValue = currentValue.add(amount); 155 } 156 157 /** Push the current value on the stack. */ 158 protected final void pushValue() { 159 valueStack.push(currentValue); 160 currentValue = INITIAL_VALUE; 161 } 162 163 /** 164 * Pops a value off the stack and makes it the current value. 165 * @return pop a value off the stack and make it the current value 166 */ 167 protected final BigInteger popValue() { 168 currentValue = valueStack.pop(); 169 return currentValue; 170 } 171 172 /** Process the start of the method definition. */ 173 private void visitMethodDef() { 174 pushValue(); 175 } 176 177 /** 178 * Process the end of a method definition. 179 * 180 * @param ast the token representing the method definition 181 */ 182 private void leaveMethodDef(DetailAST ast) { 183 final BigInteger bigIntegerMax = BigInteger.valueOf(max); 184 if (currentValue.compareTo(bigIntegerMax) > 0) { 185 log(ast, getMessageID(), currentValue, bigIntegerMax); 186 } 187 popValue(); 188 } 189}