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 delimiter 034 * position is either alone on its own line or on the same line as 035 * the block comment begin {@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 14.4.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 /** 089 * Creates a new {@code BlockCommentEndPositionCheck} instance. 090 */ 091 public BlockCommentEndPositionCheck() { 092 // no code by default 093 } 094 095 @Override 096 public int[] getRequiredTokens() { 097 return getAcceptableTokens(); 098 } 099 100 @Override 101 public int[] getAcceptableTokens() { 102 return new int[] { 103 TokenTypes.BLOCK_COMMENT_BEGIN, 104 }; 105 } 106 107 @Override 108 public int[] getDefaultTokens() { 109 return getAcceptableTokens(); 110 } 111 112 @Override 113 public boolean isCommentNodesRequired() { 114 return true; 115 } 116 117 /** 118 * Setter to specify the policy on strategy of the block comment end position. 119 * 120 * @param value string to decode strategy from 121 * @throws IllegalArgumentException if unable to decode 122 * @since 14.4.0 123 */ 124 public void setStrategy(String value) { 125 strategy = BlockCommentEndPositionOption.valueOf(value.trim().toUpperCase(Locale.ENGLISH)); 126 } 127 128 @Override 129 public void visitToken(DetailAST ast) { 130 final DetailAST lastChild = ast.getLastChild(); 131 if (JavadocUtil.isJavadocComment(ast) 132 && (strategy == BlockCommentEndPositionOption.ALONE 133 || !TokenUtil.areOnSameLine(ast, lastChild)) 134 && !isAlone(lastChild)) { 135 log(lastChild, MSG_BLOCK_COMMENT_END); 136 } 137 } 138 139 /** 140 * Checks whether the block comment end token is located alone on its own line. 141 * 142 * @param ast the block comment end token 143 * @return true if block comment end is alone 144 */ 145 private boolean isAlone(DetailAST ast) { 146 final String lineText = getLine(ast.getLineNo() - 1).trim(); 147 return lineText.startsWith("*/"); 148 } 149 150}