langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/Constants.java
changeset 11864 116173ff7d77
parent 11711 3a9d57fab406
child 11865 8dc106e1925e
equal deleted inserted replaced
11711:3a9d57fab406 11864:116173ff7d77
     1 /*
       
     2  * Copyright (c) 2004, 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.apt.mirror.declaration;
       
    27 
       
    28 
       
    29 import java.util.Collection;
       
    30 
       
    31 import com.sun.mirror.declaration.*;
       
    32 import com.sun.mirror.type.TypeMirror;
       
    33 import com.sun.tools.apt.mirror.type.TypeMirrorImpl;
       
    34 import com.sun.tools.javac.code.Type;
       
    35 
       
    36 import static com.sun.tools.javac.code.TypeTags.*;
       
    37 
       
    38 
       
    39 /**
       
    40  * Utility class for operating on constant expressions.
       
    41  */
       
    42 @SuppressWarnings("deprecation")
       
    43 class Constants {
       
    44 
       
    45     /**
       
    46      * Converts a constant in javac's internal representation (in which
       
    47      * boolean, char, byte, short, and int are each represented by an Integer)
       
    48      * into standard representation.  Other values (including null) are
       
    49      * returned unchanged.
       
    50      */
       
    51     static Object decodeConstant(Object value, Type type) {
       
    52         if (value instanceof Integer) {
       
    53             int i = ((Integer) value).intValue();
       
    54             switch (type.tag) {
       
    55             case BOOLEAN:  return Boolean.valueOf(i != 0);
       
    56             case CHAR:     return Character.valueOf((char) i);
       
    57             case BYTE:     return Byte.valueOf((byte) i);
       
    58             case SHORT:    return Short.valueOf((short) i);
       
    59             }
       
    60         }
       
    61         return value;
       
    62     }
       
    63 
       
    64     /**
       
    65      * Returns a formatter for generating the text of constant
       
    66      * expressions.  Equivalent to
       
    67      * <tt>getFormatter(new StringBuilder())</tt>.
       
    68      */
       
    69     static Formatter getFormatter() {
       
    70         return new Formatter(new StringBuilder());
       
    71     }
       
    72 
       
    73     /**
       
    74      * Returns a formatter for generating the text of constant
       
    75      * expressions.  Also generates the text of constant
       
    76      * "pseudo-expressions" for annotations and array-valued
       
    77      * annotation elements.
       
    78      *
       
    79      * @param buf  where the expression is written
       
    80      */
       
    81     static Formatter getFormatter(StringBuilder buf) {
       
    82         return new Formatter(buf);
       
    83     }
       
    84 
       
    85 
       
    86     /**
       
    87      * Utility class used to generate the text of constant
       
    88      * expressions.  Also generates the text of constant
       
    89      * "pseudo-expressions" for annotations and array-valued
       
    90      * annotation elements.
       
    91      */
       
    92     static class Formatter {
       
    93 
       
    94         private StringBuilder buf;      // where the output goes
       
    95 
       
    96         private Formatter(StringBuilder buf) {
       
    97             this.buf = buf;
       
    98         }
       
    99 
       
   100 
       
   101         public String toString() {
       
   102             return buf.toString();
       
   103         }
       
   104 
       
   105         /**
       
   106          * Appends a constant whose type is not statically known
       
   107          * by dispatching to the appropriate overloaded append method.
       
   108          */
       
   109         void append(Object val) {
       
   110             if (val instanceof String) {
       
   111                 append((String) val);
       
   112             } else if (val instanceof Character) {
       
   113                 append((Character) val);
       
   114             } else if (val instanceof Boolean) {
       
   115                 append((Boolean) val);
       
   116             } else if (val instanceof Byte) {
       
   117                 append((Byte) val);
       
   118             } else if (val instanceof Short) {
       
   119                 append((Short) val);
       
   120             } else if (val instanceof Integer) {
       
   121                 append((Integer) val);
       
   122             } else if (val instanceof Long) {
       
   123                 append((Long) val);
       
   124             } else if (val instanceof Float) {
       
   125                 append((Float) val);
       
   126             } else if (val instanceof Double) {
       
   127                 append((Double) val);
       
   128             } else if (val instanceof TypeMirror) {
       
   129                 append((TypeMirrorImpl) val);
       
   130             } else if (val instanceof EnumConstantDeclaration) {
       
   131                 append((EnumConstantDeclarationImpl) val);
       
   132             } else if (val instanceof AnnotationMirror) {
       
   133                 append((AnnotationMirrorImpl) val);
       
   134             } else if (val instanceof Collection<?>) {
       
   135                 append((Collection<?>) val);
       
   136             } else {
       
   137                 appendUnquoted(val.toString());
       
   138             }
       
   139         }
       
   140 
       
   141         /**
       
   142          * Appends a string, escaped (as needed) and quoted.
       
   143          */
       
   144         void append(String val) {
       
   145             buf.append('"');
       
   146             appendUnquoted(val);
       
   147             buf.append('"');
       
   148         }
       
   149 
       
   150         /**
       
   151          * Appends a Character, escaped (as needed) and quoted.
       
   152          */
       
   153         void append(Character val) {
       
   154             buf.append('\'');
       
   155             appendUnquoted(val.charValue());
       
   156             buf.append('\'');
       
   157         }
       
   158 
       
   159         void append(Boolean val) {
       
   160             buf.append(val);
       
   161         }
       
   162 
       
   163         void append(Byte val) {
       
   164             buf.append(String.format("0x%02x", val));
       
   165         }
       
   166 
       
   167         void append(Short val) {
       
   168             buf.append(val);
       
   169         }
       
   170 
       
   171         void append(Integer val) {
       
   172             buf.append(val);
       
   173         }
       
   174 
       
   175         void append(Long val) {
       
   176             buf.append(val).append('L');
       
   177         }
       
   178 
       
   179         void append(Float val) {
       
   180             if (val.isNaN()) {
       
   181                 buf.append("0.0f/0.0f");
       
   182             } else if (val.isInfinite()) {
       
   183                 if (val.floatValue() < 0) {
       
   184                     buf.append('-');
       
   185                 }
       
   186                 buf.append("1.0f/0.0f");
       
   187             } else {
       
   188                 buf.append(val).append('f');
       
   189             }
       
   190         }
       
   191 
       
   192         void append(Double val) {
       
   193             if (val.isNaN()) {
       
   194                 buf.append("0.0/0.0");
       
   195             } else if (val.isInfinite()) {
       
   196                 if (val.doubleValue() < 0) {
       
   197                     buf.append('-');
       
   198                 }
       
   199                 buf.append("1.0/0.0");
       
   200             } else {
       
   201                 buf.append(val);
       
   202             }
       
   203         }
       
   204 
       
   205         /**
       
   206          * Appends the class literal corresponding to a type.  Should
       
   207          * only be invoked for types that have an associated literal.
       
   208          * e.g:  "java.lang.String.class"
       
   209          *       "boolean.class"
       
   210          *       "int[].class"
       
   211          */
       
   212         void append(TypeMirrorImpl t) {
       
   213             appendUnquoted(t.type.toString());
       
   214             buf.append(".class");
       
   215         }
       
   216 
       
   217         /**
       
   218          * Appends the fully qualified name of an enum constant.
       
   219          * e.g:  "java.math.RoundingMode.UP"
       
   220          */
       
   221         void append(EnumConstantDeclarationImpl e) {
       
   222             appendUnquoted(e.sym.enclClass() + "." + e);
       
   223         }
       
   224 
       
   225         /**
       
   226          * Appends the text of an annotation pseudo-expression.
       
   227          * e.g:  "@pkg.Format(linesep='\n')"
       
   228          */
       
   229         void append(AnnotationMirrorImpl anno) {
       
   230             appendUnquoted(anno.toString());
       
   231         }
       
   232 
       
   233         /**
       
   234          * Appends the elements of a collection, enclosed within braces
       
   235          * and separated by ", ".  Useful for array-valued annotation
       
   236          * elements.
       
   237          */
       
   238         void append(Collection<?> vals) {
       
   239             buf.append('{');
       
   240             boolean first = true;
       
   241             for (Object val : vals) {
       
   242                 if (first) {
       
   243                     first = false;
       
   244                 } else {
       
   245                     buf.append(", ");
       
   246                 }
       
   247                 append(((AnnotationValue) val).getValue());
       
   248             }
       
   249             buf.append('}');
       
   250         }
       
   251 
       
   252 
       
   253         /**
       
   254          * For each char of a string, append using appendUnquoted(char).
       
   255          */
       
   256         private void appendUnquoted(String s) {
       
   257             for (char c : s.toCharArray()) {
       
   258                 appendUnquoted(c);
       
   259             }
       
   260         }
       
   261 
       
   262         /**
       
   263          * Appends a char (unquoted), using escapes for those that are not
       
   264          * printable ASCII.  We don't know what is actually printable in
       
   265          * the locale in which this result will be used, so ASCII is our
       
   266          * best guess as to the least common denominator.
       
   267          */
       
   268         private void appendUnquoted(char c) {
       
   269             switch (c) {
       
   270             case '\b': buf.append("\\b");  break;
       
   271             case '\t': buf.append("\\t");  break;
       
   272             case '\n': buf.append("\\n");  break;
       
   273             case '\f': buf.append("\\f");  break;
       
   274             case '\r': buf.append("\\r");  break;
       
   275             case '\"': buf.append("\\\""); break;
       
   276             case '\'': buf.append("\\\'"); break;
       
   277             case '\\': buf.append("\\\\"); break;
       
   278             default:
       
   279                 if (isPrintableAscii(c)) {
       
   280                     buf.append(c);
       
   281                 } else {
       
   282                     buf.append(String.format("\\u%04x", (int) c));
       
   283                 }
       
   284             }
       
   285         }
       
   286 
       
   287         /**
       
   288          * Is c a printable ASCII character?
       
   289          */
       
   290         private static boolean isPrintableAscii(char c) {
       
   291             return c >= ' ' && c <= '~';
       
   292         }
       
   293     }
       
   294 }