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  
11  /**
12   * Check if import lines are all together without any empty lines or comments.
13   *
14   * <p>All {@code import} instructions shall stay together, without any empty
15   * lines between them. If you need to separate them because the list is too
16   * big - it's time to refactor the class and make is smaller.
17   *
18   * @since 0.3
19   */
20  @SuppressWarnings("PMD.CyclomaticComplexity")
21  public final class ImportCohesionCheck extends AbstractFileSetCheck {
22  
23      /**
24       * The "import" keyword.
25       */
26      private static final String IMPORT = "import ";
27  
28      @Override
29      public void processFiltered(final File file, final FileText lines) {
30          int first = -1;
31          int last = -1;
32          for (int pos = 0; pos < lines.size(); pos += 1) {
33              final String line = lines.get(pos);
34              if (line.startsWith(ImportCohesionCheck.IMPORT)) {
35                  if (first == -1) {
36                      first = pos;
37                  }
38                  last = pos;
39              }
40          }
41          if (first == -1) {
42              return;
43          }
44          if (this.check(first, last, lines)) {
45              this.fireErrors(file.getPath());
46          }
47      }
48  
49      /**
50       * Perform check for empty lines and comments inside imports.
51       * @param first Line number where import occurred first
52       * @param last Line number where import occurred first
53       * @param lines All file line by line
54       * @return True if check is failed
55       */
56      private boolean check(final int first, final int last,
57          final FileText lines
58      ) {
59          boolean failure = false;
60          if (first == 0 || !lines.get(first - 1).isEmpty()) {
61              this.log(first, "Line before imports should be empty");
62              failure = true;
63          }
64          if (lines.size() > last + 1 && !lines.get(last + 1).isEmpty()) {
65              this.log(last + 2, "Line after imports should be empty");
66              failure = true;
67          }
68          for (int pos = first; pos < last; pos += 1) {
69              final String line = lines.get(pos);
70              if (!line.startsWith(ImportCohesionCheck.IMPORT)) {
71                  this.log(
72                      pos + 1,
73                      "Empty line or comment between imports is not allowed"
74                  );
75                  failure = true;
76              }
77          }
78          return failure;
79      }
80  
81  }