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" file. 043 */ 044 public static final String MSG_KEY = "no.line.wrap"; 045 046 /** 047 * Property that defines whether annotations on the previous line should be 048 * checked as violation. 049 */ 050 private boolean skipAnnotations = true; 051 052 /** 053 * Creates a new {@code NoLineWrapCheck} instance. 054 */ 055 public NoLineWrapCheck() { 056 // no code by default 057 } 058 059 /** 060 * Setter to specify whether to skip annotations to be part of target token. 061 * 062 * @param shouldSkipAnnotations whether to skip annotations to be part of target token. 063 * @since 13.9.0 064 */ 065 public void setSkipAnnotations(boolean shouldSkipAnnotations) { 066 skipAnnotations = shouldSkipAnnotations; 067 } 068 069 @Override 070 public int[] getDefaultTokens() { 071 return new int[] { 072 TokenTypes.PACKAGE_DEF, 073 TokenTypes.IMPORT, 074 TokenTypes.STATIC_IMPORT, 075 TokenTypes.MODULE_IMPORT, 076 TokenTypes.MODULE_DEF, 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 TokenTypes.MODULE_DEF, 095 }; 096 } 097 098 @Override 099 public int[] getRequiredTokens() { 100 return CommonUtil.EMPTY_INT_ARRAY; 101 } 102 103 @Override 104 public void visitToken(DetailAST ast) { 105 DetailAST detailAST = ast; 106 if (skipAnnotations && AnnotationUtil.containsAnnotation(ast)) { 107 detailAST = AnnotationUtil.getAnnotationHolder(ast).getNextSibling(); 108 } 109 if (!TokenUtil.areOnSameLine(detailAST, ast.getLastChild())) { 110 log(ast, MSG_KEY, ast.getText()); 111 } 112 } 113 114}