001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2020 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.coding; 021 022import com.puppycrawl.tools.checkstyle.FileStatefulCheck; 023import com.puppycrawl.tools.checkstyle.api.AbstractCheck; 024import com.puppycrawl.tools.checkstyle.api.DetailAST; 025import com.puppycrawl.tools.checkstyle.api.TokenTypes; 026 027/** 028 * <p> 029 * Restricts nested try-catch-finally blocks to a specified depth. 030 * </p> 031 * <ul> 032 * <li> 033 * Property {@code max} - Specify maximum allowed nesting depth. 034 * Default value is {@code 1}. 035 * </li> 036 * </ul> 037 * <p> 038 * To configure the check: 039 * </p> 040 * <pre> 041 * <module name="NestedTryDepth"/> 042 * </pre> 043 * <p> 044 * case 1: Example of code with violation: 045 * </p> 046 * <pre> 047 * try { 048 * try { 049 * try { // violation, current depth is 2, default max allowed depth is 1 050 * } catch (Exception e) { 051 * } 052 * } catch (Exception e) { 053 * } 054 * } catch (Exception e) { 055 * } 056 * </pre> 057 * <p> 058 * case 1: Example of compliant code: 059 * </p> 060 * <pre> 061 * try { 062 * try { // OK, current depth is 1, default max allowed depth is also 1 063 * } catch (Exception e) { 064 * } 065 * } catch (Exception e) { 066 * } 067 * </pre> 068 * <p>case 2: Example of code for handling unique and general exceptions</p> 069 * <pre> 070 * try { 071 * try { // OK, current depth is 1, default max allowed depth is also 1 072 * // any more nesting could cause code violation! 073 * throw ArithmeticException(); 074 * } catch (ArithmeticException e) { // catches arithmetic exceptions 075 * } catch (NumberFormatException e) { // catches number-format exceptions 076 * } catch (Exception e) { // catches general exceptions other than stated above 077 * } 078 * } catch ( 079 * ArithmeticException 080 * | NumberFormatException 081 * | ArrayIndexOutOfBoundsException e) { // catches any of the 3 exception 082 * } catch (Exception e) { // catches general exception 083 * } finally { // do something when try-catch block finished execution 084 * } 085 * </pre> 086 * <p> 087 * To configure the check to allow nesting depth 3: 088 * </p> 089 * <pre> 090 * <module name="NestedTryDepth"> 091 * <property name="max" value="3"/> 092 * </module> 093 * </pre> 094 * <p> 095 * Example of code with violation: 096 * </p> 097 * <pre> 098 * try { 099 * try { 100 * try { 101 * try { 102 * try { // violation, current depth is 4, max allowed depth is 3 103 * } catch (Exception e) { 104 * } 105 * } catch (Exception e) { 106 * } 107 * } catch (Exception e) { 108 * } 109 * } catch (Exception e) { 110 * } 111 * } catch (Exception e) { 112 * } 113 * </pre> 114 * <p> 115 * Example of compliant code: 116 * </p> 117 * <pre> 118 * try { 119 * try { 120 * try { 121 * try { // OK, current depth is 3, max allowed depth is also 3 122 * } catch (Exception e) { 123 * } 124 * } catch (Exception e) { 125 * } 126 * } catch (Exception e) { 127 * } 128 * } catch (Exception e) { 129 * } 130 * </pre> 131 * 132 * @since 3.2 133 */ 134@FileStatefulCheck 135public final class NestedTryDepthCheck extends AbstractCheck { 136 137 /** 138 * A key is pointing to the warning message text in "messages.properties" 139 * file. 140 */ 141 public static final String MSG_KEY = "nested.try.depth"; 142 143 /** Specify maximum allowed nesting depth. */ 144 private int max = 1; 145 /** Current nesting depth. */ 146 private int depth; 147 148 /** 149 * Setter to specify maximum allowed nesting depth. 150 * 151 * @param max maximum allowed nesting depth. 152 */ 153 public void setMax(int max) { 154 this.max = max; 155 } 156 157 @Override 158 public int[] getDefaultTokens() { 159 return getRequiredTokens(); 160 } 161 162 @Override 163 public int[] getAcceptableTokens() { 164 return getRequiredTokens(); 165 } 166 167 @Override 168 public int[] getRequiredTokens() { 169 return new int[] {TokenTypes.LITERAL_TRY}; 170 } 171 172 @Override 173 public void beginTree(DetailAST rootAST) { 174 depth = 0; 175 } 176 177 @Override 178 public void visitToken(DetailAST literalTry) { 179 if (depth > max) { 180 log(literalTry, MSG_KEY, depth, max); 181 } 182 ++depth; 183 } 184 185 @Override 186 public void leaveToken(DetailAST literalTry) { 187 --depth; 188 } 189 190}