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