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