Repository: checkstyle/checkstyle

Problem statement:
checkstyle 10.3.3 and newer throws NullPointerException on annotated generic types from IllegalType rule
I minimized my repro to narrow down the cause.

The config:

`❯ /bin/cat checkstyle-configuration.xml`

```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="IllegalType">
            <property name="illegalClassNames"
                    value="java.lang.StringBuffer, " />
        </module>
    </module>
</module>
```

The code:

`❯ cat ExampleClass.java`

```java
package com.example;

import java.util.List;

import javax.validation.constraints.Pattern;

public class ExampleClass
{
    public void example(List<@Pattern String> strings)
    {
    }
}
```

```bash
❯ RUN_LOCALE="-Duser.language=en -Duser.country=US"
❯ java $RUN_LOCALE -jar checkstyle-10.3.3-all.jar -c checkstyle-configuration.xml ExampleClass.java 
Starting audit...
com.puppycrawl.tools.checkstyle.api.CheckstyleException: Exception was thrown while processing ExampleClass.java
	at com.puppycrawl.tools.checkstyle.Checker.processFiles(Checker.java:307)
	at com.puppycrawl.tools.checkstyle.Checker.process(Checker.java:224)
	at com.puppycrawl.tools.checkstyle.Main.runCheckstyle(Main.java:416)
	at com.puppycrawl.tools.checkstyle.Main.runCli(Main.java:339)
	at com.puppycrawl.tools.checkstyle.Main.execute(Main.java:196)
	at com.puppycrawl.tools.checkstyle.Main.main(Main.java:131)
Caused by: java.lang.NullPointerException: Cannot invoke "com.puppycrawl.tools.checkstyle.api.DetailAST.getLineNo()" because "ast" is null
	at com.puppycrawl.tools.checkstyle.api.AbstractCheck.log(AbstractCheck.java:276)
	at com.puppycrawl.tools.checkstyle.checks.coding.IllegalTypeCheck.checkIdent(IllegalTypeCheck.java:645)
	at com.puppycrawl.tools.checkstyle.checks.coding.IllegalTypeCheck.checkType(IllegalTypeCheck.java:674)
	at com.puppycrawl.tools.checkstyle.utils.TokenUtil.forEachChild(TokenUtil.java:244)
	at com.puppycrawl.tools.checkstyle.checks.coding.IllegalTypeCheck.checkTypeArguments(IllegalTypeCheck.java:719)
	at com.puppycrawl.tools.checkstyle.checks.coding.IllegalTypeCheck.checkType(IllegalTypeCheck.java:675)
	at com.puppycrawl.tools.checkstyle.checks.coding.IllegalTypeCheck.checkClassName(IllegalTypeCheck.java:633)
	at com.puppycrawl.tools.checkstyle.checks.coding.IllegalTypeCheck.visitParameterDef(IllegalTypeCheck.java:563)
	at com.puppycrawl.tools.checkstyle.checks.coding.IllegalTypeCheck.visitToken(IllegalTypeCheck.java:478)
	at com.puppycrawl.tools.checkstyle.TreeWalker.notifyVisit(TreeWalker.java:336)
	at com.puppycrawl.tools.checkstyle.TreeWalker.processIter(TreeWalker.java:407)
	at com.puppycrawl.tools.checkstyle.TreeWalker.walk(TreeWalker.java:274)
	at com.puppycrawl.tools.checkstyle.TreeWalker.processFiltered(TreeWalker.java:155)
	at com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck.process(AbstractFileSetCheck.java:98)
	at com.puppycrawl.tools.checkstyle.Checker.processFile(Checker.java:335)
	at com.puppycrawl.tools.checkstyle.Checker.processFiles(Checker.java:294)
	... 5 more
Checkstyle ends with 1 errors.

❯ java $RUN_LOCALE -jar checkstyle-10.3.2-all.jar -c checkstyle-configuration.xml ExampleClass.java
Starting audit...
Audit done.
```


---

Note that any little change to the config file prevents this problem. Even getting rid of the trailing comma or space at the end of StringBuffer in `<property name="illegalClassNames" value="java.lang.StringBuffer, " />` prevents the problem.

---





Hints:
This issue is tied to https://github.com/checkstyle/checkstyle/issues/12017 and commits https://github.com/checkstyle/checkstyle/commit/308001394030b0ba52921dd8f1b0bef22c90ea83 and https://github.com/checkstyle/checkstyle/commit/01b7de64e59c5932a13f4936c2f2355bb56603ec and PRs https://github.com/checkstyle/checkstyle/pull/12034 and https://github.com/checkstyle/checkstyle/pull/12035.

