View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2025 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.checkstyle;
6   
7   import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
8   import com.puppycrawl.tools.checkstyle.api.FileText;
9   import java.io.File;
10  import org.cactoos.text.Joined;
11  
12  /**
13   * Make sure each line indentation is either:
14   * <ul>
15   * <li>the same as previous one or less
16   * <li>bigger than previous by exactly 4
17   * </ul>
18   * All other cases must cause a failure.
19   *
20   * @since 0.3
21   */
22  public final class CascadeIndentationCheck extends AbstractFileSetCheck {
23      /**
24       * Exact indentation increase difference.
25       */
26      private static final int LINE_INDENT_DIFF = 4;
27  
28      @Override
29      public void processFiltered(final File file, final FileText lines) {
30          int previous = 0;
31          for (int pos = 0; pos < lines.size(); pos += 1) {
32              final String line = lines.get(pos);
33              final int current = CascadeIndentationCheck.indentation(line);
34              if (CascadeIndentationCheck.inCommentBlock(line)
35                  || line.isEmpty()) {
36                  continue;
37              }
38              if (current > previous
39                  && current != previous
40                  + CascadeIndentationCheck.LINE_INDENT_DIFF) {
41                  this.log(
42                      pos + 1,
43                      String.format(
44                          new Joined(
45                              "",
46                              "Indentation (%d) must be same or ",
47                              "less than previous line (%d), or ",
48                              "bigger by exactly 4"
49                          ).toString(),
50                          current,
51                          previous
52                      )
53                  );
54              }
55              previous = current;
56          }
57      }
58  
59      /**
60       * Checks if the line belongs to a comment block.
61       * @param line Input.
62       * @return True if the line belongs to a comment block.
63       */
64      private static boolean inCommentBlock(final String line) {
65          final String trimmed = line.trim();
66          return !trimmed.isEmpty()
67              && (trimmed.charAt(0) == '*'
68                  || trimmed.startsWith("/*")
69                  || trimmed.startsWith("*/")
70                  );
71      }
72  
73      /**
74       * Calculates indentation of a line.
75       * @param line Input line
76       * @return Indentation of the given line.
77       */
78      private static int indentation(final String line) {
79          int result = 0;
80          for (int pos = 0; pos < line.length(); pos += 1) {
81              if (!Character.isWhitespace(line.charAt(pos))) {
82                  break;
83              }
84              result += 1;
85          }
86          return result;
87      }
88  
89  }