001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2014 Oliver Burn 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//////////////////////////////////////////////////////////////////////////////// 019package com.puppycrawl.tools.checkstyle.checks.indentation; 020 021import com.puppycrawl.tools.checkstyle.api.DetailAST; 022import com.puppycrawl.tools.checkstyle.api.TokenTypes; 023 024/** 025 * Handler for array initialization blocks. 026 * 027 * @author jrichard 028 */ 029public class ArrayInitHandler extends BlockParentHandler 030{ 031 /** 032 * Construct an instance of this handler with the given indentation check, 033 * astract syntax tree, and parent handler. 034 * 035 * @param indentCheck the indentation check 036 * @param ast the astract syntax tree 037 * @param parent the parent handler 038 */ 039 public ArrayInitHandler(IndentationCheck indentCheck, 040 DetailAST ast, ExpressionHandler parent) 041 { 042 super(indentCheck, "array initialization", ast, parent); 043 } 044 045 @Override 046 protected IndentLevel getLevelImpl() 047 { 048 final DetailAST parentAST = getMainAst().getParent(); 049 final int type = parentAST.getType(); 050 if ((type == TokenTypes.LITERAL_NEW) || (type == TokenTypes.ASSIGN)) { 051 // note: assumes new or assignment is line to align with 052 return new IndentLevel(getLineStart(parentAST)); 053 } 054 else if (getParent() instanceof ArrayInitHandler) { 055 return ((ArrayInitHandler) getParent()).getChildrenExpectedLevel(); 056 } 057 else { 058 return getParent().getLevel(); 059 } 060 } 061 062 @Override 063 protected DetailAST getToplevelAST() 064 { 065 return null; 066 } 067 068 @Override 069 protected DetailAST getLCurly() 070 { 071 return getMainAst(); 072 } 073 074 @Override 075 protected IndentLevel curlyLevel() 076 { 077 final IndentLevel level = new IndentLevel(getLevel(), getBraceAdjustement()); 078 level.addAcceptedIndent(level.getLastIndentLevel() + getLineWrappingIndent()); 079 return level; 080 } 081 082 @Override 083 protected DetailAST getRCurly() 084 { 085 return getMainAst().findFirstToken(TokenTypes.RCURLY); 086 } 087 088 @Override 089 protected boolean rcurlyMustStart() 090 { 091 return false; 092 } 093 094 @Override 095 protected boolean childrenMayNest() 096 { 097 return true; 098 } 099 100 @Override 101 protected DetailAST getListChild() 102 { 103 return getMainAst(); 104 } 105 106 @Override 107 protected IndentLevel getChildrenExpectedLevel() 108 { 109 final IndentLevel expectedIndent = 110 new IndentLevel(getLevel(), getIndentCheck().getArrayInitIndent(), 111 getIndentCheck().getLineWrappingIndentation()); 112 113 final int firstLine = getFirstLine(Integer.MAX_VALUE, getListChild()); 114 if (hasCurlys() && (firstLine == getLCurly().getLineNo())) { 115 final int lcurlyPos = expandedTabsColumnNo(getLCurly()); 116 final int firstChildPos = 117 getNextFirstNonblankOnLineAfter(firstLine, lcurlyPos); 118 if (firstChildPos >= 0) { 119 expectedIndent.addAcceptedIndent(firstChildPos); 120 expectedIndent.addAcceptedIndent(lcurlyPos + getLineWrappingIndent()); 121 } 122 } 123 return expectedIndent; 124 } 125 126 /** 127 * @param lineNo number of line on which we search 128 * @param columnNo number of column after which we search 129 * 130 * @return column number of first non-blank char after 131 * specified column on specified line or -1 if 132 * such char doesn't exist. 133 */ 134 private int getNextFirstNonblankOnLineAfter(int lineNo, int columnNo) 135 { 136 int realColumnNo = columnNo + 1; 137 final String line = getIndentCheck().getLines()[lineNo - 1]; 138 final int lineLength = line.length(); 139 while ((realColumnNo < lineLength) 140 && Character.isWhitespace(line.charAt(realColumnNo))) 141 { 142 realColumnNo++; 143 } 144 145 return (realColumnNo == lineLength) ? -1 : realColumnNo; 146 } 147 148 /** 149 * A shortcut for <code>IndentationCheck</code> property. 150 * @return value of lineWrappingIndentation property 151 * of <code>IndentationCheck</code> 152 */ 153 private int getLineWrappingIndent() 154 { 155 return getIndentCheck().getLineWrappingIndentation(); 156 } 157}