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 * <div> 30 * Checks that there are no tab characters ({@code '\t'}) in the source code. 31 * </div> 32 * 33 * <p> 34 * Rationale: 35 * </p> 36 * <ul> 37 * <li> 38 * Developers should not need to configure the tab width of their text editors in order 39 * to be able to read source code. 40 * </li> 41 * <li> 42 * From the Apache jakarta coding standards: In a distributed development environment, 43 * when the commit messages get sent to a mailing list, they are almost impossible to 44 * read if you use tabs. 45 * </li> 46 * </ul> 47 * <ul> 48 * <li> 49 * Property {@code eachLine} - Control whether to report on each line containing a tab, 50 * or just the first instance. 51 * Type is {@code boolean}. 52 * Default value is {@code false}. 53 * </li> 54 * <li> 55 * Property {@code fileExtensions} - Specify the file extensions of the files to process. 56 * Type is {@code java.lang.String[]}. 57 * Default value is {@code ""}. 58 * </li> 59 * </ul> 60 * 61 * <p> 62 * Parent is {@code com.puppycrawl.tools.checkstyle.Checker} 63 * </p> 64 * 65 * <p> 66 * Violation Message Keys: 67 * </p> 68 * <ul> 69 * <li> 70 * {@code containsTab} 71 * </li> 72 * <li> 73 * {@code file.containsTab} 74 * </li> 75 * </ul> 76 * 77 * @since 5.0 78 */ 79 @StatelessCheck 80 public class FileTabCharacterCheck extends AbstractFileSetCheck { 81 82 /** 83 * A key is pointing to the warning message text in "messages.properties" 84 * file. 85 */ 86 public static final String MSG_CONTAINS_TAB = "containsTab"; 87 88 /** 89 * A key is pointing to the warning message text in "messages.properties" 90 * file. 91 */ 92 public static final String MSG_FILE_CONTAINS_TAB = "file.containsTab"; 93 94 /** Control whether to report on each line containing a tab, or just the first instance. */ 95 private boolean eachLine; 96 97 @Override 98 protected void processFiltered(File file, FileText fileText) { 99 int lineNum = 0; 100 for (int index = 0; index < fileText.size(); index++) { 101 final String line = fileText.get(index); 102 lineNum++; 103 final int tabPosition = line.indexOf('\t'); 104 if (tabPosition != -1) { 105 if (eachLine) { 106 log(lineNum, tabPosition, MSG_CONTAINS_TAB); 107 } 108 else { 109 log(lineNum, tabPosition, MSG_FILE_CONTAINS_TAB); 110 break; 111 } 112 } 113 } 114 } 115 116 /** 117 * Setter to control whether to report on each line containing a tab, or just the first 118 * instance. 119 * 120 * @param eachLine Whether report on each line containing a tab. 121 * @since 5.0 122 */ 123 public void setEachLine(boolean eachLine) { 124 this.eachLine = eachLine; 125 } 126 127 }