001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2015 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.utils; 021 022import java.lang.reflect.Field; 023import java.util.ResourceBundle; 024 025import org.apache.commons.lang3.ArrayUtils; 026 027import com.google.common.collect.ImmutableCollection; 028import com.google.common.collect.ImmutableMap; 029import com.puppycrawl.tools.checkstyle.api.TokenTypes; 030 031/** 032 * Contains utility methods for tokens. 033 * 034 * @author <a href="mailto:nesterenko-aleksey@list.ru">Aleksey Nesterenko</a> 035 */ 036public final class TokenUtils { 037 038 /** Maps from a token name to value. */ 039 private static final ImmutableMap<String, Integer> TOKEN_NAME_TO_VALUE; 040 /** Maps from a token value to name. */ 041 private static final String[] TOKEN_VALUE_TO_NAME; 042 043 /** Array of all token IDs. */ 044 private static final int[] TOKEN_IDS; 045 046 /** Prefix for exception when getting token by given id. */ 047 private static final String TOKEN_ID_EXCEPTION_PREFIX = "given id "; 048 049 /** Prefix for exception when getting token by given name. */ 050 private static final String TOKEN_NAME_EXCEPTION_PREFIX = "given name "; 051 052 // initialise the constants 053 static { 054 final ImmutableMap.Builder<String, Integer> builder = 055 ImmutableMap.builder(); 056 final Field[] fields = TokenTypes.class.getDeclaredFields(); 057 String[] tempTokenValueToName = ArrayUtils.EMPTY_STRING_ARRAY; 058 for (final Field field : fields) { 059 // Only process the int declarations. 060 if (field.getType() != Integer.TYPE) { 061 continue; 062 } 063 064 final String name = field.getName(); 065 final int tokenValue = getIntFromField(field, name); 066 builder.put(name, tokenValue); 067 if (tokenValue > tempTokenValueToName.length - 1) { 068 final String[] temp = new String[tokenValue + 1]; 069 System.arraycopy(tempTokenValueToName, 0, 070 temp, 0, tempTokenValueToName.length); 071 tempTokenValueToName = temp; 072 } 073 tempTokenValueToName[tokenValue] = name; 074 } 075 076 TOKEN_NAME_TO_VALUE = builder.build(); 077 TOKEN_VALUE_TO_NAME = tempTokenValueToName; 078 final ImmutableCollection<Integer> values = TOKEN_NAME_TO_VALUE.values(); 079 final Integer[] ids = values.toArray(new Integer[values.size()]); 080 TOKEN_IDS = ArrayUtils.toPrimitive(ids); 081 } 082 083 /** Stop instances being created. **/ 084 private TokenUtils() { 085 } 086 087 /** 088 * Gets the value of a static or instance field of type int or of another primitive type 089 * convertible to type int via a widening conversion. Does not throw any checked exceptions. 090 * @param field from which the int should be extracted 091 * @param object to extract the int value from 092 * @return the value of the field converted to type int 093 * @throws IllegalStateException if this Field object is enforcing Java language access control 094 * and the underlying field is inaccessible 095 * @see Field#getInt(Object) 096 */ 097 public static int getIntFromField(Field field, Object object) { 098 try { 099 return field.getInt(object); 100 } 101 catch (final IllegalAccessException exception) { 102 throw new IllegalStateException(exception); 103 } 104 } 105 106 /** 107 * Get all token IDs that are available in TokenTypes. 108 * @return array of token IDs 109 */ 110 public static int[] getAllTokenIds() { 111 final int[] safeCopy = new int[TOKEN_IDS.length]; 112 System.arraycopy(TOKEN_IDS, 0, safeCopy, 0, TOKEN_IDS.length); 113 return safeCopy; 114 } 115 116 /** 117 * Returns the name of a token for a given ID. 118 * @param id the ID of the token name to get 119 * @return a token name 120 */ 121 public static String getTokenName(int id) { 122 if (id > TOKEN_VALUE_TO_NAME.length - 1) { 123 throw new IllegalArgumentException(TOKEN_ID_EXCEPTION_PREFIX + id); 124 } 125 final String name = TOKEN_VALUE_TO_NAME[id]; 126 if (name == null) { 127 throw new IllegalArgumentException(TOKEN_ID_EXCEPTION_PREFIX + id); 128 } 129 return name; 130 } 131 132 /** 133 * Returns the ID of a token for a given name. 134 * @param name the name of the token ID to get 135 * @return a token ID 136 */ 137 public static int getTokenId(String name) { 138 final Integer id = TOKEN_NAME_TO_VALUE.get(name); 139 if (id == null) { 140 throw new IllegalArgumentException(TOKEN_NAME_EXCEPTION_PREFIX + name); 141 } 142 return id; 143 } 144 145 /** 146 * Returns the short description of a token for a given name. 147 * @param name the name of the token ID to get 148 * @return a short description 149 */ 150 public static String getShortDescription(String name) { 151 if (!TOKEN_NAME_TO_VALUE.containsKey(name)) { 152 throw new IllegalArgumentException(TOKEN_NAME_EXCEPTION_PREFIX + name); 153 } 154 155 final String tokenTypes = 156 "com.puppycrawl.tools.checkstyle.api.tokentypes"; 157 final ResourceBundle bundle = ResourceBundle.getBundle(tokenTypes); 158 return bundle.getString(name); 159 } 160 161 /** 162 * Is argument comment-related type (SINGLE_LINE_COMMENT, 163 * BLOCK_COMMENT_BEGIN, BLOCK_COMMENT_END, COMMENT_CONTENT). 164 * @param type 165 * token type. 166 * @return true if type is comment-related type. 167 */ 168 public static boolean isCommentType(int type) { 169 return type == TokenTypes.SINGLE_LINE_COMMENT 170 || type == TokenTypes.BLOCK_COMMENT_BEGIN 171 || type == TokenTypes.BLOCK_COMMENT_END 172 || type == TokenTypes.COMMENT_CONTENT; 173 } 174 175 /** 176 * Is argument comment-related type name (SINGLE_LINE_COMMENT, 177 * BLOCK_COMMENT_BEGIN, BLOCK_COMMENT_END, COMMENT_CONTENT). 178 * @param type 179 * token type name. 180 * @return true if type is comment-related type name. 181 */ 182 public static boolean isCommentType(String type) { 183 return isCommentType(getTokenId(type)); 184 } 185 186}