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 
  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 
  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 
  94         private Kind(Category category) {
  95             this(category, null, null, null);
  96         }
  97 
  98         private Kind(Category category,
  99                      KindSelector selector) {
 100             this(category, null, null, selector);
 101         }
 102 
 103         private Kind(Category category,
 104                      KindName absentKind) {
 105             this(category, null, absentKind, null);
 106         }
 107 
 108         private Kind(Category category,
 109                      KindName kindName,
 110                      KindSelector selector) {
 111             this(category, kindName, null, selector);
 112         }
 113 
 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 
 124         public KindSelector toSelector() {
 125             return selector;
 126         }
 127 
 128         public boolean matches(KindSelector kindSelectors) {
 129             return selector.contains(kindSelectors);
 130         }
 131 
 132         public boolean isResolutionError() {
 133             return category == Category.RESOLUTION || category == Category.RESOLUTION_TARGET;
 134         }
 135 
 136         public boolean isResolutionTargetError() {
 137             return category == Category.RESOLUTION_TARGET;
 138         }
 139 
 140         public boolean isValid() {
 141             return category == Category.BASIC;
 142         }
 143 
 144         public boolean betterThan(Kind other) {
 145             return ordinal() < other.ordinal();
 146         }
 147 
 148         public KindName kindName() {
 149             if (kindName == null) {
 150                 throw new AssertionError("Unexpected kind: " + this);
 151             } else {
 152                 return kindName;
 153             }
 154         }
 155 
 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 
 188         private KindSelector(int data) {
 189             this.data = (byte) data;
 190         }
 191 
 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 
 200         public boolean subset(KindSelector other) {
 201             return (data & ~other.data) == 0;
 202         }
 203 
 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. */
 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 
 240         private final String name;
 241 
 242         KindName(String name) {
 243             this.name = name;
 244         }
 245 
 246         public String toString() {
 247             return name;
 248         }
 249 
 250         public String getKind() {
 251             return "Kindname";
 252         }
 253 
 254         public String toString(Locale locale, Messages messages) {
 255             String s = toString();
 256             return messages.getLocalizedString(locale, "compiler.misc." + s);
 257         }
 258     }
 259 
 260     public static KindName kindName(MemberReferenceTree.ReferenceMode mode) {
 261         switch (mode) {
 262             case INVOKE: return KindName.METHOD;
 263             case NEW: return KindName.CONSTRUCTOR;
 264             default : throw new AssertionError("Unexpected mode: "+ mode);
 265         }
 266     }
 267 
 268     /** A KindName representing a given symbol
 269      */
 270     public static KindName kindName(Symbol sym) {
 271         switch (sym.getKind()) {
 272         case PACKAGE:
 273             return KindName.PACKAGE;
 274 
 275         case ENUM:
 276             return KindName.ENUM;
 277 
 278         case ANNOTATION_TYPE:
 279         case CLASS:
 280             return KindName.CLASS;
 281 
 282         case INTERFACE:
 283             return KindName.INTERFACE;
 284 
 285         case TYPE_PARAMETER:
 286             return KindName.TYPEVAR;
 287 
 288         case ENUM_CONSTANT:
 289         case FIELD:
 290         case PARAMETER:
 291         case LOCAL_VARIABLE:
 292         case EXCEPTION_PARAMETER:
 293         case RESOURCE_VARIABLE:
 294             return KindName.VAR;
 295 
 296         case CONSTRUCTOR:
 297             return KindName.CONSTRUCTOR;
 298 
 299         case METHOD:
 300             return KindName.METHOD;
 301         case STATIC_INIT:
 302             return KindName.STATIC_INIT;
 303         case INSTANCE_INIT:
 304             return KindName.INSTANCE_INIT;
 305 
 306         default:
 307                 throw new AssertionError("Unexpected kind: "+sym.getKind());
 308         }
 309     }
 310 
 311     /** A KindName representing the kind of a given class/interface type.
 312      */
 313     public static KindName typeKindName(Type t) {
 314         if (t.hasTag(TYPEVAR) ||
 315             t.hasTag(CLASS) && (t.tsym.flags() & COMPOUND) != 0)
 316             return KindName.BOUND;
 317         else if (t.hasTag(PACKAGE))
 318             return KindName.PACKAGE;
 319         else if ((t.tsym.flags_field & ANNOTATION) != 0)
 320             return KindName.ANNOTATION;
 321         else if ((t.tsym.flags_field & INTERFACE) != 0)
 322             return KindName.INTERFACE;
 323         else
 324             return KindName.CLASS;
 325     }
 326 
 327 }