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.whitespace;
021
022import java.util.List;
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;
029
030/**
031 * <div>
032 * Checks that all lines in a multi-line block comment start with
033 * a leading asterisk (*), as required by the
034 * <a href="https://google.github.io/styleguide/javaguide.html#s4.8.6-comments">
035 * Google Java Style Guide ยง4.8.6</a>.
036 * </div>
037 *
038 * <p>
039 * For multi-line block comments, subsequent lines must start with * aligned
040 * with the * on the previous line. This check does not apply to single-line
041 * block comments (&#47;* comment *&#47;).
042 * </p>
043 *
044 * <p>
045 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker}
046 * </p>
047 *
048 * <p>
049 * Violation Message Keys:
050 * </p>
051 * <ul>
052 * <li>
053 * {@code multiline.comment.missing.asterisk}
054 * </li>
055 * </ul>
056 *
057 * @since 13.3.0
058 */
059@StatelessCheck
060public class MultilineCommentLeadingAsteriskPresenceCheck extends AbstractCheck {
061
062    /**
063     * A key is pointing to the warning message text in "messages.properties"
064     * file.
065     */
066    public static final String MSG_MISSING_ASTERISK = "multiline.comment.missing.asterisk";
067
068    @Override
069    public int[] getDefaultTokens() {
070        return getRequiredTokens();
071    }
072
073    @Override
074    public int[] getAcceptableTokens() {
075        return getRequiredTokens();
076    }
077
078    @Override
079    public int[] getRequiredTokens() {
080        return new int[] {
081            TokenTypes.BLOCK_COMMENT_BEGIN,
082        };
083    }
084
085    @Override
086    public boolean isCommentNodesRequired() {
087        return true;
088    }
089
090    @Override
091    public void visitToken(DetailAST ast) {
092        // Skip Javadoc comments - only check regular block comments
093        if (!JavadocUtil.isJavadocComment(ast)) {
094            final String commentText = ast.getFirstChild().getText();
095            checkCommentLines(ast, commentText);
096        }
097    }
098
099    /**
100     * Checks each line of the comment for leading asterisks.
101     *
102     * @param ast the block comment AST node
103     * @param commentText the text of the comment
104     */
105    private void checkCommentLines(DetailAST ast, String commentText) {
106        final List<String> lines = commentText.lines().toList();
107
108        for (int cur = 1; cur < lines.size(); cur++) {
109            final String trimmedLine = lines.get(cur).trim();
110
111            if (!trimmedLine.isEmpty() && !trimmedLine.startsWith("*")) {
112                log(ast, MSG_MISSING_ASTERISK);
113                break;
114            }
115        }
116    }
117}