001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2015 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.Check; 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 {@link Check} instead. 033 * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a> 034 * @author Oliver Burn 035 * @noinspection AbstractClassNeverImplemented 036 */ 037@Deprecated 038public abstract class AbstractComplexityCheck 039 extends Check { 040 /** The initial current value. */ 041 private static final BigInteger INITIAL_VALUE = BigInteger.ONE; 042 043 /** Stack of values - all but the current value. */ 044 private final Deque<BigInteger> valueStack = new ArrayDeque<>(); 045 046 /** The current value. */ 047 private BigInteger currentValue = BigInteger.ZERO; 048 049 /** Threshold to report error for. */ 050 private int max; 051 052 /** 053 * Creates an instance. 054 * @param max the threshold of when to report an error 055 */ 056 protected AbstractComplexityCheck(int max) { 057 this.max = max; 058 } 059 060 /** 061 * Gets the message ID to log violations with. 062 * @return the message ID to log violations with 063 */ 064 protected abstract String getMessageID(); 065 066 /** 067 * Hook called when visiting a token. Will not be called the method 068 * definition tokens. 069 * 070 * @param ast the token being visited 071 */ 072 protected abstract void visitTokenHook(DetailAST ast); 073 074 /** 075 * Hook called when leaving a token. Will not be called the method 076 * definition tokens. 077 * 078 * @param ast the token being left 079 */ 080 protected abstract void leaveTokenHook(DetailAST ast); 081 082 @Override 083 public final int[] getRequiredTokens() { 084 return new int[] { 085 TokenTypes.CTOR_DEF, 086 TokenTypes.METHOD_DEF, 087 TokenTypes.INSTANCE_INIT, 088 TokenTypes.STATIC_INIT, 089 }; 090 } 091 092 /** 093 * Set the maximum threshold allowed. 094 * 095 * @param max the maximum threshold 096 */ 097 public final void setMax(int max) { 098 this.max = max; 099 } 100 101 @Override 102 public void visitToken(DetailAST ast) { 103 switch (ast.getType()) { 104 case TokenTypes.CTOR_DEF: 105 case TokenTypes.METHOD_DEF: 106 case TokenTypes.INSTANCE_INIT: 107 case TokenTypes.STATIC_INIT: 108 visitMethodDef(); 109 break; 110 default: 111 visitTokenHook(ast); 112 } 113 } 114 115 @Override 116 public void leaveToken(DetailAST ast) { 117 switch (ast.getType()) { 118 case TokenTypes.CTOR_DEF: 119 case TokenTypes.METHOD_DEF: 120 case TokenTypes.INSTANCE_INIT: 121 case TokenTypes.STATIC_INIT: 122 leaveMethodDef(ast); 123 break; 124 default: 125 leaveTokenHook(ast); 126 } 127 } 128 129 /** 130 * Gets the current value. 131 * @return the current value 132 */ 133 protected final BigInteger getCurrentValue() { 134 return currentValue; 135 } 136 137 /** 138 * Set the current value. 139 * @param value the new value 140 */ 141 protected final void setCurrentValue(BigInteger value) { 142 currentValue = value; 143 } 144 145 /** 146 * Increments the current value by a specified amount. 147 * 148 * @param by the amount to increment by 149 */ 150 protected final void incrementCurrentValue(BigInteger by) { 151 currentValue = currentValue.add(by); 152 } 153 154 /** Push the current value on the stack. */ 155 protected final void pushValue() { 156 valueStack.push(currentValue); 157 currentValue = INITIAL_VALUE; 158 } 159 160 /** 161 * Pops a value off the stack and makes it the current value. 162 * @return pop a value off the stack and make it the current value 163 */ 164 protected final BigInteger popValue() { 165 currentValue = valueStack.pop(); 166 return currentValue; 167 } 168 169 /** Process the start of the method definition. */ 170 private void visitMethodDef() { 171 pushValue(); 172 } 173 174 /** 175 * Process the end of a method definition. 176 * 177 * @param ast the token representing the method definition 178 */ 179 private void leaveMethodDef(DetailAST ast) { 180 final BigInteger bigIntegerMax = BigInteger.valueOf(max); 181 if (currentValue.compareTo(bigIntegerMax) > 0) { 182 log(ast, getMessageID(), currentValue, bigIntegerMax); 183 } 184 popValue(); 185 } 186}