Repository: checkstyle/checkstyle

Problem statement:
google_checks.xml: remove xpath suppression and false-positive indentation violations for block codes
I have read check documentation: https://checkstyle.org/checks/misc/indentation.html
I have downloaded the latest checkstyle from: https://checkstyle.org/cmdline.html#Download_and_Run
I have executed the cli and showed it below, as cli describes the problem better than 1,000 words

Detected at https://github.com/checkstyle/checkstyle/issues/14294

In [google_checks.xml](https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml), [Indentation](https://checkstyle.org/checks/misc/indentation.html) module gives false-positive error for following type of blocks:

```
{
  int x = 99;
}
```


**Example:**

```java
/** Test... */
public class Test {
  private static void indentationIssue(int condition) {
    { // line 4, false-positive
      System.out.println("True");
    } // line 6, false-positive
  }

  { // good, no violation
    System.out.println("False");
  } // good, no violation

    { // line 13, expected
      System.out.println("False");
    } // line 15, expected

  class Inner {
    void test() {
      { // line 19, false-positive
        System.out.println("True");
      } // line 21, false-positive
    }
  }
}
```

```
$ java -jar .\checkstyle-10.18.2-all.jar -c .\google_checks.xml .\Test.java
Starting audit...
[WARN] C:\checkstyle testing\.\Test.java:4:5: 'block lcurly' has incorrect indentation level 4, expected level should be 6. [Indentation]
[WARN] C:\checkstyle testing\.\Test.java:6:5: 'block rcurly' has incorrect indentation level 4, expected level should be 6. [Indentation]
[WARN] C:\checkstyle testing\.\Test.java:13:5: 'block lcurly' has incorrect indentation level 4, expected level should be 2. [Indentation]
[WARN] C:\checkstyle testing\.\Test.java:14:7: 'block' child has incorrect indentation level 6, expected level should be 4. [Indentation]
[WARN] C:\checkstyle testing\.\Test.java:15:5: 'block rcurly' has incorrect indentation level 4, expected level should be 2. [Indentation]
[WARN] C:\checkstyle testing\.\Test.java:19:7: 'block lcurly' has incorrect indentation level 6, expected level should be 8. [Indentation]
[WARN] C:\checkstyle testing\.\Test.java:21:7: 'block rcurly' has incorrect indentation level 6, expected level should be 8. [Indentation]
Audit done.
```

@romani suggested to use suppression to suppress these false-positives until we find a way to fix it at: https://github.com/checkstyle/checkstyle/issues/14294#issuecomment-2408353743

The suppression is:

```xml
    <module name="SuppressionXpathSingleFilter">
      <property name="checks" value="Indentation"/>
      <property name="query" value="//SLIST/SLIST"/>
    </module>
    <module name="SuppressionXpathSingleFilter">
      <property name="checks" value="Indentation"/>
      <property name="query" value="//SLIST/SLIST/RCURLY"/>
    </module>
    <module name="Indentation">
      <property name="basicOffset" value="2"/>
      <property name="braceAdjustment" value="2"/>
      <property name="caseIndent" value="2"/>
      <property name="throwsIndent" value="4"/>
      <property name="lineWrappingIndentation" value="4"/>
      <property name="arrayInitIndent" value="2"/>
    </module>
```

Adding this suppression will suppress all indentation violations for above mentioned type of blocks whether they're correct or not but we need to use it till we find a fix.

---

As part of this issue, we need to find a way to fix this false-positive and remove the suppression. 


Hints:
I am on it

Patch:
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/BlockParentHandler.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/BlockParentHandler.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/BlockParentHandler.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/BlockParentHandler.java
@@ -157,14 +157,23 @@ private void checkLeftCurly() {
     protected IndentLevel curlyIndent() {
         final DetailAST lcurly = getLeftCurly();
         IndentLevel expIndentLevel = new IndentLevel(getIndent(), getBraceAdjustment());
-        if (!isOnStartOfLine(lcurly)
-            || lcurly.getParent().getType() == TokenTypes.INSTANCE_INIT) {
+        if (!isOnStartOfLine(lcurly) || checkIfCodeBlock()) {
             expIndentLevel = new IndentLevel(getIndent(), 0);
         }
-
         return expIndentLevel;
     }
 
+    /**
+     * Checks if lcurly is a Code block.
+     *
+     * @return true if lcurly is a code block
+     */
+    private boolean checkIfCodeBlock() {
+        return getMainAst().getType() == TokenTypes.SLIST
+                && getParent() instanceof BlockParentHandler
+                && getParent().getParent() instanceof BlockParentHandler;
+    }
+
     /**
      * Determines if child elements within the expression may be nested.
      *


Test patch:
diff --git a/src/it/resources-noncompilable/com/google/checkstyle/test/chapter5naming/rule527localvariablenames/InputPatternVariableNameEnhancedInstanceofTestDefault.java b/src/it/resources-noncompilable/com/google/checkstyle/test/chapter5naming/rule527localvariablenames/InputPatternVariableNameEnhancedInstanceofTestDefault.java
--- a/src/it/resources-noncompilable/com/google/checkstyle/test/chapter5naming/rule527localvariablenames/InputPatternVariableNameEnhancedInstanceofTestDefault.java
+++ b/src/it/resources-noncompilable/com/google/checkstyle/test/chapter5naming/rule527localvariablenames/InputPatternVariableNameEnhancedInstanceofTestDefault.java
@@ -70,17 +70,17 @@ public void testing(Object o1, Object o2) {
       System.out.println("done");
     }
 
-      {
-        while (!(o1 instanceof String _aa)) {
-          // violation above 'Pattern variable name '_aa' must match pattern'
-          L3:
-          break L3;
-        }
-        while (o1 instanceof String aa_) {
-          // violation above 'Pattern variable name 'aa_' must match pattern'
-          aa_.length();
-        }
+    {
+      while (!(o1 instanceof String _aa)) {
+        // violation above 'Pattern variable name '_aa' must match pattern'
+        L3:
+        break L3;
       }
+      while (o1 instanceof String aa_) {
+        // violation above 'Pattern variable name 'aa_' must match pattern'
+        aa_.length();
+      }
+    }
 
     int x = o1 instanceof String aaa$aaa ? aaa$aaa.length() : 2;
     // violation above 'Pattern variable name .* must match pattern'
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java
@@ -3155,6 +3155,43 @@ public void testIndentationRecordPattern()
         verifyWarns(checkConfig, fileName, expected);
     }
 
+    @Test
+    public void testIndentationCodeBlocks1() throws Exception {
+        final DefaultConfiguration checkConfig = createModuleConfig(IndentationCheck.class);
+        checkConfig.addProperty("tabWidth", "4");
+        checkConfig.addProperty("basicOffset", "2");
+        checkConfig.addProperty("braceAdjustment", "2");
+        checkConfig.addProperty("caseIndent", "2");
+        checkConfig.addProperty("throwsIndent", "4");
+        checkConfig.addProperty("lineWrappingIndentation", "4");
+        final String[] expected = {
+            "17:5: " + getCheckMessage(MSG_ERROR, "block lcurly", 4, 2),
+            "18:7: " + getCheckMessage(MSG_CHILD_ERROR, "block", 6, 4),
+            "19:5: " + getCheckMessage(MSG_ERROR, "block rcurly", 4, 2),
+            "30:5: " + getCheckMessage(MSG_ERROR, "block lcurly", 4, 2),
+            "31:7: " + getCheckMessage(MSG_CHILD_ERROR, "block", 6, 4),
+            "32:5: " + getCheckMessage(MSG_ERROR, "block rcurly", 4, 2),
+        };
+        verifyWarns(checkConfig, getPath("InputIndentationCodeBlocks1.java"), expected);
+    }
+
+    @Test
+    public void testIndentationCodeBlocks2() throws Exception {
+        final DefaultConfiguration checkConfig = createModuleConfig(IndentationCheck.class);
+        checkConfig.addProperty("tabWidth", "4");
+        checkConfig.addProperty("basicOffset", "2");
+        checkConfig.addProperty("braceAdjustment", "2");
+        checkConfig.addProperty("throwsIndent", "4");
+        checkConfig.addProperty("caseIndent", "2");
+        checkConfig.addProperty("lineWrappingIndentation", "4");
+        final String[] expected = {
+            "45:13: " + getCheckMessage(MSG_ERROR, "for lcurly", 12, 14),
+            "47:13: " + getCheckMessage(MSG_ERROR, "for rcurly", 12, 14),
+        };
+        verifyWarns(checkConfig,
+                getNonCompilablePath("InputIndentationCodeBlocks2.java"), expected);
+    }
+
     @Test
     public void testIndentationSealedClasses()
             throws Exception {
diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationCodeBlocks2.java b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationCodeBlocks2.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationCodeBlocks2.java
@@ -0,0 +1,63 @@
+
+//non-compiled with javac: Compilable with Java17                                   //indent:0 exp:0
+
+/* Config:                                                                  //indent:0 exp:0
+ * This test-input is intended to be checked using following configuration: //indent:1 exp:1
+ *                                                                          //indent:1 exp:1
+ * basicOffset = 2                                                          //indent:1 exp:1
+ * braceAdjustment = 2                                                      //indent:1 exp:1
+ * caseIndent = 2                                                           //indent:1 exp:1
+ * lineWrappingIndentation = 4                                              //indent:1 exp:1
+ * throwsIndent = 4                                                         //indent:1 exp:1
+ */                                                                         //indent:1 exp:1
+
+package com.puppycrawl.tools.checkstyle.checks.indentation.indentation;     //indent:0 exp:0
+
+public class InputIndentationCodeBlocks2 {                                  //indent:0 exp:0
+  public void testSwitchCases(int j) {                                      //indent:2 exp:2
+    switch (j) {                                                            //indent:4 exp:4
+      case 1:                                                               //indent:6 exp:6
+        {                                                                   //indent:8 exp:8
+          System.out.println("One");                                        //indent:10 exp:10
+          break;                                                            //indent:10 exp:10
+        }                                                                   //indent:8 exp:8
+      case 2:                                                               //indent:6 exp:6
+        {                                                                   //indent:8 exp:8
+          System.out.println("2");                                          //indent:10 exp:10
+          break;                                                            //indent:10 exp:10
+        }                                                                   //indent:8 exp:8
+      default:                                                              //indent:6 exp:6
+        System.out.println("default");                                      //indent:8 exp:8
+    }                                                                       //indent:4 exp:4
+    final int status =                                                      //indent:4 exp:4
+        switch (j) {                                                        //indent:8 exp:8
+          case 1 -> 502;                                                    //indent:10 exp:10
+          case 10 -> 502;                                                   //indent:10 exp:10
+          case 110 -> 504;                                                  //indent:10 exp:10
+          default -> 500;                                                   //indent:10 exp:10
+        };                                                                  //indent:8 exp:8
+
+    switch (j) {                                                            //indent:4 exp:4
+      case 2:                                                               //indent:6 exp:6
+        if (status + 10 > 100) {                                            //indent:8 exp:8
+          {                                                                 //indent:10 exp:10
+            for (int _i1 = 0; _i1 < -5; ++_i1)                              //indent:12 exp:12
+            {                                                               //indent:12 exp:14 warn
+              System.out.println("sout");                                   //indent:14 exp:14
+            }                                                               //indent:12 exp:14 warn
+          }                                                                 //indent:10 exp:10
+        } else {                                                            //indent:8 exp:8
+          System.out.println("souta");                                      //indent:10 exp:10
+        }                                                                   //indent:8 exp:8
+    }                                                                       //indent:4 exp:4
+
+    if (j < -1) {                                                           //indent:4 exp:4
+      {                                                                     //indent:6 exp:6
+        for (int i = 0; i < 1; i++)                                         //indent:8 exp:8
+          {                                                                 //indent:10 exp:10
+            System.out.println("sout");                                     //indent:12 exp:12
+          }                                                                 //indent:10 exp:10
+      }                                                                     //indent:6 exp:6
+    }                                                                       //indent:4 exp:4
+  }                                                                         //indent:2 exp:2
+}                                                                           //indent:0 exp:0
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationCodeBlocks1.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationCodeBlocks1.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationCodeBlocks1.java
@@ -0,0 +1,58 @@
+/* Config:                                                                  //indent:0 exp:0
+ * This test-input is intended to be checked using following configuration: //indent:1 exp:1
+ *                                                                          //indent:1 exp:1
+ * basicOffset = 2                                                          //indent:1 exp:1
+ * braceAdjustment = 2                                                      //indent:1 exp:1
+ * caseIndent = 2                                                           //indent:1 exp:1
+ * lineWrappingIndentation = 4                                              //indent:1 exp:1
+ * throwsIndent = 4                                                         //indent:1 exp:1
+ */                                                                         //indent:1 exp:1
+
+package com.puppycrawl.tools.checkstyle.checks.indentation.indentation; //indent:0 exp:0
+
+public class InputIndentationCodeBlocks1 { //indent:0 exp:0
+  { //indent:2 exp:2
+    System.out.println("True"); //indent:4 exp:4
+  } //indent:2 exp:2
+    { //indent:4 exp:2 warn
+      System.out.println("False"); //indent:6 exp:4 warn
+    } //indent:4 exp:2 warn
+  private static void test(int condition) { //indent:2 exp:2
+    { //indent:4 exp:4
+      System.out.println("True"); //indent:6 exp:6
+    } //indent:4 exp:4
+  } //indent:2 exp:2
+
+  { //indent:2 exp:2
+    System.out.println("False"); //indent:4 exp:4
+  } //indent:2 exp:2
+
+    { //indent:4 exp:2 warn
+      System.out.println("False"); //indent:6 exp:4 warn
+    } //indent:4 exp:2 warn
+
+  public void testSwitchCases(int j) { //indent:2 exp:2
+    switch (j) { //indent:4 exp:4
+      case 1: //indent:6 exp:6
+        { //indent:8 exp:8
+          System.out.println("One"); //indent:10 exp:10
+          break; //indent:10 exp:10
+        } //indent:8 exp:8
+      case 2: //indent:6 exp:6
+        { //indent:8 exp:8
+          test(2); //indent:10 exp:10
+          break; //indent:10 exp:10
+        } //indent:8 exp:8
+      default: //indent:6 exp:6
+        System.out.println("default"); //indent:8 exp:8
+    } //indent:4 exp:4
+  } //indent:2 exp:2
+
+  class Inner { //indent:2 exp:2
+    void test() { //indent:4 exp:4
+      { //indent:6 exp:6
+        System.out.println("True"); //indent:8 exp:8
+      } //indent:6 exp:6
+    } //indent:4 exp:4
+  } //indent:2 exp:2
+} //indent:0 exp:0