1 package annotations.el; 2 3 import annotations.util.Hasher; 4 5 /*>>> 6 import org.checkerframework.checker.nullness.qual.*; 7 */ 8 9 /** 10 * A {@link RelativeLocation} holds location information for a 11 * instanceof, cast, or new: either the bytecode offset or the source code index. 12 * I call instanceof, cast, or new "the construct". 13 */ 14 public final class RelativeLocation implements Comparable<RelativeLocation> { 15 /** 16 * The bytecode offset of the construct. 17 */ 18 public final int offset; 19 20 /** 21 * The source code index of the construct. 22 */ 23 public final int index; 24 25 /** 26 * The type index used for intersection types in casts. 27 */ 28 public final int type_index; 29 30 /** 31 * Constructs a new {@link RelativeLocation}; the arguments are assigned to 32 * the fields of the same names. 33 * Use -1 for the relative location that you're not using 34 */ RelativeLocation(int offset, int index, int type_index)35 private RelativeLocation(int offset, int index, int type_index) { 36 this.offset = offset; 37 this.index = index; 38 this.type_index = type_index; 39 } 40 createOffset(int offset, int type_index)41 public static RelativeLocation createOffset(int offset, int type_index) { 42 return new RelativeLocation(offset, -1, type_index); 43 } 44 createIndex(int index, int type_index)45 public static RelativeLocation createIndex(int index, int type_index) { 46 return new RelativeLocation(-1, index, type_index); 47 } 48 isBytecodeOffset()49 public boolean isBytecodeOffset() { 50 return offset>-1; 51 } 52 getLocationString()53 public String getLocationString() { 54 if (isBytecodeOffset()) { 55 return "#" + offset; 56 } else { 57 return "*" + index; 58 } 59 } 60 61 @Override compareTo(RelativeLocation l)62 public int compareTo(RelativeLocation l) { 63 int c = Integer.compare(offset, l.offset); 64 if (c == 0) { 65 c = Integer.compare(index, l.index); 66 if (c == 0) { 67 c = Integer.compare(type_index, l.type_index); 68 } 69 } 70 return c; 71 } 72 73 /** 74 * Returns whether this {@link RelativeLocation} equals <code>o</code>; a 75 * slightly faster variant of {@link #equals(Object)} for when the argument 76 * is statically known to be another nonnull {@link RelativeLocation}. 77 */ equals(RelativeLocation l)78 public boolean equals(RelativeLocation l) { 79 return compareTo(l) == 0; 80 } 81 82 /** 83 * This {@link RelativeLocation} equals <code>o</code> if and only if 84 * <code>o</code> is another nonnull {@link RelativeLocation} and 85 * <code>this</code> and <code>o</code> have equal {@link #offset} and {@link #index}. 86 */ 87 @Override equals(Object o)88 public boolean equals(Object o) { 89 return o instanceof RelativeLocation 90 && equals((RelativeLocation) o); 91 } 92 93 /** 94 * {@inheritDoc} 95 */ 96 @Override hashCode()97 public int hashCode() { 98 Hasher h = new Hasher(); 99 h.mash(offset); 100 h.mash(index); 101 h.mash(type_index); 102 return h.hash; 103 } 104 105 @Override toString()106 public String toString() { 107 return "RelativeLocation(" + getLocationString() + ")"; 108 } 109 } 110