1 /*
   2  * Copyright (c) 2009, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package jdk.internal.jvmci.meta;
  24 
  25 import java.util.*;
  26 
  27 /**
  28  * Represents a reference to a Java field, either resolved or unresolved fields. Fields, like
  29  * methods and types, are resolved through {@link ConstantPool constant pools}.
  30  */
  31 public interface JavaField extends TrustedInterface {
  32 
  33     /**
  34      * Returns the name of this field.
  35      */
  36     String getName();
  37 
  38     /**
  39      * Returns a {@link JavaType} object that identifies the declared type for this field.
  40      */
  41     JavaType getType();
  42 
  43     /**
  44      * Returns the kind of this field. This is the same as calling {@link #getType}.
  45      * {@link JavaType#getJavaKind getJavaKind}.
  46      */
  47     default JavaKind getJavaKind() {
  48         return getType().getJavaKind();
  49     }
  50 
  51     /**
  52      * Returns the {@link JavaType} object representing the class or interface that declares this
  53      * field.
  54      */
  55     JavaType getDeclaringClass();
  56 
  57     /**
  58      * Gets a string for this field formatted according to a given format specification. A format
  59      * specification is composed of characters that are to be copied verbatim to the result and
  60      * specifiers that denote an attribute of this field that is to be copied to the result. A
  61      * specifier is a single character preceded by a '%' character. The accepted specifiers and the
  62      * field attributes they denote are described below:
  63      *
  64      * <pre>
  65      *     Specifier | Description                                          | Example(s)
  66      *     ----------+------------------------------------------------------------------------------------------
  67      *     'T'       | Qualified type                                       | "int" "java.lang.String"
  68      *     't'       | Unqualified type                                     | "int" "String"
  69      *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
  70      *     'h'       | Unqualified holder                                   | "Entry"
  71      *     'n'       | Field name                                           | "age"
  72      *     'f'       | Indicator if field is unresolved, static or instance | "unresolved" "static" "instance"
  73      *     '%'       | A '%' character                                      | "%"
  74      * </pre>
  75      *
  76      * @param format a format specification
  77      * @return the result of formatting this field according to {@code format}
  78      * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
  79      */
  80     @SuppressWarnings("fallthrough")
  81     default String format(String format) throws IllegalFormatException {
  82         StringBuilder sb = new StringBuilder();
  83         int index = 0;
  84         JavaType type = getType();
  85         while (index < format.length()) {
  86             char ch = format.charAt(index++);
  87             if (ch == '%') {
  88                 if (index >= format.length()) {
  89                     throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a field format specification");
  90                 }
  91                 char specifier = format.charAt(index++);
  92                 switch (specifier) {
  93                     case 'T':
  94                     case 't': {
  95                         sb.append(type.toJavaName(specifier == 'T'));
  96                         break;
  97                     }
  98                     case 'H':
  99                     case 'h': {
 100                         sb.append(getDeclaringClass().toJavaName(specifier == 'H'));
 101                         break;
 102                     }
 103                     case 'n': {
 104                         sb.append(getName());
 105                         break;
 106                     }
 107                     case 'f': {
 108                         sb.append(!(this instanceof ResolvedJavaField) ? "unresolved" : ((ResolvedJavaField) this).isStatic() ? "static" : "instance");
 109                         break;
 110                     }
 111                     case '%': {
 112                         sb.append('%');
 113                         break;
 114                     }
 115                     default: {
 116                         throw new UnknownFormatConversionException(String.valueOf(specifier));
 117                     }
 118                 }
 119             } else {
 120                 sb.append(ch);
 121             }
 122         }
 123         return sb.toString();
 124     }
 125 }