001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2026 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.Locale; 023 024import com.puppycrawl.tools.checkstyle.StatelessCheck; 025import com.puppycrawl.tools.checkstyle.api.AbstractCheck; 026import com.puppycrawl.tools.checkstyle.api.DetailAST; 027import com.puppycrawl.tools.checkstyle.api.TokenTypes; 028import com.puppycrawl.tools.checkstyle.utils.JavadocUtil; 029import com.puppycrawl.tools.checkstyle.utils.TokenUtil; 030 031/** 032 * <div> 033 * Checks that the Javadoc block comment end <code class="language-java">*/</code> 034 * position is either alone on its own line or on the same line as 035 * the block comment begin code <code class="language-java">/**</code>. 036 * </div> 037 * 038 * <p> 039 * It is possible to enforce two different strategies: 040 * </p> 041 * <ul> 042 * <li> 043 * {@code alone} - The block comment end must be alone on its own line. 044 * This allows only multi-line Javadoc comments: 045 * <div class="wrapper"><pre class="prettyprint"><code class="language-java"> 046 * /** 047 * * Multiple lines of Javadoc text are written here, 048 * * wrapped normally... 049 * */ 050 * public void method(); 051 * </code></pre></div> 052 * </li> 053 * <li> 054 * {@code alone_or_singleline} - The block comment end must be either 055 * alone on its own line or on the same line as the block comment begin. 056 * This allows multi-line Javadoc as well as single-line Javadoc comments: 057 * <div class="wrapper"><pre class="prettyprint"><code class="language-java"> 058 * // Block comment end is alone on its own line 059 * /** 060 * * Multiple lines of Javadoc text are written here, 061 * * wrapped normally... 062 * */ 063 * public void method(); 064 * 065 * // Single-line Javadoc 066 * /** Javadoc summary. */ 067 * public void method1(); 068 * </code></pre></div> 069 * </li> 070 * </ul> 071 * 072 * @since 13.3.0 073 */ 074@StatelessCheck 075public class BlockCommentEndPositionCheck extends AbstractCheck { 076 077 /** 078 * A key is pointing to the warning message text in "messages.properties" file. 079 */ 080 public static final String MSG_BLOCK_COMMENT_END = "block.comment.end"; 081 082 /** 083 * Specify the strategy policy for the block comment end position. 084 */ 085 private BlockCommentEndPositionOption strategy = 086 BlockCommentEndPositionOption.ALONE_OR_SINGLELINE; 087 088 @Override 089 public int[] getRequiredTokens() { 090 return new int[] { 091 TokenTypes.BLOCK_COMMENT_BEGIN, 092 }; 093 } 094 095 @Override 096 public int[] getAcceptableTokens() { 097 return getRequiredTokens(); 098 } 099 100 @Override 101 public int[] getDefaultTokens() { 102 return getRequiredTokens(); 103 } 104 105 @Override 106 public boolean isCommentNodesRequired() { 107 return true; 108 } 109 110 /** 111 * Setter to specify the policy on strategy of the block comment end position. 112 * 113 * @param value string to decode strategy from 114 * @throws IllegalArgumentException if unable to decode 115 * @since 13.3.0 116 */ 117 public void setStrategy(String value) { 118 strategy = BlockCommentEndPositionOption.valueOf(value.trim().toUpperCase(Locale.ENGLISH)); 119 } 120 121 @Override 122 public void visitToken(DetailAST ast) { 123 final DetailAST lastChild = ast.getLastChild(); 124 if (JavadocUtil.isJavadocComment(ast) 125 && (strategy == BlockCommentEndPositionOption.ALONE 126 || !TokenUtil.areOnSameLine(ast, lastChild)) 127 && !isAlone(lastChild)) { 128 log(lastChild, MSG_BLOCK_COMMENT_END, "BLOCK_COMMENT_END"); 129 } 130 } 131 132 /** 133 * Checks whether the block comment end token is located alone on its own line. 134 * 135 * @param ast the block comment end token 136 * @return true if block comment end is alone 137 */ 138 private boolean isAlone(DetailAST ast) { 139 final String lineText = getLine(ast.getLineNo() - 1).trim(); 140 return "*/".equals(lineText); 141 } 142}