1 /* 2 * Copyright (c) 1999, 2019, 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 26 package com.sun.tools.javac.code; 27 28 import java.util.EnumSet; 29 import java.util.Set; 30 import java.util.Locale; 31 32 import com.sun.source.tree.MemberReferenceTree; 33 import com.sun.tools.javac.api.Formattable; 34 import com.sun.tools.javac.api.Messages; 35 36 import static com.sun.tools.javac.code.Flags.*; 37 import static com.sun.tools.javac.code.TypeTag.CLASS; 38 import static com.sun.tools.javac.code.TypeTag.PACKAGE; 39 import 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 */ 50 public class Kinds { 51 Kinds()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 MDL(Category.BASIC, KindSelector.MDL), 69 ERR(Category.ERROR, KindSelector.ERR), 70 AMBIGUOUS(Category.RESOLUTION_TARGET), // overloaded target 71 HIDDEN(Category.RESOLUTION_TARGET), // not overloaded non-target 72 STATICERR(Category.RESOLUTION_TARGET), // overloaded? target 73 MISSING_ENCL(Category.RESOLUTION), // not overloaded non-target 74 BAD_RESTRICTED_TYPE(Category.RESOLUTION), // not overloaded non-target 75 ABSENT_VAR(Category.RESOLUTION_TARGET, KindName.VAR), // not overloaded non-target 76 WRONG_MTHS(Category.RESOLUTION_TARGET, KindName.METHOD), // overloaded target 77 WRONG_MTH(Category.RESOLUTION_TARGET, KindName.METHOD), // not overloaded target 78 ABSENT_MTH(Category.RESOLUTION_TARGET, KindName.METHOD), // not overloaded non-target 79 ABSENT_TYP(Category.RESOLUTION_TARGET, KindName.CLASS); // not overloaded non-target 80 81 // There are essentially two "levels" to the Kind datatype. 82 // The first is a totally-ordered set of categories of 83 // solutions. Within each category, we have more 84 // possibilities. 85 private enum Category { 86 BASIC, ERROR, RESOLUTION, RESOLUTION_TARGET; 87 } 88 89 private final KindName kindName; 90 private final KindName absentKind; 91 private final KindSelector selector; 92 private final Category category; 93 Kind(Category category)94 private Kind(Category category) { 95 this(category, null, null, null); 96 } 97 Kind(Category category, KindSelector selector)98 private Kind(Category category, 99 KindSelector selector) { 100 this(category, null, null, selector); 101 } 102 Kind(Category category, KindName absentKind)103 private Kind(Category category, 104 KindName absentKind) { 105 this(category, null, absentKind, null); 106 } 107 Kind(Category category, KindName kindName, KindSelector selector)108 private Kind(Category category, 109 KindName kindName, 110 KindSelector selector) { 111 this(category, kindName, null, selector); 112 } 113 Kind(Category category, KindName kindName, KindName absentKind, KindSelector selector)114 private Kind(Category category, 115 KindName kindName, 116 KindName absentKind, 117 KindSelector selector) { 118 this.category = category; 119 this.kindName = kindName; 120 this.absentKind = absentKind; 121 this.selector = selector; 122 } 123 toSelector()124 public KindSelector toSelector() { 125 return selector; 126 } 127 matches(KindSelector kindSelectors)128 public boolean matches(KindSelector kindSelectors) { 129 return selector.contains(kindSelectors); 130 } 131 isResolutionError()132 public boolean isResolutionError() { 133 return category == Category.RESOLUTION || category == Category.RESOLUTION_TARGET; 134 } 135 isResolutionTargetError()136 public boolean isResolutionTargetError() { 137 return category == Category.RESOLUTION_TARGET; 138 } 139 isValid()140 public boolean isValid() { 141 return category == Category.BASIC; 142 } 143 betterThan(Kind other)144 public boolean betterThan(Kind other) { 145 return ordinal() < other.ordinal(); 146 } 147 kindName()148 public KindName kindName() { 149 if (kindName == null) { 150 throw new AssertionError("Unexpected kind: " + this); 151 } else { 152 return kindName; 153 } 154 } 155 absentKind()156 public KindName absentKind() { 157 if (absentKind == null) { 158 throw new AssertionError("Unexpected kind: " + this); 159 } else { 160 return absentKind; 161 } 162 } 163 } 164 165 public static class KindSelector { 166 167 //basic selectors 168 public static final KindSelector NIL = new KindSelector(0); 169 public static final KindSelector PCK = new KindSelector(0x01); 170 public static final KindSelector TYP = new KindSelector(0x02); 171 public static final KindSelector VAR = new KindSelector(0x04); 172 public static final KindSelector VAL = new KindSelector(0x0c); 173 public static final KindSelector MTH = new KindSelector(0x10); 174 public static final KindSelector POLY = new KindSelector(0x20); 175 public static final KindSelector MDL = new KindSelector(0x40); 176 public static final KindSelector ERR = new KindSelector(0x7f); 177 public static final KindSelector ASG = new KindSelector(0x84); 178 179 //common derived selectors 180 public static final KindSelector TYP_PCK = of(TYP, PCK); 181 public static final KindSelector VAL_MTH = of(VAL, MTH); 182 public static final KindSelector VAL_POLY = of(VAL, POLY); 183 public static final KindSelector VAL_TYP = of(VAL, TYP); 184 public static final KindSelector VAL_TYP_PCK = of(VAL, TYP, PCK); 185 186 private final byte data; 187 KindSelector(int data)188 private KindSelector(int data) { 189 this.data = (byte) data; 190 } 191 of(KindSelector... kindSelectors)192 public static KindSelector of(KindSelector... kindSelectors) { 193 byte newData = 0; 194 for (KindSelector kindSel : kindSelectors) { 195 newData |= kindSel.data; 196 } 197 return new KindSelector(newData); 198 } 199 subset(KindSelector other)200 public boolean subset(KindSelector other) { 201 return (data & ~other.data) == 0; 202 } 203 contains(KindSelector other)204 public boolean contains(KindSelector other) { 205 return (data & other.data) != 0; 206 } 207 208 /** A set of KindName(s) representing a set of symbol's kinds. */ kindNames()209 public Set<KindName> kindNames() { 210 EnumSet<KindName> kinds = EnumSet.noneOf(KindName.class); 211 if ((data & VAL.data) != 0) { 212 if ((data & VAL.data) == VAR.data) kinds.add(KindName.VAR); 213 else kinds.add(KindName.VAL); 214 } 215 if ((data & MTH.data) != 0) kinds.add(KindName.METHOD); 216 if ((data & TYP.data) != 0) kinds.add(KindName.CLASS); 217 if ((data & PCK.data) != 0) kinds.add(KindName.PACKAGE); 218 if ((data & MDL.data) != 0) kinds.add(KindName.MODULE); 219 return kinds; 220 } 221 } 222 223 public enum KindName implements Formattable { 224 ANNOTATION("kindname.annotation"), 225 CONSTRUCTOR("kindname.constructor"), 226 INTERFACE("kindname.interface"), 227 ENUM("kindname.enum"), 228 STATIC("kindname.static"), 229 TYPEVAR("kindname.type.variable"), 230 BOUND("kindname.type.variable.bound"), 231 VAR("kindname.variable"), 232 VAL("kindname.value"), 233 METHOD("kindname.method"), 234 CLASS("kindname.class"), 235 STATIC_INIT("kindname.static.init"), 236 INSTANCE_INIT("kindname.instance.init"), 237 PACKAGE("kindname.package"), 238 MODULE("kindname.module"), 239 RECORD_COMPONENT("kindname.record.component"), 240 RECORD("kindname.record"); 241 242 private final String name; 243 KindName(String name)244 KindName(String name) { 245 this.name = name; 246 } 247 toString()248 public String toString() { 249 return name; 250 } 251 getKind()252 public String getKind() { 253 return "Kindname"; 254 } 255 toString(Locale locale, Messages messages)256 public String toString(Locale locale, Messages messages) { 257 String s = toString(); 258 return messages.getLocalizedString(locale, "compiler.misc." + s); 259 } 260 } 261 kindName(MemberReferenceTree.ReferenceMode mode)262 public static KindName kindName(MemberReferenceTree.ReferenceMode mode) { 263 switch (mode) { 264 case INVOKE: return KindName.METHOD; 265 case NEW: return KindName.CONSTRUCTOR; 266 default : throw new AssertionError("Unexpected mode: "+ mode); 267 } 268 } 269 270 /** A KindName representing a given symbol 271 */ kindName(Symbol sym)272 public static KindName kindName(Symbol sym) { 273 switch (sym.getKind()) { 274 case PACKAGE: 275 return KindName.PACKAGE; 276 277 case ENUM: 278 return KindName.ENUM; 279 280 case ANNOTATION_TYPE: 281 case CLASS: 282 return KindName.CLASS; 283 284 case RECORD: 285 return KindName.RECORD; 286 287 case INTERFACE: 288 return KindName.INTERFACE; 289 290 case TYPE_PARAMETER: 291 return KindName.TYPEVAR; 292 293 case BINDING_VARIABLE: 294 case ENUM_CONSTANT: 295 case PARAMETER: 296 case LOCAL_VARIABLE: 297 case EXCEPTION_PARAMETER: 298 case RESOURCE_VARIABLE: 299 return KindName.VAR; 300 301 case FIELD: 302 return ((sym.flags_field & RECORD) != 0) ? KindName.RECORD_COMPONENT : KindName.VAR; 303 304 case CONSTRUCTOR: 305 return KindName.CONSTRUCTOR; 306 307 case METHOD: 308 return KindName.METHOD; 309 case STATIC_INIT: 310 return KindName.STATIC_INIT; 311 case INSTANCE_INIT: 312 return KindName.INSTANCE_INIT; 313 314 default: 315 throw new AssertionError("Unexpected kind: "+sym.getKind()); 316 } 317 } 318 319 /** A KindName representing the kind of a given class/interface type. 320 */ typeKindName(Type t)321 public static KindName typeKindName(Type t) { 322 if (t.hasTag(TYPEVAR) || 323 t.hasTag(CLASS) && (t.tsym.flags() & COMPOUND) != 0) 324 return KindName.BOUND; 325 else if (t.hasTag(PACKAGE)) 326 return KindName.PACKAGE; 327 else if ((t.tsym.flags_field & ANNOTATION) != 0) 328 return KindName.ANNOTATION; 329 else if ((t.tsym.flags_field & INTERFACE) != 0) 330 return KindName.INTERFACE; 331 else 332 return KindName.CLASS; 333 } 334 335 } 336