blob: 4bc92bce7ed98acffa426bb0603e900d32f5f172 [file] [log] [blame]
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Vector;
import org.checkerframework.checker.interning.qual.InternMethod;
import org.checkerframework.checker.interning.qual.Interned;
import org.checkerframework.checker.interning.qual.UnknownInterned;
// The @Interned annotation indicates that much like an enum, all variables
// declared of this type are interned (except the constructor return value).
public @Interned class InternedClass {
int value;
InternedClass factory(int i) {
return new InternedClass(i).intern();
}
// Private constructor
private InternedClass(int i) {
value = i;
// "this" in the constructor is not interned.
// :: error: (assignment)
@Interned InternedClass that = this;
}
// Overriding method
@org.checkerframework.dataflow.qual.Pure
public String toString() {
@Interned InternedClass c = this;
return Integer.valueOf(value).toString();
}
// Factory method
private InternedClass(InternedClass ic) {
value = ic.value;
}
// Equals method (used only by interning; clients should use ==)
@org.checkerframework.dataflow.qual.Pure
public boolean equals(Object other) {
if (!(other instanceof InternedClass)) {
return false;
}
return value == ((InternedClass) other).value;
}
// Interning method
@SuppressWarnings("annotations.on.use")
private static Map<@UnknownInterned InternedClass, @Interned InternedClass> pool =
new HashMap<>();
@InternMethod
public @Interned InternedClass intern() {
if (!pool.containsKey(this)) {
pool.put(this, (@Interned InternedClass) this);
}
return pool.get(this);
}
public void myMethod(InternedClass ic, InternedClass[] ica) {
boolean b1 = (this == ic); // valid
boolean b2 = (this == returnInternedObject()); // valid
boolean b3 = (this == ica[0]); // valid
InternedClass ic2 = returnArray()[0]; // valid
// :: error: (interned.object.creation)
ica[0] = new InternedClass(22);
InternedClass[] arr1 = returnArray(); // valid
InternedClass[] arr2 = new InternedClass[22]; // valid
InternedClass[] arr3 = new InternedClass[] {}; // valid
Map<InternedClass, Integer> map = new LinkedHashMap<>();
for (Map.Entry<InternedClass, Integer> e : map.entrySet()) {
InternedClass ic3 = e.getKey(); // valid
}
}
public InternedClass returnInternedObject() {
return this;
}
public InternedClass[] returnArray() {
return new InternedClass[] {};
}
public void internedVarargs(String name, InternedClass... args) {
InternedClass arg = args[0]; // valid
}
public void internedVarargs2(String name, @Interned String... args) {
@Interned String arg = args[0]; // valid
}
public static InternedClass[] arrayclone_simple(InternedClass[] a_old) {
int len = a_old.length;
InternedClass[] a_new = new InternedClass[len];
for (int i = 0; i < len; i++) {
// :: error: (interned.object.creation)
a_new[i] = new InternedClass(a_old[i]);
}
return a_new;
}
public @Interned class Subclass extends InternedClass {
// Private constructor
private Subclass(int i) {
super(i);
}
}
public static void castFromInternedClass(InternedClass ic) {
Subclass s = (Subclass) ic;
}
public static void castToInternedClass(Object o) {
InternedClass ic = (InternedClass) o;
}
// Default implementation
@org.checkerframework.dataflow.qual.Pure
public InternedClass clone() throws CloneNotSupportedException {
return (InternedClass) super.clone();
}
// java.lang.Class should be considered interned
public static void classTest() {
Integer i = 5;
assert i.getClass() == Integer.class;
}
// java.lang.Class is interned
public static void arrayOfClass() throws Exception {
Class<?> c = String.class;
Class[] parameterTypes = new Class[1];
parameterTypes[0] = String.class;
java.lang.reflect.Constructor<?> ctor = c.getConstructor(parameterTypes);
}
Class[] getSuperClasses(Class<?> c) {
Vector<Class<?>> v = new Vector<>();
while (true) {
// :: warning: (unnecessary.equals)
if (c.getSuperclass().equals((new Object()).getClass())) {
break;
}
c = c.getSuperclass();
v.addElement(c);
}
return (Class[]) v.toArray(new Class[0]);
}
void testCast(Object o) {
Object i = (InternedClass) o;
if (i == this) {}
}
}