Kinds.java revision 2866:801b26483eb6
1/* 2 * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javac.code; 27 28import java.util.EnumSet; 29import java.util.Set; 30import java.util.Locale; 31 32import com.sun.source.tree.MemberReferenceTree; 33import com.sun.tools.javac.api.Formattable; 34import com.sun.tools.javac.api.Messages; 35 36import static com.sun.tools.javac.code.Flags.*; 37import static com.sun.tools.javac.code.TypeTag.CLASS; 38import static com.sun.tools.javac.code.TypeTag.PACKAGE; 39import static com.sun.tools.javac.code.TypeTag.TYPEVAR; 40 41/** Internal symbol kinds, which distinguish between elements of 42 * different subclasses of Symbol. Symbol kinds are organized so they can be 43 * or'ed to sets. 44 * 45 * <p><b>This is NOT part of any supported API. 46 * If you write code that depends on this, you do so at your own risk. 47 * This code and its internal interfaces are subject to change or 48 * deletion without notice.</b> 49 */ 50public class Kinds { 51 52 private Kinds() {} // uninstantiable 53 54 /** 55 * Kind of symbols. 56 * 57 * IMPORTANT: This is an ordered type. The ordering of 58 * declarations in this enum matters. Be careful when changing 59 * it. 60 */ 61 public enum Kind { 62 NIL(Category.BASIC, KindSelector.NIL), 63 PCK(Category.BASIC, KindName.PACKAGE, KindSelector.PCK), 64 TYP(Category.BASIC, KindName.CLASS, KindSelector.TYP), 65 VAR(Category.BASIC, KindName.VAR, KindSelector.VAR), 66 MTH(Category.BASIC, KindName.METHOD, KindSelector.MTH), 67 POLY(Category.BASIC, KindSelector.POLY), 68 ERR(Category.ERROR, KindSelector.ERR), 69 AMBIGUOUS(Category.RESOLUTION_TARGET), // overloaded target 70 HIDDEN(Category.RESOLUTION_TARGET), // not overloaded non-target 71 STATICERR(Category.RESOLUTION_TARGET), // overloaded? target 72 MISSING_ENCL(Category.RESOLUTION), // not overloaded non-target 73 ABSENT_VAR(Category.RESOLUTION_TARGET, KindName.VAR), // not overloaded non-target 74 WRONG_MTHS(Category.RESOLUTION_TARGET, KindName.METHOD), // overloaded target 75 WRONG_MTH(Category.RESOLUTION_TARGET, KindName.METHOD), // not overloaded target 76 ABSENT_MTH(Category.RESOLUTION_TARGET, KindName.METHOD), // not overloaded non-target 77 ABSENT_TYP(Category.RESOLUTION_TARGET, KindName.CLASS); // not overloaded non-target 78 79 // There are essentially two "levels" to the Kind datatype. 80 // The first is a totally-ordered set of categories of 81 // solutions. Within each category, we have more 82 // possibilities. 83 private enum Category { 84 BASIC, ERROR, RESOLUTION, RESOLUTION_TARGET; 85 } 86 87 private final KindName kindName; 88 private final KindName absentKind; 89 private final KindSelector selector; 90 private final Category category; 91 92 private Kind(Category category) { 93 this(category, null, null, null); 94 } 95 96 private Kind(Category category, 97 KindSelector selector) { 98 this(category, null, null, selector); 99 } 100 101 private Kind(Category category, 102 KindName absentKind) { 103 this(category, null, absentKind, null); 104 } 105 106 private Kind(Category category, 107 KindName kindName, 108 KindSelector selector) { 109 this(category, kindName, null, selector); 110 } 111 112 private Kind(Category category, 113 KindName kindName, 114 KindName absentKind, 115 KindSelector selector) { 116 this.category = category; 117 this.kindName = kindName; 118 this.absentKind = absentKind; 119 this.selector = selector; 120 } 121 122 public KindSelector toSelector() { 123 return selector; 124 } 125 126 public boolean matches(KindSelector kindSelectors) { 127 return selector.contains(kindSelectors); 128 } 129 130 public boolean isResolutionError() { 131 return category == Category.RESOLUTION || category == Category.RESOLUTION_TARGET; 132 } 133 134 public boolean isResolutionTargetError() { 135 return category == Category.RESOLUTION_TARGET; 136 } 137 138 public boolean isValid() { 139 return category == Category.BASIC; 140 } 141 142 public boolean betterThan(Kind other) { 143 return ordinal() < other.ordinal(); 144 } 145 146 public KindName kindName() { 147 if (kindName == null) { 148 throw new AssertionError("Unexpected kind: " + this); 149 } else { 150 return kindName; 151 } 152 } 153 154 public KindName absentKind() { 155 if (absentKind == null) { 156 throw new AssertionError("Unexpected kind: " + this); 157 } else { 158 return absentKind; 159 } 160 } 161 } 162 163 public static class KindSelector { 164 165 //basic selectors 166 public static final KindSelector NIL = new KindSelector(0); 167 public static final KindSelector PCK = new KindSelector(0x01); 168 public static final KindSelector TYP = new KindSelector(0x02); 169 public static final KindSelector VAR = new KindSelector(0x04); 170 public static final KindSelector VAL = new KindSelector(0x0c); 171 public static final KindSelector MTH = new KindSelector(0x10); 172 public static final KindSelector ERR = new KindSelector(0x3f); 173 public static final KindSelector POLY = new KindSelector(0x20); 174 public static final KindSelector ASG = new KindSelector(0x44); 175 176 //common derived selectors 177 public static final KindSelector TYP_PCK = of(TYP, PCK); 178 public static final KindSelector VAL_MTH = of(VAL, MTH); 179 public static final KindSelector VAL_POLY = of(VAL, POLY); 180 public static final KindSelector VAL_TYP = of(VAL, TYP); 181 public static final KindSelector VAL_TYP_PCK = of(VAL, TYP, PCK); 182 183 private final byte data; 184 185 private KindSelector(int data) { 186 this.data = (byte) data; 187 } 188 189 public static KindSelector of(KindSelector... kindSelectors) { 190 byte newData = 0; 191 for (KindSelector kindSel : kindSelectors) { 192 newData |= kindSel.data; 193 } 194 return new KindSelector(newData); 195 } 196 197 public boolean subset(KindSelector other) { 198 return (data & ~other.data) == 0; 199 } 200 201 public boolean contains(KindSelector other) { 202 return (data & other.data) != 0; 203 } 204 205 /** A set of KindName(s) representing a set of symbol's kinds. */ 206 public Set<KindName> kindNames() { 207 EnumSet<KindName> kinds = EnumSet.noneOf(KindName.class); 208 if ((data & VAL.data) != 0) { 209 if ((data & VAL.data) == VAR.data) kinds.add(KindName.VAR); 210 else kinds.add(KindName.VAL); 211 } 212 if ((data & MTH.data) != 0) kinds.add(KindName.METHOD); 213 if ((data & TYP.data) != 0) kinds.add(KindName.CLASS); 214 if ((data & PCK.data) != 0) kinds.add(KindName.PACKAGE); 215 return kinds; 216 } 217 } 218 219 public enum KindName implements Formattable { 220 ANNOTATION("kindname.annotation"), 221 CONSTRUCTOR("kindname.constructor"), 222 INTERFACE("kindname.interface"), 223 ENUM("kindname.enum"), 224 STATIC("kindname.static"), 225 TYPEVAR("kindname.type.variable"), 226 BOUND("kindname.type.variable.bound"), 227 VAR("kindname.variable"), 228 VAL("kindname.value"), 229 METHOD("kindname.method"), 230 CLASS("kindname.class"), 231 STATIC_INIT("kindname.static.init"), 232 INSTANCE_INIT("kindname.instance.init"), 233 PACKAGE("kindname.package"); 234 235 private final String name; 236 237 KindName(String name) { 238 this.name = name; 239 } 240 241 public String toString() { 242 return name; 243 } 244 245 public String getKind() { 246 return "Kindname"; 247 } 248 249 public String toString(Locale locale, Messages messages) { 250 String s = toString(); 251 return messages.getLocalizedString(locale, "compiler.misc." + s); 252 } 253 } 254 255 public static KindName kindName(MemberReferenceTree.ReferenceMode mode) { 256 switch (mode) { 257 case INVOKE: return KindName.METHOD; 258 case NEW: return KindName.CONSTRUCTOR; 259 default : throw new AssertionError("Unexpected mode: "+ mode); 260 } 261 } 262 263 /** A KindName representing a given symbol 264 */ 265 public static KindName kindName(Symbol sym) { 266 switch (sym.getKind()) { 267 case PACKAGE: 268 return KindName.PACKAGE; 269 270 case ENUM: 271 return KindName.ENUM; 272 273 case ANNOTATION_TYPE: 274 case CLASS: 275 return KindName.CLASS; 276 277 case INTERFACE: 278 return KindName.INTERFACE; 279 280 case TYPE_PARAMETER: 281 return KindName.TYPEVAR; 282 283 case ENUM_CONSTANT: 284 case FIELD: 285 case PARAMETER: 286 case LOCAL_VARIABLE: 287 case EXCEPTION_PARAMETER: 288 case RESOURCE_VARIABLE: 289 return KindName.VAR; 290 291 case CONSTRUCTOR: 292 return KindName.CONSTRUCTOR; 293 294 case METHOD: 295 return KindName.METHOD; 296 case STATIC_INIT: 297 return KindName.STATIC_INIT; 298 case INSTANCE_INIT: 299 return KindName.INSTANCE_INIT; 300 301 default: 302 throw new AssertionError("Unexpected kind: "+sym.getKind()); 303 } 304 } 305 306 /** A KindName representing the kind of a given class/interface type. 307 */ 308 public static KindName typeKindName(Type t) { 309 if (t.hasTag(TYPEVAR) || 310 t.hasTag(CLASS) && (t.tsym.flags() & COMPOUND) != 0) 311 return KindName.BOUND; 312 else if (t.hasTag(PACKAGE)) 313 return KindName.PACKAGE; 314 else if ((t.tsym.flags_field & ANNOTATION) != 0) 315 return KindName.ANNOTATION; 316 else if ((t.tsym.flags_field & INTERFACE) != 0) 317 return KindName.INTERFACE; 318 else 319 return KindName.CLASS; 320 } 321 322} 323