001////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code for adherence to a set of rules.
003// Copyright (C) 2001-2020 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.CommonUtil;
027import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
028
029/**
030 * <p>Checks that chosen statements are not line-wrapped.
031 * By default this Check restricts wrapping import and package statements,
032 * but it's possible to check any statement.
033 * </p>
034 * <ul>
035 * <li>
036 * Property {@code tokens} - tokens to check
037 * Type is {@code int[]}.
038 * Default value is:
039 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#PACKAGE_DEF">
040 * PACKAGE_DEF</a>,
041 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#IMPORT">
042 * IMPORT</a>,
043 * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#STATIC_IMPORT">
044 * STATIC_IMPORT</a>.
045 * </li>
046 * </ul>
047 * <p>Examples of line-wrapped statements (bad case):
048 * </p>
049 * <pre>
050 * package com.puppycrawl. // violation
051 *     tools.checkstyle.checks;
052 *
053 * import com.puppycrawl.tools. // violation
054 *     checkstyle.api.AbstractCheck;
055 *
056 * import static java.math. // violation
057 *     BigInteger.ZERO;
058 * </pre>
059 *
060 * <p>
061 * To configure the check to force no line-wrapping
062 * in package and import statements (default values):
063 * </p>
064 * <pre>
065 * &lt;module name=&quot;NoLineWrap&quot;/&gt;
066 * </pre>
067 * <p>
068 * Examples:
069 * </p>
070 * <pre>
071 * package com.puppycrawl.tools.checkstyle. // violation
072 *   checks.whitespace;
073 *
074 * import java.lang.Object; // OK
075 * import java.lang. // violation
076 *   Integer;
077 *
078 * import static java.math. // violation
079 *   BigInteger.TEN;
080 * </pre>
081 * <pre>
082 * package com.puppycrawl.tools.checkstyle.checks.coding; // OK
083 *
084 * import java.lang. // violation
085 *   Boolean;
086 *
087 * import static java.math.BigInteger.ONE; // OK
088 * </pre>
089 *
090 * <p>
091 * To configure the check to force no line-wrapping only
092 * in import statements:
093 * </p>
094 * <pre>
095 * &lt;module name=&quot;NoLineWrap&quot;&gt;
096 *   &lt;property name="tokens" value="IMPORT"/&gt;
097 * &lt;/module&gt;
098 * </pre>
099 * <p>
100 * Example:
101 * </p>
102 * <pre>
103 * package com.puppycrawl. // OK
104 *   tools.checkstyle.checks;
105 *
106 * import java.io.*; // OK
107 * import java.lang. // violation
108 *  Boolean;
109 *
110 * import static java.math. // OK
111 * BigInteger.ZERO;
112 * </pre>
113 * <p>
114 * To configure the check to force no line-wrapping only
115 * in class, method and constructor definitions:
116 * </p>
117 * <pre>
118 * &lt;module name=&quot;NoLineWrap&quot;&gt;
119 *   &lt;property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF"/&gt;
120 * &lt;/module&gt;
121 * </pre>
122 * <p>
123 * Example:
124 * </p>
125 * <pre>
126 * public class // violation, class definition not wrapped in a single line
127 *   Foo {
128 *
129 *   public Foo() { // OK
130 *   }
131 *
132 *   public static void // violation, method definition not wrapped in a single line
133 *     doSomething() {
134 *   }
135 * }
136 *
137 * public class Bar { // OK
138 *
139 *   public // violation, constructor definition not wrapped in a single line
140 *     Bar() {
141 *   }
142 *
143 *   public int fun() { // OK
144 *   }
145 * }
146 * </pre>
147 *
148 * <p>Examples of not line-wrapped statements (good case):
149 * </p>
150 * <pre>
151 * import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
152 * import static java.math.BigInteger.ZERO;
153 * </pre>
154 * <p>
155 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker}
156 * </p>
157 * <p>
158 * Violation Message Keys:
159 * </p>
160 * <ul>
161 * <li>
162 * {@code no.line.wrap}
163 * </li>
164 * </ul>
165 *
166 * @since 5.8
167 */
168@StatelessCheck
169public class NoLineWrapCheck extends AbstractCheck {
170
171    /**
172     * A key is pointing to the warning message text in "messages.properties"
173     * file.
174     */
175    public static final String MSG_KEY = "no.line.wrap";
176
177    @Override
178    public int[] getDefaultTokens() {
179        return new int[] {TokenTypes.PACKAGE_DEF, TokenTypes.IMPORT, TokenTypes.STATIC_IMPORT};
180    }
181
182    @Override
183    public int[] getAcceptableTokens() {
184        return new int[] {
185            TokenTypes.IMPORT,
186            TokenTypes.STATIC_IMPORT,
187            TokenTypes.PACKAGE_DEF,
188            TokenTypes.CLASS_DEF,
189            TokenTypes.METHOD_DEF,
190            TokenTypes.CTOR_DEF,
191            TokenTypes.ENUM_DEF,
192            TokenTypes.INTERFACE_DEF,
193        };
194    }
195
196    @Override
197    public int[] getRequiredTokens() {
198        return CommonUtil.EMPTY_INT_ARRAY;
199    }
200
201    @Override
202    public void visitToken(DetailAST ast) {
203        if (!TokenUtil.areOnSameLine(ast, ast.getLastChild())) {
204            log(ast, MSG_KEY, ast.getText());
205        }
206    }
207
208}