001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2020 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.coding; 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 * Checks that enum definition does not contain a trailing comma. 030 * Rationale: JLS allows trailing commas in arrays and enumerations, but does not allow 031 * them in other locations. To unify the coding style, the use of trailing commas should 032 * be prohibited. 033 * </p> 034 * <pre> 035 * enum Foo1 { 036 * FOO, 037 * BAR; 038 * } 039 * </pre> 040 * <p> 041 * The check demands that there should not be any comma after last constant in 042 * enum definition. 043 * </p> 044 * <pre> 045 * enum Foo1 { 046 * FOO, 047 * BAR, //violation 048 * } 049 * </pre> 050 * <p> 051 * To configure the check: 052 * </p> 053 * <pre> 054 * <module name="NoEnumTrailingComma"/> 055 * </pre> 056 * <p> 057 * Which results in the following violations: 058 * </p> 059 * <pre> 060 * enum Foo1 { 061 * FOO, 062 * BAR; //OK 063 * } 064 * enum Foo2 { 065 * FOO, 066 * BAR //OK 067 * } 068 * enum Foo3 { 069 * FOO, 070 * BAR, //violation 071 * } 072 * enum Foo4 { 073 * FOO, 074 * BAR, // violation 075 * ; 076 * } 077 * enum Foo5 { 078 * FOO, 079 * BAR,; // violation 080 * } 081 * enum Foo6 { FOO, BAR,; } // violation 082 * enum Foo7 { FOO, BAR, } // violation 083 * enum Foo8 { 084 * FOO, 085 * BAR // OK 086 * ; 087 * } 088 * enum Foo9 { FOO, BAR; } // OK 089 * enum Foo10 { FOO, BAR } // OK 090 * </pre> 091 * 092 * @since 8.29 093 */ 094@StatelessCheck 095public class NoEnumTrailingCommaCheck extends AbstractCheck { 096 097 /** 098 * A key is pointing to the warning message text in "messages.properties" 099 * file. 100 */ 101 public static final String MSG_KEY = "no.enum.trailing.comma"; 102 103 @Override 104 public int[] getDefaultTokens() { 105 return getRequiredTokens(); 106 } 107 108 @Override 109 public int[] getAcceptableTokens() { 110 return getRequiredTokens(); 111 } 112 113 @Override 114 public int[] getRequiredTokens() { 115 return new int[] {TokenTypes.ENUM_CONSTANT_DEF}; 116 } 117 118 @Override 119 public void visitToken(DetailAST detailAST) { 120 final DetailAST nextSibling = detailAST.getNextSibling(); 121 if (nextSibling.getType() == TokenTypes.COMMA) { 122 final DetailAST nextToNextSibling = nextSibling.getNextSibling(); 123 if (nextToNextSibling.getType() != TokenTypes.ENUM_CONSTANT_DEF) { 124 log(nextSibling, MSG_KEY); 125 } 126 } 127 } 128}