Repository: checkstyle/checkstyle

Problem statement:
EmptyLineSeparator flags commas for multiple single type variables on line
**Check documentation:** https://checkstyle.org/config_whitespace.html#EmptyLineSeparator

```

/var/tmp $ javac Test.java

/var/tmp $ cat Test.java
public class Test {
    int readOnly;
    int p01;
    int p11;
    int q01, q02, q03, q04, q05, q06, q07, q08;
 }


/var/tmp $ cat config.xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
        "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
        "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
  <module name="TreeWalker">
    <module name="EmptyLineSeparator">
      <property name="allowNoEmptyLineBetweenFields"
                value="true" />
    </module>
  </module>
</module>

/var/tmp $ RUN_LOCALE="-Duser.language=en -Duser.country=US"
/var/tmp $ java $RUN_LOCALE -jar checkstyle-8.36.jar -c config.xml Test.java
Starting audit...
[ERROR] /var/temp/Test.java:5:10: ',' should be separated from previous statement. [EmptyLineSeparator]
[ERROR] /var/temp/Test.java:5:15: ',' should be separated from previous statement. [EmptyLineSeparator]
[ERROR] /var/temp/Test.java:5:20: ',' should be separated from previous statement. [EmptyLineSeparator]
[ERROR] /var/temp/Test.java:5:25: ',' should be separated from previous statement. [EmptyLineSeparator]
[ERROR] /var/temp/Test.java:5:30: ',' should be separated from previous statement. [EmptyLineSeparator]
[ERROR] /var/temp/Test.java:5:35: ',' should be separated from previous statement. [EmptyLineSeparator]
[ERROR] /var/temp/Test.java:5:40: ',' should be separated from previous statement. [EmptyLineSeparator]
Audit done.
```

**Expected:** No violations.

        



Hints:

Patch:
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/EmptyLineSeparatorCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/EmptyLineSeparatorCheck.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/EmptyLineSeparatorCheck.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/EmptyLineSeparatorCheck.java
@@ -20,7 +20,6 @@
 package com.puppycrawl.tools.checkstyle.checks.whitespace;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
@@ -32,6 +31,7 @@
 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
 import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
+import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
 
 /**
  * <p>
@@ -166,6 +166,17 @@
  * </pre>
  *
  * <p>
+ * Example:
+ * </p>
+ *
+ * <pre>
+ * class Foo {
+ *   int field1; // ok
+ *   double field2; // ok
+ *   long field3, field4 = 10L, field5; // ok
+ * }
+ * </pre>
+ * <p>
  * Example of declarations with multiple empty lines between class members (allowed by default):
  * </p>
  *
@@ -319,11 +330,6 @@ public class EmptyLineSeparatorCheck extends AbstractCheck {
     public static final String MSG_MULTIPLE_LINES_INSIDE =
             "empty.line.separator.multiple.lines.inside";
 
-    /** List of AST token types, which can not have comment nodes to check inside. */
-    private static final List<Integer> TOKEN_TYPES_WITHOUT_COMMENTS_TO_CHECK_INSIDE =
-            Arrays.asList(TokenTypes.PACKAGE_DEF, TokenTypes.IMPORT, TokenTypes.STATIC_IMPORT,
-                    TokenTypes.STATIC_INIT);
-
     /** Allow no empty line between fields. */
     private boolean allowNoEmptyLineBetweenFields;
 
@@ -408,7 +414,7 @@ public void visitToken(DetailAST ast) {
             checkCommentInModifiers(ast);
         }
         DetailAST nextToken = ast.getNextSibling();
