blob: 2e90e942571c1186a447ff34defed37db6d91b28 [file] [log] [blame]
package org.checkerframework.dataflow.expression;
import java.util.List;
import java.util.Objects;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.StringsPlume;
/** JavaExpression for array creations. {@code new String[]()}. */
public class ArrayCreation extends JavaExpression {
/**
* List of dimensions expressions. A {code null} element means that there is no dimension
* expression for the given array level.
*/
protected final List<@Nullable JavaExpression> dimensions;
/** List of initializers. */
protected final List<JavaExpression> initializers;
/**
* Creates an ArrayCreation object.
*
* @param type array type
* @param dimensions list of dimension expressions; a {code null} element means that there is no
* dimension expression for the given array level.
* @param initializers list of initializer expressions
*/
public ArrayCreation(
TypeMirror type,
List<@Nullable JavaExpression> dimensions,
List<JavaExpression> initializers) {
super(type);
assert type.getKind() == TypeKind.ARRAY;
this.dimensions = dimensions;
this.initializers = initializers;
}
/**
* Returns a list representing the dimensions of this array creation. A {code null} element means
* that there is no dimension expression for the given array level.
*
* @return a list representing the dimensions of this array creation
*/
public List<@Nullable JavaExpression> getDimensions() {
return dimensions;
}
public List<JavaExpression> getInitializers() {
return initializers;
}
@Override
public boolean containsOfClass(Class<? extends JavaExpression> clazz) {
for (JavaExpression n : dimensions) {
if (n != null && n.getClass() == clazz) {
return true;
}
}
for (JavaExpression n : initializers) {
if (n.getClass() == clazz) {
return true;
}
}
return false;
}
@Override
public boolean isDeterministic(AnnotationProvider provider) {
return listIsDeterministic(dimensions, provider) && listIsDeterministic(initializers, provider);
}
@Override
public boolean isUnassignableByOtherCode() {
return false;
}
@Override
public boolean isUnmodifiableByOtherCode() {
return false;
}
@Override
public int hashCode() {
return Objects.hash(dimensions, initializers, getType().toString());
}
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof ArrayCreation)) {
return false;
}
ArrayCreation other = (ArrayCreation) obj;
return this.dimensions.equals(other.getDimensions())
&& this.initializers.equals(other.getInitializers())
// It might be better to use Types.isSameType(getType(), other.getType()), but I
// don't have a Types object.
&& getType().toString().equals(other.getType().toString());
}
@Override
public boolean syntacticEquals(JavaExpression je) {
if (!(je instanceof ArrayCreation)) {
return false;
}
ArrayCreation other = (ArrayCreation) je;
return JavaExpression.syntacticEqualsList(this.dimensions, other.dimensions)
&& JavaExpression.syntacticEqualsList(this.initializers, other.initializers)
&& getType().toString().equals(other.getType().toString());
}
@Override
public boolean containsSyntacticEqualJavaExpression(JavaExpression other) {
return syntacticEquals(other)
|| JavaExpression.listContainsSyntacticEqualJavaExpression(dimensions, other)
|| JavaExpression.listContainsSyntacticEqualJavaExpression(initializers, other);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (dimensions.isEmpty()) {
sb.append("new " + type);
} else {
sb.append("new " + TypesUtils.getInnermostComponentType((ArrayType) type));
for (JavaExpression dim : dimensions) {
sb.append("[");
sb.append(dim == null ? "" : dim);
sb.append("]");
}
}
if (!initializers.isEmpty()) {
sb.append(" {");
sb.append(StringsPlume.join(", ", initializers));
sb.append("}");
}
return sb.toString();
}
@Override
public String toStringDebug() {
return "\""
+ super.toStringDebug()
+ "\""
+ " type="
+ type
+ " dimensions="
+ dimensions
+ " initializers="
+ initializers;
}
@Override
public <R, P> R accept(JavaExpressionVisitor<R, P> visitor, P p) {
return visitor.visitArrayCreation(this, p);
}
}