Rationale was `No need to trim strings here, they are trimmed further down in the method`.

It appears it was not taken into account to have an extra comma on the end with an empty space. There is no exception if there is just an extra comma. The exception comes in when there is a space after the comma.

It is not user friendly to throw an exception. I think we should restore the code and drop the remaining empty item.
We should restore trim.
As we do for all other.

Example: https://github.com/checkstyle/checkstyle/pull/12258
On it

Patch:
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java
@@ -361,7 +361,7 @@ private static class RelaxedStringArrayConverter implements Converter {
         @Override
         public Object convert(Class type, Object value) {
             final StringTokenizer tokenizer = new StringTokenizer(
-                value.toString(), COMMA_SEPARATOR);
+                value.toString().trim(), COMMA_SEPARATOR);
             final List<String> result = new ArrayList<>();
 
             while (tokenizer.hasMoreTokens()) {
@@ -390,7 +390,7 @@ private static class RelaxedAccessModifierArrayConverter implements Converter {
         public Object convert(Class type, Object value) {
             // Converts to a String and trims it for the tokenizer.
             final StringTokenizer tokenizer = new StringTokenizer(
-                value.toString(), COMMA_SEPARATOR);
+                value.toString().trim(), COMMA_SEPARATOR);
             final List<AccessModifierOption> result = new ArrayList<>();
 
             while (tokenizer.hasMoreTokens()) {


Test patch:
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalTypeCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalTypeCheckTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalTypeCheckTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalTypeCheckTest.java
@@ -389,6 +389,14 @@ public void testRecordComponentsPublicProtectedStatic() throws Exception {
                 expected);
     }
 
+    @Test
+    public void testTrailingWhitespaceInConfig() throws Exception {
+        final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
+        verifyWithInlineConfigParser(
+                getPath("InputIllegalTypeWhitespaceInConfig.java"),
+                expected);
+    }
+
     @Test
     public void testTokensNotNull() {
         final IllegalTypeCheck check = new IllegalTypeCheck();
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/naming/ParameterNameCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/naming/ParameterNameCheckTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/naming/ParameterNameCheckTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/naming/ParameterNameCheckTest.java
@@ -178,4 +178,11 @@ public void testLambdaParameterNoViolationAtAll() throws Exception {
                 getPath("InputParameterNameLambda.java"), expected);
     }
 
+    @Test
+    public void testWhitespaceInConfig() throws Exception {
+        final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
+        verifyWithInlineConfigParser(
+                getPath("InputParameterNameWhitespaceInConfig.java"), expected);
+    }
+
 }
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/illegaltype/InputIllegalTypeWhitespaceInConfig.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/illegaltype/InputIllegalTypeWhitespaceInConfig.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/illegaltype/InputIllegalTypeWhitespaceInConfig.java
@@ -0,0 +1,28 @@
+/*
+IllegalType
+validateAbstractClassNames = (default)false
+illegalClassNames = java.lang.StringBuffer,\t
+legalAbstractClassNames = (default)
+ignoredMethodNames = (default)getEnvironment, getInitialContext
+illegalAbstractClassNameFormat = (default)^(.*[.])?Abstract.*$
+memberModifiers = (default)
+tokens = (default)ANNOTATION_FIELD_DEF, CLASS_DEF, INTERFACE_DEF, METHOD_CALL, METHOD_DEF, \
+         METHOD_REF, PARAMETER_DEF, VARIABLE_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF, \
+         RECORD_COMPONENT_DEF
+
+
+*/
+package com.puppycrawl.tools.checkstyle.checks.coding.illegaltype;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.util.List;
+
+public class InputIllegalTypeWhitespaceInConfig {
+    public void example(List<@MyPattern String> strings) { // ok
+    }
+
+    @Target(ElementType.TYPE_USE)
+    public @interface MyPattern {}
+}
+
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/naming/parametername/InputParameterNameWhitespaceInConfig.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/naming/parametername/InputParameterNameWhitespaceInConfig.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/naming/parametername/InputParameterNameWhitespaceInConfig.java
@@ -0,0 +1,14 @@
+/*
+ParameterName
+format = (default)^[a-z][a-zA-Z0-9]*$
+ignoreOverridden = (default)false
+accessModifiers = public\t,\t
+
+
+*/
+
+package com.puppycrawl.tools.checkstyle.checks.naming.parametername;
+
+public class InputParameterNameWhitespaceInConfig {
+    int method(){return 1;} // ok
+}