1 /////////////////////////////////////////////////////////////////////////////////////////////// 2 // checkstyle: Checks Java source code and other text files for adherence to a set of rules. 3 // Copyright (C) 2001-2024 the original author or authors. 4 // 5 // This library is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 2.1 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 /////////////////////////////////////////////////////////////////////////////////////////////// 19 20 package com.puppycrawl.tools.checkstyle.checks.whitespace; 21 22 import java.io.File; 23 24 import com.puppycrawl.tools.checkstyle.StatelessCheck; 25 import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck; 26 import com.puppycrawl.tools.checkstyle.api.FileText; 27 28 /** 29 * <p> 30 * Checks that there are no tab characters ({@code '\t'}) in the source code. 31 * </p> 32 * <p> 33 * Rationale: 34 * </p> 35 * <ul> 36 * <li> 37 * Developers should not need to configure the tab width of their text editors in order 38 * to be able to read source code. 39 * </li> 40 * <li> 41 * From the Apache jakarta coding standards: In a distributed development environment, 42 * when the commit messages get sent to a mailing list, they are almost impossible to 43 * read if you use tabs. 44 * </li> 45 * </ul> 46 * <ul> 47 * <li> 48 * Property {@code eachLine} - Control whether to report on each line containing a tab, 49 * or just the first instance. 50 * Type is {@code boolean}. 51 * Default value is {@code false}. 52 * </li> 53 * <li> 54 * Property {@code fileExtensions} - Specify the file extensions of the files to process. 55 * Type is {@code java.lang.String[]}. 56 * Default value is {@code ""}. 57 * </li> 58 * </ul> 59 * <p> 60 * Parent is {@code com.puppycrawl.tools.checkstyle.Checker} 61 * </p> 62 * <p> 63 * Violation Message Keys: 64 * </p> 65 * <ul> 66 * <li> 67 * {@code containsTab} 68 * </li> 69 * <li> 70 * {@code file.containsTab} 71 * </li> 72 * </ul> 73 * 74 * @since 5.0 75 */ 76 @StatelessCheck 77 public class FileTabCharacterCheck extends AbstractFileSetCheck { 78 79 /** 80 * A key is pointing to the warning message text in "messages.properties" 81 * file. 82 */ 83 public static final String MSG_CONTAINS_TAB = "containsTab"; 84 85 /** 86 * A key is pointing to the warning message text in "messages.properties" 87 * file. 88 */ 89 public static final String MSG_FILE_CONTAINS_TAB = "file.containsTab"; 90 91 /** Control whether to report on each line containing a tab, or just the first instance. */ 92 private boolean eachLine; 93 94 @Override 95 protected void processFiltered(File file, FileText fileText) { 96 int lineNum = 0; 97 for (int index = 0; index < fileText.size(); index++) { 98 final String line = fileText.get(index); 99 lineNum++; 100 final int tabPosition = line.indexOf('\t'); 101 if (tabPosition != -1) { 102 if (eachLine) { 103 log(lineNum, tabPosition, MSG_CONTAINS_TAB); 104 } 105 else { 106 log(lineNum, tabPosition, MSG_FILE_CONTAINS_TAB); 107 break; 108 } 109 } 110 } 111 } 112 113 /** 114 * Setter to control whether to report on each line containing a tab, or just the first 115 * instance. 116 * 117 * @param eachLine Whether report on each line containing a tab. 118 * @since 5.0 119 */ 120 public void setEachLine(boolean eachLine) { 121 this.eachLine = eachLine; 122 } 123 124 }