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.indentation; 021 022import com.puppycrawl.tools.checkstyle.api.DetailAST; 023import com.puppycrawl.tools.checkstyle.api.TokenTypes; 024 025/** 026 * Handler for try blocks. 027 * 028 */ 029public class TryHandler extends BlockParentHandler { 030 031 /** 032 * Construct an instance of this handler with the given indentation check, 033 * abstract syntax tree, and parent handler. 034 * 035 * @param indentCheck the indentation check 036 * @param ast the abstract syntax tree 037 * @param parent the parent handler 038 */ 039 public TryHandler(IndentationCheck indentCheck, 040 DetailAST ast, AbstractExpressionHandler parent) { 041 super(indentCheck, "try", ast, parent); 042 } 043 044 /** 045 * Method to find left parenthesis of try with resources. 046 * 047 * @return DetailAst left parenthesis of try with resources 048 */ 049 private DetailAST getTryResLparen() { 050 return getMainAst().getFirstChild().getFirstChild(); 051 } 052 053 /** 054 * Method to find right parenthesis of try with resources. 055 * 056 * @return DetailAst right parenthesis of try with resources 057 */ 058 private DetailAST getTryResRparen() { 059 return getMainAst().getFirstChild().getLastChild(); 060 } 061 062 @Override 063 public IndentLevel getSuggestedChildIndent(AbstractExpressionHandler child) { 064 final IndentLevel result; 065 if (child instanceof CatchHandler 066 || child instanceof FinallyHandler) { 067 result = getIndent(); 068 } 069 else { 070 result = super.getSuggestedChildIndent(child); 071 } 072 return result; 073 } 074 075 @Override 076 public void checkIndentation() { 077 super.checkIndentation(); 078 if (getMainAst().getFirstChild().getType() == TokenTypes.RESOURCE_SPECIFICATION) { 079 checkTryResParen(getTryResLparen(), "lparen"); 080 checkTryResParen(getTryResRparen(), "rparen"); 081 checkTryResources(getMainAst().getFirstChild()); 082 } 083 } 084 085 /** 086 * Method to check the indentation of left paren or right paren. 087 * This method itself checks whether either of these are on start of line. This method 088 * takes care of line wrapping strict condition as well. 089 * 090 * @param parenAst lparen or rparen ast to check 091 * @param subType name to be used in log message 092 */ 093 private void checkTryResParen(final DetailAST parenAst, 094 final String subType) { 095 if (isOnStartOfLine(parenAst)) { 096 final IndentLevel expectedIdent = new IndentLevel(getIndent(), 0, 097 getIndentCheck().getLineWrappingIndentation()); 098 099 checkChildIndentation(parenAst, subType, expectedIdent); 100 } 101 } 102 103 /** 104 * Method to check indentation of try resources children. 105 * It takes into account forceStrictCondition value when logging violations. 106 * Example of usage would include checking for try parenthesis and try resources. 107 * 108 * @param ast AST to check. 109 * @param subType String representing child type. 110 * @param expectedIdent Expected indent level. 111 */ 112 private void checkChildIndentation(DetailAST ast, String subType, IndentLevel expectedIdent) { 113 if (getIndentCheck().isForceStrictCondition()) { 114 if (!expectedIdent.isAcceptable(expandedTabsColumnNo(ast))) { 115 logError(ast, subType, expandedTabsColumnNo(ast), expectedIdent); 116 } 117 } 118 else { 119 if (expandedTabsColumnNo(ast) < expectedIdent.getFirstIndentLevel()) { 120 logError(ast, subType, expandedTabsColumnNo(ast), expectedIdent); 121 } 122 } 123 } 124 125 /** 126 * Checks indentation of resources parameters in try resources. 127 * 128 * @param resourcesSpecAst Resource specification ast 129 */ 130 private void checkTryResources(final DetailAST resourcesSpecAst) { 131 final DetailAST resourcesAst = resourcesSpecAst.findFirstToken(TokenTypes.RESOURCES); 132 final int indentation = getIndent().getFirstIndentLevel() 133 + getIndentCheck().getLineWrappingIndentation(); 134 final IndentLevel expectedResourceIndent = new IndentLevel(indentation); 135 136 final String subType = "resource"; 137 138 DetailAST resourceAst = resourcesAst.getFirstChild(); 139 while (resourceAst != null) { 140 if (resourceAst.getType() == TokenTypes.RESOURCE) { 141 final DetailAST nextSibling; 142 if (resourceAst.getNextSibling() == null) { 143 nextSibling = getTryResRparen(); 144 } 145 else { 146 nextSibling = resourceAst.getNextSibling(); 147 } 148 if (isOnStartOfLine(resourceAst)) { 149 checkChildIndentation(resourceAst, subType, expectedResourceIndent); 150 checkWrappingIndentation( 151 resourceAst, 152 nextSibling, 153 getIndentCheck().getLineWrappingIndentation(), 154 expectedResourceIndent.getFirstIndentLevel(), 155 true); 156 } 157 else { 158 checkWrappingIndentation(resourceAst, nextSibling); 159 } 160 } 161 resourceAst = resourceAst.getNextSibling(); 162 } 163 } 164 165}