-        while (nextToken != null && isComment(nextToken)) {
+        while (isComment(nextToken)) {
             nextToken = nextToken.getNextSibling();
         }
         if (nextToken != null) {
@@ -486,11 +492,9 @@ private void processMultipleLinesInside(DetailAST ast) {
      * @return true if the AST is a class member block.
      */
     private static boolean isClassMemberBlock(int astType) {
-        return astType == TokenTypes.STATIC_INIT
-                || astType == TokenTypes.INSTANCE_INIT
-                || astType == TokenTypes.METHOD_DEF
-                || astType == TokenTypes.CTOR_DEF
-                || astType == TokenTypes.COMPACT_CTOR_DEF;
+        return TokenUtil.isOfType(astType,
+            TokenTypes.STATIC_INIT, TokenTypes.INSTANCE_INIT, TokenTypes.METHOD_DEF,
+            TokenTypes.CTOR_DEF, TokenTypes.COMPACT_CTOR_DEF);
     }
 
     /**
@@ -583,8 +587,8 @@ private void processPackage(DetailAST ast, DetailAST nextToken) {
      * @param nextToken next token
      */
     private void processImport(DetailAST ast, DetailAST nextToken) {
-        if (nextToken.getType() != TokenTypes.IMPORT
-                && nextToken.getType() != TokenTypes.STATIC_IMPORT && !hasEmptyLineAfter(ast)) {
+        if (!TokenUtil.isOfType(nextToken, TokenTypes.IMPORT, TokenTypes.STATIC_IMPORT)
+            && !hasEmptyLineAfter(ast)) {
             log(nextToken, MSG_SHOULD_BE_SEPARATED, nextToken.getText());
         }
     }
@@ -612,7 +616,7 @@ && isViolatingEmptyLineBetweenFieldsPolicy(nextToken)) {
     private boolean isViolatingEmptyLineBetweenFieldsPolicy(DetailAST detailAST) {
         return detailAST.getType() != TokenTypes.RCURLY
                 && (!allowNoEmptyLineBetweenFields
-                    || detailAST.getType() != TokenTypes.VARIABLE_DEF);
+                    || !TokenUtil.isOfType(detailAST, TokenTypes.COMMA, TokenTypes.VARIABLE_DEF));
     }
 
     /**
@@ -633,7 +637,9 @@ private boolean hasNotAllowedTwoEmptyLinesBefore(DetailAST token) {
      */
     private void checkComments(DetailAST token) {
         if (!allowMultipleEmptyLines) {
-            if (TOKEN_TYPES_WITHOUT_COMMENTS_TO_CHECK_INSIDE.contains(token.getType())) {
+            if (TokenUtil.isOfType(token,
+                TokenTypes.PACKAGE_DEF, TokenTypes.IMPORT,
+                TokenTypes.STATIC_IMPORT, TokenTypes.STATIC_INIT)) {
                 DetailAST previousNode = token.getPreviousSibling();
                 while (isCommentInBeginningOfLine(previousNode)) {
                     if (hasEmptyLineBefore(previousNode) && isPrePreviousLineEmpty(previousNode)) {
@@ -813,8 +819,8 @@ private static boolean isPrecededByJavadoc(DetailAST token) {
      * @return true, if given ast is comment.
      */
     private static boolean isComment(DetailAST ast) {
-        return ast.getType() == TokenTypes.SINGLE_LINE_COMMENT
-                   || ast.getType() == TokenTypes.BLOCK_COMMENT_BEGIN;
+        return TokenUtil.isOfType(ast,
+            TokenTypes.SINGLE_LINE_COMMENT, TokenTypes.BLOCK_COMMENT_BEGIN);
     }
 
     /**
@@ -824,9 +830,8 @@ private static boolean isComment(DetailAST ast) {
      * @return true variable definition is a type field.
      */
     private static boolean isTypeField(DetailAST variableDef) {
-        final int parentType = variableDef.getParent().getParent().getType();
-        return parentType == TokenTypes.CLASS_DEF
-                || parentType == TokenTypes.RECORD_DEF;
+        return TokenUtil.isOfType(variableDef.getParent().getParent(),
+             TokenTypes.CLASS_DEF, TokenTypes.RECORD_DEF);
     }
 
 }


Test patch:
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/EmptyLineSeparatorCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/EmptyLineSeparatorCheckTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/EmptyLineSeparatorCheckTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/EmptyLineSeparatorCheckTest.java
@@ -474,4 +474,16 @@ public void testEmptyLineSeparatorRecordsAndCompactCtorsNoEmptyLines() throws Ex
                 expected);
     }
 
+    @Test
+    public void testEmptyLineSeparatorMultipleSingleTypeVariables() throws Exception {
+        final DefaultConfiguration checkConfig = createModuleConfig(EmptyLineSeparatorCheck.class);
+        checkConfig.addAttribute("allowNoEmptyLineBetweenFields", "true");
+
+        final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
+
+        verify(checkConfig,
+                getPath("InputEmptyLineSeparatorSingleTypeVariables.java"),
+                expected);
+    }
+
 }
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/emptylineseparator/InputEmptyLineSeparator.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/emptylineseparator/InputEmptyLineSeparator.java
--- a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/emptylineseparator/InputEmptyLineSeparator.java
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/emptylineseparator/InputEmptyLineSeparator.java
@@ -151,3 +151,7 @@ public int compareTo(InputEmptyLineSeparator aObject) //ok
         }
     };
 }
+
+class Class3 {
+    int field;
+}
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/emptylineseparator/InputEmptyLineSeparatorSingleTypeVariables.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/emptylineseparator/InputEmptyLineSeparatorSingleTypeVariables.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/whitespace/emptylineseparator/InputEmptyLineSeparatorSingleTypeVariables.java
@@ -0,0 +1,33 @@
+////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code for adherence to a set of rules.
+// Copyright (C) 2001-2020 the original author or authors.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+////////////////////////////////////////////////////////////////////////////////
+
+package com.puppycrawl.tools.checkstyle.checks.whitespace.emptylineseparator;
+
+/*
+ * Config:
+ * allowNoEmptyLineBetweenFields = true
+ */
+
+public class InputEmptyLineSeparatorSingleTypeVariables {
+    int a; // ok
+    int b; // ok
+    int c; // ok
+    int a1, b1, c1; // ok
+
+}