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.javadoc; 020 021import java.util.ArrayList; 022import java.util.List; 023 024import com.puppycrawl.tools.checkstyle.api.DetailNode; 025import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes; 026 027/** 028 * <p> 029 * Checks the indentation of the continuation lines in at-clauses. 030 * </p> 031 * <p> 032 * Default configuration: 033 * </p> 034 * <pre> 035 * <module name="JavadocTagContinuationIndentation"> 036 * <property name="offset" value="4"/> 037 * </module> 038 * </pre> 039 * 040 * @author max 041 * 042 */ 043public class JavadocTagContinuationIndentationCheck extends AbstractJavadocCheck 044{ 045 046 /** Default tag continuation indentation */ 047 private static final int DEFAULT_INDENTATION = 4; 048 049 /** 050 * How many spaces to use for new indentation level. 051 */ 052 private int offset = DEFAULT_INDENTATION; 053 054 /** 055 * Sets custom indentation level. 056 * @param offset custom value. 057 */ 058 public void setOffset(int offset) 059 { 060 this.offset = offset; 061 } 062 063 @Override 064 public int[] getDefaultJavadocTokens() 065 { 066 return new int[] {JavadocTokenTypes.DESCRIPTION }; 067 } 068 069 @Override 070 public void visitJavadocToken(DetailNode ast) 071 { 072 final List<DetailNode> textNodes = getAllNewlineNodes(ast); 073 if (isInlineDescription(ast)) { 074 return; 075 } 076 for (DetailNode newlineNode : textNodes) { 077 final DetailNode textNode = JavadocUtils.getNextSibling(JavadocUtils 078 .getNextSibling(newlineNode)); 079 if (textNode != null && textNode.getType() == JavadocTokenTypes.TEXT 080 && textNode.getChildren().length > 1) 081 { 082 final DetailNode whitespace = JavadocUtils.getFirstChild(textNode); 083 if (whitespace.getType() == JavadocTokenTypes.WS 084 && whitespace.getText().length() - 1 < offset) 085 { 086 log(textNode.getLineNumber(), "tag.continuation.indent", offset); 087 } 088 } 089 } 090 } 091 092 /** 093 * Finds and collects all NEWLINE nodes inside DESCRIPTION node. 094 * @param descriptionNode DESCRIPTION node. 095 * @return List with NEWLINE nodes. 096 */ 097 private List<DetailNode> getAllNewlineNodes(DetailNode descriptionNode) 098 { 099 final List<DetailNode> textNodes = new ArrayList<DetailNode>(); 100 DetailNode node = JavadocUtils.getFirstChild(descriptionNode); 101 while (JavadocUtils.getNextSibling(node) != null) { 102 if (node.getType() == JavadocTokenTypes.NEWLINE) { 103 textNodes.add(node); 104 } 105 node = JavadocUtils.getNextSibling(node); 106 } 107 return textNodes; 108 } 109 110 /** 111 * Checks, if description node is a description of in-line tag. 112 * @param description DESCRIPTION node. 113 * @return true, if description node is a description of in-line tag. 114 */ 115 private boolean isInlineDescription(DetailNode description) 116 { 117 DetailNode inlineTag = description.getParent(); 118 while (inlineTag != null) { 119 if (inlineTag.getType() == JavadocTokenTypes.JAVADOC_INLINE_TAG) { 120 return true; 121 } 122 inlineTag = inlineTag.getParent(); 123 } 124 return false; 125 } 126}