blob: c3ab07735be89ae3815f77f4204bd63f749637eb [file] [log] [blame]
package org.checkerframework.checker.index.samelen;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.Tree;
import java.util.Collection;
import java.util.Collections;
import java.util.TreeSet;
import javax.lang.model.element.AnnotationMirror;
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
import org.checkerframework.checker.index.IndexUtil;
import org.checkerframework.checker.index.qual.PolySameLen;
import org.checkerframework.checker.index.qual.SameLen;
import org.checkerframework.common.basetype.BaseTypeChecker;
import org.checkerframework.common.basetype.BaseTypeVisitor;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.TreeUtils;
public class SameLenVisitor extends BaseTypeVisitor<SameLenAnnotatedTypeFactory> {
public SameLenVisitor(BaseTypeChecker checker) {
super(checker);
}
/**
* Merges SameLen annotations, then calls super.
*
* <p>{@inheritDoc}
*/
@Override
protected void commonAssignmentCheck(
AnnotatedTypeMirror varType,
AnnotatedTypeMirror valueType,
Tree valueTree,
@CompilerMessageKey String errorKey,
Object... extraArgs) {
if (IndexUtil.isSequenceType(valueType.getUnderlyingType())
&& TreeUtils.isExpressionTree(valueTree)
// if both annotations are @PolySameLen, there is nothing to do
&& !(valueType.hasAnnotation(PolySameLen.class)
&& varType.hasAnnotation(PolySameLen.class))) {
JavaExpression rhs = JavaExpression.fromTree((ExpressionTree) valueTree);
if (rhs != null && SameLenAnnotatedTypeFactory.mayAppearInSameLen(rhs)) {
String rhsExpr = rhs.toString();
AnnotationMirror sameLenAnno = valueType.getAnnotation(SameLen.class);
Collection<String> exprs;
if (sameLenAnno == null) {
exprs = Collections.singletonList(rhsExpr);
} else {
exprs =
new TreeSet<>(
AnnotationUtils.getElementValueArray(
sameLenAnno, atypeFactory.sameLenValueElement, String.class));
exprs.add(rhsExpr);
}
AnnotationMirror newSameLen = atypeFactory.createSameLen(exprs);
valueType.replaceAnnotation(newSameLen);
}
}
super.commonAssignmentCheck(varType, valueType, valueTree, errorKey, extraArgs);
}
}