001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2022 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018/////////////////////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.checks.design; 021 022import com.puppycrawl.tools.checkstyle.StatelessCheck; 023import com.puppycrawl.tools.checkstyle.api.AbstractCheck; 024import com.puppycrawl.tools.checkstyle.api.DetailAST; 025import com.puppycrawl.tools.checkstyle.api.TokenTypes; 026 027/** 028 * <p> 029 * Implements Joshua Bloch, Effective Java, Item 17 - 030 * Use Interfaces only to define types. 031 * </p> 032 * <p> 033 * According to Bloch, an interface should describe a <em>type</em>. It is therefore 034 * inappropriate to define an interface that does not contain any methods 035 * but only constants. The Standard interface 036 * <a href="https://docs.oracle.com/javase/8/docs/api/javax/swing/SwingConstants.html"> 037 * javax.swing.SwingConstants</a> is an example of an interface that would be flagged by this check. 038 * </p> 039 * <p> 040 * The check can be configured to also disallow marker interfaces like {@code java.io.Serializable}, 041 * that do not contain methods or constants at all. 042 * </p> 043 * <ul> 044 * <li> 045 * Property {@code allowMarkerInterfaces} - Control whether marker interfaces 046 * like Serializable are allowed. 047 * Type is {@code boolean}. 048 * Default value is {@code true}. 049 * </li> 050 * </ul> 051 * <p> 052 * To configure the check: 053 * </p> 054 * <pre> 055 * <module name="InterfaceIsType"/> 056 * </pre> 057 * <p>Example:</p> 058 * <pre> 059 * public interface Test1 { // violation 060 * int a = 3; 061 * 062 * } 063 * 064 * public interface Test2 { // OK 065 * 066 * } 067 * 068 * public interface Test3 { // OK 069 * int a = 3; 070 * void test(); 071 * } 072 * </pre> 073 * <p> 074 * To configure the check to report violation so that it doesn't allow Marker Interfaces: 075 * </p> 076 * <pre> 077 * <module name="InterfaceIsType"> 078 * <property name="allowMarkerInterfaces" value="false"/> 079 * </module> 080 * </pre> 081 * <p>Example:</p> 082 * <pre> 083 * public interface Test1 { // violation 084 * int a = 3; 085 * } 086 * 087 * public interface Test2 { // violation 088 * 089 * } 090 * </pre> 091 * <p> 092 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} 093 * </p> 094 * <p> 095 * Violation Message Keys: 096 * </p> 097 * <ul> 098 * <li> 099 * {@code interface.type} 100 * </li> 101 * </ul> 102 * 103 * @since 3.1 104 */ 105@StatelessCheck 106public final class InterfaceIsTypeCheck 107 extends AbstractCheck { 108 109 /** 110 * A key is pointing to the warning message text in "messages.properties" 111 * file. 112 */ 113 public static final String MSG_KEY = "interface.type"; 114 115 /** Control whether marker interfaces like Serializable are allowed. */ 116 private boolean allowMarkerInterfaces = true; 117 118 @Override 119 public int[] getDefaultTokens() { 120 return getRequiredTokens(); 121 } 122 123 @Override 124 public int[] getRequiredTokens() { 125 return new int[] {TokenTypes.INTERFACE_DEF}; 126 } 127 128 @Override 129 public int[] getAcceptableTokens() { 130 return getRequiredTokens(); 131 } 132 133 @Override 134 public void visitToken(DetailAST ast) { 135 final DetailAST objBlock = 136 ast.findFirstToken(TokenTypes.OBJBLOCK); 137 final DetailAST methodDef = 138 objBlock.findFirstToken(TokenTypes.METHOD_DEF); 139 final DetailAST variableDef = 140 objBlock.findFirstToken(TokenTypes.VARIABLE_DEF); 141 final boolean methodRequired = 142 !allowMarkerInterfaces || variableDef != null; 143 144 if (methodDef == null && methodRequired) { 145 log(ast, MSG_KEY); 146 } 147 } 148 149 /** 150 * Setter to control whether marker interfaces like Serializable are allowed. 151 * 152 * @param flag whether to allow marker interfaces or not 153 */ 154 public void setAllowMarkerInterfaces(boolean flag) { 155 allowMarkerInterfaces = flag; 156 } 157 158}