Represents field references in IR.
| 41 | * Represents field references in IR. |
| 42 | */ |
| 43 | @InternalCanonicalized |
| 44 | public class FieldRef extends MemberRef { |
| 45 | |
| 46 | private static final Logger logger = LogManager.getLogger(FieldRef.class); |
| 47 | |
| 48 | private static final ConcurrentMap<Key, FieldRef> map = |
| 49 | Maps.newConcurrentMap(4096); |
| 50 | |
| 51 | /** |
| 52 | * Records the FieldRef that fails to be resolved. |
| 53 | */ |
| 54 | private static final Set<FieldRef> resolveFailures = |
| 55 | Sets.newConcurrentSet(); |
| 56 | |
| 57 | static { |
| 58 | World.registerResetCallback(map::clear); |
| 59 | World.registerResetCallback(resolveFailures::clear); |
| 60 | } |
| 61 | |
| 62 | private final Type type; |
| 63 | |
| 64 | /** |
| 65 | * Caches the resolved field for this reference to avoid redundant |
| 66 | * field resolution. |
| 67 | * |
| 68 | * @see #resolve() |
| 69 | * @see #resolveNullable() |
| 70 | */ |
| 71 | @Nullable |
| 72 | private transient JField field; |
| 73 | |
| 74 | public static FieldRef get( |
| 75 | JClass declaringClass, String name, Type type, boolean isStatic) { |
| 76 | Key key = new Key(declaringClass, name, type); |
| 77 | return map.computeIfAbsent(key, k -> new FieldRef(k, isStatic)); |
| 78 | } |
| 79 | |
| 80 | private FieldRef(Key key, boolean isStatic) { |
| 81 | super(key.declaringClass, key.name, isStatic); |
| 82 | this.type = key.type; |
| 83 | } |
| 84 | |
| 85 | public Type getType() { |
| 86 | return type; |
| 87 | } |
| 88 | |
| 89 | @Override |
| 90 | public JField resolve() { |
| 91 | if (field == null) { |
| 92 | field = World.get().getClassHierarchy() |
| 93 | .resolveField(this); |
| 94 | if (field == null) { |
| 95 | throw new FieldResolutionFailedException( |
| 96 | "Cannot resolve " + this); |
| 97 | } |
| 98 | } |
| 99 | return field; |
| 100 | } |
nothing calls this directly
no test coverage detected