1 /* 2 * Copyright (c) 2011-2024 Qulice.com 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 1) Redistributions of source code must retain the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer. 2) Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following 12 * disclaimer in the documentation and/or other materials provided 13 * with the distribution. 3) Neither the name of the Qulice.com nor 14 * the names of its contributors may be used to endorse or promote 15 * products derived from this software without specific prior written 16 * permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 20 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 22 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 29 * OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 package com.qulice.checkstyle; 32 33 import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck; 34 import com.puppycrawl.tools.checkstyle.api.FileText; 35 import java.io.File; 36 37 /** 38 * Check if import lines are all together without any empty lines or comments. 39 * 40 * <p>All {@code import} instructions shall stay together, without any empty 41 * lines between them. If you need to separate them because the list is too 42 * big - it's time to refactor the class and make is smaller. 43 * 44 * @since 0.3 45 */ 46 @SuppressWarnings("PMD.CyclomaticComplexity") 47 public final class ImportCohesionCheck extends AbstractFileSetCheck { 48 49 /** 50 * The "import" keyword. 51 */ 52 private static final String IMPORT = "import "; 53 54 @Override 55 public void processFiltered(final File file, final FileText lines) { 56 int first = -1; 57 int last = -1; 58 for (int pos = 0; pos < lines.size(); pos += 1) { 59 final String line = lines.get(pos); 60 if (line.startsWith(ImportCohesionCheck.IMPORT)) { 61 if (first == -1) { 62 first = pos; 63 } 64 last = pos; 65 } 66 } 67 if (first == -1) { 68 return; 69 } 70 if (this.check(first, last, lines)) { 71 this.fireErrors(file.getPath()); 72 } 73 } 74 75 /** 76 * Perform check for empty lines and comments inside imports. 77 * @param first Line number where import occurred first 78 * @param last Line number where import occurred first 79 * @param lines All file line by line 80 * @return True if check is failed 81 */ 82 private boolean check(final int first, final int last, 83 final FileText lines 84 ) { 85 boolean failure = false; 86 if (first == 0 || !lines.get(first - 1).isEmpty()) { 87 this.log(first, "Line before imports should be empty"); 88 failure = true; 89 } 90 if (lines.size() > last + 1 && !lines.get(last + 1).isEmpty()) { 91 this.log(last + 2, "Line after imports should be empty"); 92 failure = true; 93 } 94 for (int pos = first; pos < last; pos += 1) { 95 final String line = lines.get(pos); 96 if (!line.startsWith(ImportCohesionCheck.IMPORT)) { 97 this.log( 98 pos + 1, 99 "Empty line or comment between imports is not allowed" 100 ); 101 failure = true; 102 } 103 } 104 return failure; 105 } 106 107 }