| package org.checkerframework.dataflow.expression; |
| |
| import com.sun.tools.javac.code.Symbol.VarSymbol; |
| import java.util.Objects; |
| import javax.lang.model.element.Element; |
| import org.checkerframework.checker.nullness.qual.Nullable; |
| import org.checkerframework.dataflow.cfg.node.LocalVariableNode; |
| import org.checkerframework.javacutil.AnnotationProvider; |
| import org.checkerframework.javacutil.ElementUtils; |
| import org.checkerframework.javacutil.TypeAnnotationUtils; |
| import org.checkerframework.javacutil.TypesUtils; |
| |
| /** |
| * A local variable. |
| * |
| * <p>This class also represents a formal parameter expressed using its name. Class {@link |
| * FormalParameter} represents a formal parameter expressed using the "#2" notation. |
| */ |
| public class LocalVariable extends JavaExpression { |
| /** The element for this local variable. */ |
| protected final Element element; |
| |
| /** |
| * Creates a new LocalVariable. |
| * |
| * @param localVar a CFG local variable |
| */ |
| public LocalVariable(LocalVariableNode localVar) { |
| super(localVar.getType()); |
| this.element = localVar.getElement(); |
| } |
| |
| /** |
| * Creates a LocalVariable |
| * |
| * @param element the element for the local variable |
| */ |
| public LocalVariable(Element element) { |
| super(ElementUtils.getType(element)); |
| this.element = element; |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| if (!(obj instanceof LocalVariable)) { |
| return false; |
| } |
| LocalVariable other = (LocalVariable) obj; |
| |
| return sameElement(element, other.element); |
| } |
| |
| /** |
| * Returns true if the two elements are the same. |
| * |
| * @param element1 the first element to compare |
| * @param element2 the second element to compare |
| * @return true if the two elements are the same |
| */ |
| protected static boolean sameElement(Element element1, Element element2) { |
| VarSymbol vs1 = (VarSymbol) element1; |
| VarSymbol vs2 = (VarSymbol) element2; |
| // The code below isn't just return vs1.equals(vs2) because an element might be |
| // different between subcheckers. The owner of a lambda parameter is the enclosing |
| // method, so a local variable and a lambda parameter might have the same name and the |
| // same owner. pos is used to differentiate this case. |
| return vs1.pos == vs2.pos |
| && vs1.name.contentEquals(vs2.name) |
| && vs1.owner.toString().equals(vs2.owner.toString()); |
| } |
| |
| /** |
| * Returns the element for this variable. |
| * |
| * @return the element for this variable |
| */ |
| public Element getElement() { |
| return element; |
| } |
| |
| @Override |
| public int hashCode() { |
| VarSymbol vs = (VarSymbol) element; |
| return Objects.hash( |
| vs.name.toString(), |
| TypeAnnotationUtils.unannotatedType(vs.type).toString(), |
| vs.owner.toString()); |
| } |
| |
| @Override |
| public String toString() { |
| return element.toString(); |
| } |
| |
| @Override |
| public String toStringDebug() { |
| return super.toStringDebug() + " [owner=" + ((VarSymbol) element).owner + "]"; |
| } |
| |
| @Override |
| public boolean containsOfClass(Class<? extends JavaExpression> clazz) { |
| return getClass() == clazz; |
| } |
| |
| @Override |
| public boolean isDeterministic(AnnotationProvider provider) { |
| return true; |
| } |
| |
| @Override |
| public boolean syntacticEquals(JavaExpression je) { |
| if (!(je instanceof LocalVariable)) { |
| return false; |
| } |
| LocalVariable other = (LocalVariable) je; |
| return this.equals(other); |
| } |
| |
| @Override |
| public boolean containsSyntacticEqualJavaExpression(JavaExpression other) { |
| return syntacticEquals(other); |
| } |
| |
| @Override |
| public boolean isUnassignableByOtherCode() { |
| return true; |
| } |
| |
| @Override |
| public boolean isUnmodifiableByOtherCode() { |
| return TypesUtils.isImmutableTypeInJdk(((VarSymbol) element).type); |
| } |
| |
| @Override |
| public <R, P> R accept(JavaExpressionVisitor<R, P> visitor, P p) { |
| return visitor.visitLocalVariable(this, p); |
| } |
| } |