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