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 com.puppycrawl.tools.checkstyle.StatelessCheck; 023import com.puppycrawl.tools.checkstyle.api.AbstractCheck; 024import com.puppycrawl.tools.checkstyle.api.DetailAST; 025import com.puppycrawl.tools.checkstyle.api.TokenTypes; 026import com.puppycrawl.tools.checkstyle.utils.AnnotationUtil; 027import com.puppycrawl.tools.checkstyle.utils.CommonUtil; 028import com.puppycrawl.tools.checkstyle.utils.TokenUtil; 029 030/** 031 * <div>Checks that chosen statements are not line-wrapped. 032 * By default, this Check restricts wrapping import and package statements, 033 * but it's possible to check any statement. 034 * </div> 035 * 036 * @since 5.8 037 */ 038@StatelessCheck 039public class NoLineWrapCheck extends AbstractCheck { 040 041 /** 042 * A key is pointing to the warning message text in "messages.properties" 043 * file. 044 */ 045 public static final String MSG_KEY = "no.line.wrap"; 046 047 /** 048 * Property that defines whether annotations on the previous line should be 049 * checked as violation. 050 */ 051 private boolean skipAnnotations = true; 052 053 /** 054 * Creates a new {@code NoLineWrapCheck} instance. 055 */ 056 public NoLineWrapCheck() { 057 // no code by default 058 } 059 060 /** 061 * Setter to specify whether to skip annotations to be part of target token. 062 * 063 * @param shouldSkipAnnotations whether to skip annotations to be part of target token. 064 * @since 13.9.0 065 */ 066 public void setSkipAnnotations(boolean shouldSkipAnnotations) { 067 skipAnnotations = shouldSkipAnnotations; 068 } 069 070 @Override 071 public int[] getDefaultTokens() { 072 return new int[] { 073 TokenTypes.PACKAGE_DEF, 074 TokenTypes.IMPORT, 075 TokenTypes.STATIC_IMPORT, 076 TokenTypes.MODULE_IMPORT, 077 }; 078 } 079 080 @Override 081 public int[] getAcceptableTokens() { 082 return new int[] { 083 TokenTypes.IMPORT, 084 TokenTypes.STATIC_IMPORT, 085 TokenTypes.MODULE_IMPORT, 086 TokenTypes.PACKAGE_DEF, 087 TokenTypes.CLASS_DEF, 088 TokenTypes.METHOD_DEF, 089 TokenTypes.CTOR_DEF, 090 TokenTypes.ENUM_DEF, 091 TokenTypes.INTERFACE_DEF, 092 TokenTypes.RECORD_DEF, 093 TokenTypes.COMPACT_CTOR_DEF, 094 }; 095 } 096 097 @Override 098 public int[] getRequiredTokens() { 099 return CommonUtil.EMPTY_INT_ARRAY; 100 } 101 102 @Override 103 public void visitToken(DetailAST ast) { 104 DetailAST detailAST = ast; 105 if (skipAnnotations && AnnotationUtil.containsAnnotation(ast)) { 106 detailAST = AnnotationUtil.getAnnotationHolder(ast).getNextSibling(); 107 } 108 if (!TokenUtil.areOnSameLine(detailAST, ast.getLastChild())) { 109 log(ast, MSG_KEY, ast.getText()); 110 } 111 } 112 113}