All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.checkerframework.dataflow.expression.FieldAccess Maven / Gradle / Ivy

Go to download

dataflow-shaded is a dataflow framework based on the javac compiler. It differs from the org.checkerframework:dataflow artifact in two ways. First, the packages in this artifact have been renamed to org.checkerframework.shaded.*. Second, unlike the dataflow artifact, this artifact contains the dependencies it requires.

There is a newer version: 3.42.0-eisop5
Show newest version
package org.checkerframework.dataflow.expression;

import com.sun.tools.javac.code.Symbol;

import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.analysis.Store;
import org.checkerframework.dataflow.cfg.node.FieldAccessNode;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.TypesUtils;

import java.util.Objects;

import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;

/**
 * A FieldAccess represents a field access. It does not represent a class literal such as {@code
 * SomeClass.class} or {@code int[].class}.
 */
public class FieldAccess extends JavaExpression {
    /** The receiver of the field access. */
    protected final JavaExpression receiver;

    /** The field being accessed. */
    protected final VariableElement field;

    /**
     * Returns the receiver.
     *
     * @return the receiver
     */
    public JavaExpression getReceiver() {
        return receiver;
    }

    /**
     * Returns the field.
     *
     * @return the field
     */
    public VariableElement getField() {
        return field;
    }

    /**
     * Create a {@code FieldAccess}.
     *
     * @param receiver receiver of the field access
     * @param node the FieldAccessNode
     */
    public FieldAccess(JavaExpression receiver, FieldAccessNode node) {
        this(receiver, node.getType(), node.getElement());
    }

    /**
     * Create a {@code FieldAccess}.
     *
     * @param receiver receiver of the field access
     * @param fieldElement element of the field
     */
    public FieldAccess(JavaExpression receiver, VariableElement fieldElement) {
        this(receiver, fieldElement.asType(), fieldElement);
    }

    /**
     * Create a {@code FieldAccess}.
     *
     * @param receiver receiver of the field access
     * @param type type of the field
     * @param fieldElement element of the field
     */
    public FieldAccess(JavaExpression receiver, TypeMirror type, VariableElement fieldElement) {
        super(type);
        this.receiver = receiver;
        this.field = fieldElement;
        String fieldName = fieldElement.toString();
        if (fieldName.equals("class") || fieldName.equals("this")) {
            BugInCF e =
                    new BugInCF(
                            String.format(
                                    "bad field name \"%s\" in new FieldAccess(%s, %s, %s)%n",
                                    fieldName, receiver, type, fieldElement));
            e.printStackTrace(System.out);
            e.printStackTrace(System.err);
            throw e;
        }
    }

    public boolean isFinal() {
        return ElementUtils.isFinal(field);
    }

    public boolean isStatic() {
        return ElementUtils.isStatic(field);
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (!(obj instanceof FieldAccess)) {
            return false;
        }
        FieldAccess fa = (FieldAccess) obj;
        return fa.getField().equals(getField()) && fa.getReceiver().equals(getReceiver());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getField(), getReceiver());
    }

    @Override
    public boolean syntacticEquals(JavaExpression je) {
        if (!(je instanceof FieldAccess)) {
            return false;
        }
        FieldAccess other = (FieldAccess) je;
        return this.receiver.syntacticEquals(other.receiver) && this.field.equals(other.field);
    }

    @Override
    public boolean containsSyntacticEqualJavaExpression(JavaExpression other) {
        return syntacticEquals(other) || receiver.containsSyntacticEqualJavaExpression(other);
    }

    @Override
    public boolean containsModifiableAliasOf(Store store, JavaExpression other) {
        return super.containsModifiableAliasOf(store, other)
                || receiver.containsModifiableAliasOf(store, other);
    }

    @Override
    public String toString() {
        if (receiver instanceof ClassName) {
            return receiver.getType() + "." + field;
        } else {
            return receiver + "." + field;
        }
    }

    @Override
    public String toStringDebug() {
        return String.format(
                "FieldAccess(type=%s, receiver=%s, field=%s [%s] [%s] owner=%s)",
                type,
                receiver.toStringDebug(),
                field,
                field.getClass().getSimpleName(),
                System.identityHashCode(field),
                ((Symbol) field).owner);
    }

    @Override
    public boolean containsOfClass(Class clazz) {
        return getClass() == clazz || receiver.containsOfClass(clazz);
    }

    @Override
    public boolean isDeterministic(AnnotationProvider provider) {
        return receiver.isDeterministic(provider);
    }

    @Override
    public boolean isUnassignableByOtherCode() {
        return isFinal() && getReceiver().isUnassignableByOtherCode();
    }

    @Override
    public boolean isUnmodifiableByOtherCode() {
        return isUnassignableByOtherCode() && TypesUtils.isImmutableTypeInJdk(getReceiver().type);
    }

    @Override
    public  R accept(JavaExpressionVisitor visitor, P p) {
        return visitor.visitFieldAccess(this, p);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy