1 /* 2 * Copyright (c) 2011-2025 Yegor Bugayenko 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 1) Redistributions of source code must retain the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer. 2) Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following 12 * disclaimer in the documentation and/or other materials provided 13 * with the distribution. 3) Neither the name of the Qulice.com nor 14 * the names of its contributors may be used to endorse or promote 15 * products derived from this software without specific prior written 16 * permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 20 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 22 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 29 * OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 package com.qulice.checkstyle; 32 33 import com.puppycrawl.tools.checkstyle.api.AbstractCheck; 34 import com.puppycrawl.tools.checkstyle.api.DetailAST; 35 import com.puppycrawl.tools.checkstyle.api.TokenTypes; 36 import java.util.regex.Matcher; 37 import java.util.regex.Pattern; 38 39 /** 40 * C++ style inline comment is not allowed. 41 * Use //-style comment instead. 42 * @since 0.18 43 */ 44 public final class SingleLineCommentCheck extends AbstractCheck { 45 46 /** 47 * Pattern for check. 48 * It is not final as it is initialized from the configuration. 49 */ 50 private Pattern format = Pattern.compile("^$"); 51 52 /** 53 * The message to report for a match. 54 * It is not final as it is initialized from the configuration. 55 */ 56 private String message = ""; 57 58 /** 59 * Comment line. 60 * It is not final because the visitToken method is called many times 61 * during the class under test and the field is reinitialized with a new object. 62 */ 63 @SuppressWarnings("PMD.AvoidStringBufferField") 64 private StringBuilder line; 65 66 /** 67 * When inside a block comment, holds begin line number. 68 */ 69 private int begin; 70 71 @Override 72 public boolean isCommentNodesRequired() { 73 return true; 74 } 75 76 @Override 77 public int[] getDefaultTokens() { 78 return new int[]{ 79 TokenTypes.BLOCK_COMMENT_BEGIN, 80 TokenTypes.COMMENT_CONTENT, 81 TokenTypes.BLOCK_COMMENT_END, 82 }; 83 } 84 85 @Override 86 public int[] getAcceptableTokens() { 87 return this.getDefaultTokens(); 88 } 89 90 @Override 91 public int[] getRequiredTokens() { 92 return this.getDefaultTokens(); 93 } 94 95 @Override 96 public void visitToken(final DetailAST ast) { 97 if (ast.getType() == TokenTypes.BLOCK_COMMENT_BEGIN) { 98 this.line = new StringBuilder(ast.getText()); 99 this.begin = ast.getLineNo(); 100 } else if (ast.getType() == TokenTypes.COMMENT_CONTENT) { 101 this.line.append(ast.getText()); 102 } else { 103 this.line.append(ast.getText()); 104 final Matcher matcher = this.format.matcher(this.line.toString()); 105 if (matcher.matches() && this.singleLineCStyleComment(ast)) { 106 this.log(ast, this.message); 107 } 108 } 109 } 110 111 /** 112 * The method is called from checkstyle to configure this class. 113 * The parameter is set from the checks.xml file 114 * <module name="com.qulice.checkstyle.SingleLineCommentCheck"/> and 115 * <property name="format" value=" this regexp "/> property 116 * 117 * @param fmt Validatig regexp. 118 */ 119 public void setFormat(final String fmt) { 120 this.format = Pattern.compile(fmt); 121 } 122 123 /** 124 * The method is called from checkstyle to configure this class. 125 * The parameter is set from the checks.xml file 126 * <module name="com.qulice.checkstyle.SingleLineCommentCheck"/> and 127 * <property name="message" value="This kind of comment is not allowed."/> 128 * property 129 * 130 * @param msg Error message. 131 */ 132 public void setMessage(final String msg) { 133 this.message = msg; 134 } 135 136 /** 137 * Checks for the end of a comment line. 138 * @param ast Checkstyle's AST nodes. 139 * @return True if this is the end of the comment 140 * and the starting line number is equal to the ending line number. 141 */ 142 private boolean singleLineCStyleComment(final DetailAST ast) { 143 return ast.getType() == TokenTypes.BLOCK_COMMENT_END && this.begin == ast.getLineNo(); 144 } 145 }