Skip to content

Commit

Permalink
Add InferenceQualifierDefault. (#134)
Browse files Browse the repository at this point in the history
* Add InferenceQualifierDefault.

* Unify the place of creating equivalent VarAnno given a real qualifier. Clean up a bit the related code in VariableAnnotator and ConstantToVariableAnnotator.

* Update javadoc for ConstantToVariableAnnotator.

* Make createConstant() static. Keep a reference of constantToVariableAnnotator in InferenceATF, instead of creating a new one each time the client of InferenceATF needs a c2vAnnotator.

* Add javadoc for InferenceQualifierDefaults.

* Add javadoc for explianing the motivation of replacing real qualifier with equivalent VarAnnot in applyDefault() method, instead of mutating the annotation in Default.

* Remove createConstantSlot method in Constant2VariableAnnoatator.

* Migrate createEquivalentVarAnno() method into SlotManager.

* Don't store C2VAnnotator reference in VariableAnnotator, as it introduce a very implicit construction constraint on the order of object initializations in InferenceATF constructor. This is tricky, so let InferenceATF be the source of providing C2VAnnotator.
  • Loading branch information
CharlesZ-Chen committed Feb 15, 2018
1 parent 292f8fd commit d307fc6
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 81 deletions.
2 changes: 1 addition & 1 deletion src/checkers/inference/BytecodeTypeAnnotator.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ public void annotate(final Element element, final AnnotatedTypeMirror inferenceT
final AnnotatedTypeMirror realType = realTypeFactory.getAnnotatedType(element);

CopyUtil.copyAnnotations(realType, inferenceType);
inferenceTypeFactory.getNewConstantToVariableAnnotator().visit(inferenceType);
inferenceTypeFactory.getConstantToVariableAnnotator().visit(inferenceType);
}
}
6 changes: 6 additions & 0 deletions src/checkers/inference/DefaultSlotManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -358,4 +358,10 @@ public ExistentialVariableSlot createExistentialVariableSlot(VariableSlot potent
}
return existentialVariableSlot;
}

@Override
public AnnotationMirror createEquivalentVarAnno(AnnotationMirror realQualifier) {
ConstantSlot varSlot = createConstantSlot(realQualifier);
return getAnnotation(varSlot);
}
}
71 changes: 40 additions & 31 deletions src/checkers/inference/InferenceAnnotatedTypeFactory.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
package checkers.inference;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeVariable;

import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.framework.flow.CFAbstractAnalysis;
import org.checkerframework.framework.flow.CFAnalysis;
Expand Down Expand Up @@ -28,26 +49,13 @@
import org.checkerframework.javacutil.Pair;
import org.checkerframework.javacutil.TreeUtils;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeVariable;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.Tree;

import checkers.inference.dataflow.InferenceAnalysis;
import checkers.inference.model.CombVariableSlot;
Expand All @@ -57,14 +65,7 @@
import checkers.inference.qual.VarAnnot;
import checkers.inference.util.ConstantToVariableAnnotator;
import checkers.inference.util.InferenceUtil;

import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.Tree;
import checkers.inference.util.defaults.InferenceQualifierDefaults;

/**
* InferenceAnnotatedTypeFactory is responsible for creating AnnotatedTypeMirrors that are annotated with
Expand Down Expand Up @@ -111,6 +112,7 @@ public class InferenceAnnotatedTypeFactory extends BaseAnnotatedTypeFactory {
private final AnnotationMirror realTop;
private final AnnotationMirror varAnnot;
private final InferenceQualifierPolymorphism inferencePoly;
private final ConstantToVariableAnnotator constantToVariableAnnotator;

public static final Logger logger = Logger.getLogger(InferenceAnnotatedTypeFactory.class.getSimpleName());

Expand Down Expand Up @@ -151,6 +153,8 @@ public InferenceAnnotatedTypeFactory(
realTop, varAnnot, variableAnnotator);

inferencePoly = new InferenceQualifierPolymorphism(slotManager, variableAnnotator, varAnnot);

constantToVariableAnnotator = new ConstantToVariableAnnotator(realTop, varAnnot);
// Every subclass must call postInit!
if (this.getClass().equals(InferenceAnnotatedTypeFactory.class)) {
this.postInit();
Expand Down Expand Up @@ -193,12 +197,17 @@ public TreeAnnotator createTreeAnnotator() {
realChecker, realTypeFactory, variableAnnotator, slotManager));
}

@Override
protected QualifierDefaults createQualifierDefaults() {
return new InferenceQualifierDefaults(elements, this);
}

public AnnotationMirror getVarAnnot() {
return varAnnot;
}

public ConstantToVariableAnnotator getNewConstantToVariableAnnotator() {
return new ConstantToVariableAnnotator(realTop, varAnnot, variableAnnotator, slotManager);
public ConstantToVariableAnnotator getConstantToVariableAnnotator() {
return constantToVariableAnnotator;
}

@Override
Expand Down Expand Up @@ -521,7 +530,7 @@ protected void addComputedTypeAnnotations(Tree tree, AnnotatedTypeMirror type, b
}

// typeAnnotator.visit(type, null);
// defaults.annotate(tree, type);
defaults.annotate(tree, type);

if (iUseFlow) {
CFValue as = getInferredValueFor(tree);
Expand Down
2 changes: 1 addition & 1 deletion src/checkers/inference/InferenceTreeAnnotator.java
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ public Void visitInstanceOf(final InstanceOfTree instanceOfTree, final Annotated
AnnotatedPrimitiveType instanceOfType = (AnnotatedPrimitiveType) realTypeFactory.getAnnotatedType(instanceOfTree);
atm.replaceAnnotations(instanceOfType.getAnnotations());

ConstantToVariableAnnotator constantToVarAnnotator = infTypeFactory.getNewConstantToVariableAnnotator();
ConstantToVariableAnnotator constantToVarAnnotator = infTypeFactory.getConstantToVariableAnnotator();
constantToVarAnnotator.visit(atm);

// atm is always boolean, get actual tested type
Expand Down
8 changes: 8 additions & 0 deletions src/checkers/inference/SlotManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ public interface SlotManager {
*/
ExistentialVariableSlot createExistentialVariableSlot(VariableSlot potentialSlot, VariableSlot alternativeSlot);

/**
* Create a VarAnnot equivalent to the given realQualifier.
*
* @return a VarAnnot equivalent to the given realQualifier.
*
*/
AnnotationMirror createEquivalentVarAnno(final AnnotationMirror realQualifier);

/** Return the variable identified by the given id or null if no such variable has been added */
VariableSlot getVariable( int id );

Expand Down
22 changes: 7 additions & 15 deletions src/checkers/inference/VariableAnnotator.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ public class VariableAnnotator extends AnnotatedTypeScanner<Void,Tree> {
private final AnnotationMirror realTop;

private final ExistentialVariableInserter existentialInserter;
private final ConstantToVariableAnnotator constantToVariableAnnotator;
private final ImpliedTypeAnnotator impliedTypeAnnotator;

public VariableAnnotator(final InferenceAnnotatedTypeFactory typeFactory,
Expand All @@ -166,8 +165,6 @@ public VariableAnnotator(final InferenceAnnotatedTypeFactory typeFactory,
varAnnot, this);

this.impliedTypeAnnotator = new ImpliedTypeAnnotator(inferenceTypeFactory, slotManager, existentialInserter);
this.constantToVariableAnnotator = new ConstantToVariableAnnotator(realTop, varAnnot, this,
slotManager);
}


Expand Down Expand Up @@ -261,7 +258,7 @@ private VariableSlot createVariable(final AnnotationLocation location) {
}

public ConstantSlot createConstant(final AnnotationMirror value, final Tree tree) {
final ConstantSlot constantSlot = createConstant(value);
final ConstantSlot constantSlot = slotManager.createConstantSlot(value);

// if (path != null) {
// Element element = inferenceTypeFactory.getTreeUtils().getElement(path);
Expand All @@ -279,11 +276,6 @@ public ConstantSlot createConstant(final AnnotationMirror value, final Tree tree
return constantSlot;
}

public ConstantSlot createConstant(final AnnotationMirror value) {
final ConstantSlot constantSlot = slotManager.createConstantSlot(value);
return constantSlot;
}

/**
* ExistentialVariableSlot are used when a constraint should appear in an ExistentialConstraint.
* Between two variable slots (a potential and alternative) we only ever need to create
Expand Down Expand Up @@ -512,7 +504,7 @@ private VariableSlot addPrimaryVariable(AnnotatedTypeMirror atm, final Tree tree
AnnotationLocation location = treeToLocation(tree);
variable = replaceOrCreateEquivalentVarAnno(atm, tree, location);
final Pair<VariableSlot, Set<? extends AnnotationMirror>> varATMPair = Pair
.<VariableSlot, Set<? extends AnnotationMirror>> of(variable,
.of(variable,
AnnotationUtils.createAnnotationSet());

treeToVarAnnoPair.put(tree, varATMPair);
Expand Down Expand Up @@ -566,11 +558,11 @@ private VariableSlot replaceOrCreateEquivalentVarAnno(AnnotatedTypeMirror atm, T
ErrorReporter.errorAbort("The annotation(s) on the given type is neither VarAnno nor real qualifier!"
+ "Atm is: " + atm + " annotations: " + atm.getAnnotations());
}
varSlot = constantToVariableAnnotator.createConstantSlot(realQualifier);
varSlot = slotManager.createConstantSlot(realQualifier);
} else if (tree != null && realChecker.isConstant(tree) ) {
// Considered constant by real type system
realQualifier = realTypeFactory.getAnnotatedType(tree).getAnnotationInHierarchy(realTop);
varSlot = constantToVariableAnnotator.createConstantSlot(realQualifier);
varSlot = slotManager.createConstantSlot(realQualifier);
} else {
varSlot = createVariable(location);
}
Expand All @@ -580,7 +572,7 @@ private VariableSlot replaceOrCreateEquivalentVarAnno(AnnotatedTypeMirror atm, T
}

public VariableSlot getTopConstant() {
return constantToVariableAnnotator.createConstantSlot(realTop);
return slotManager.createConstantSlot(realTop);
}

/**
Expand Down Expand Up @@ -637,7 +629,7 @@ public Void visitDeclared(final AnnotatedDeclaredType adt, final Tree tree) {
if (varElement.getKind() == ElementKind.ENUM_CONSTANT) {
AnnotatedTypeMirror realType = realTypeFactory.getAnnotatedType(tree);
CopyUtil.copyAnnotations(realType, adt);
constantToVariableAnnotator.visit(adt);
inferenceTypeFactory.getConstantToVariableAnnotator().visit(adt);
} else {
// calls this method again but with a ParameterizedTypeTree
visitDeclared(adt, ((VariableTree) tree).getType());
Expand Down Expand Up @@ -1047,7 +1039,7 @@ private void annotateArrayLiteral(AnnotatedArrayType type, NewArrayTree tree) {
if (path == null || enclosedByAnnotation(path)) {
AnnotatedTypeMirror realType = realTypeFactory.getAnnotatedType(tree);
CopyUtil.copyAnnotations(realType, type);
constantToVariableAnnotator.visit(type);
inferenceTypeFactory.getConstantToVariableAnnotator().visit(type);
return;
} // else

Expand Down
43 changes: 10 additions & 33 deletions src/checkers/inference/util/ConstantToVariableAnnotator.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package checkers.inference.util;

import checkers.inference.SlotManager;
import checkers.inference.VariableAnnotator;
import checkers.inference.model.AnnotationLocation;
import checkers.inference.model.ConstantSlot;
import javax.lang.model.element.AnnotationMirror;

import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.visitor.AnnotatedTypeScanner;
import org.checkerframework.javacutil.ErrorReporter;

import javax.lang.model.element.AnnotationMirror;
import checkers.inference.InferenceMain;
import checkers.inference.SlotManager;


/**
Expand All @@ -21,27 +18,11 @@ public class ConstantToVariableAnnotator extends AnnotatedTypeScanner<Void, Void

private final AnnotationMirror realTop;
private final AnnotationMirror varAnnot;
private final VariableAnnotator variableAnnotator;
private final SlotManager slotManager;
private static final SlotManager slotManager = InferenceMain.getInstance().getSlotManager();

public ConstantToVariableAnnotator(AnnotationMirror realTop, AnnotationMirror varAnnot,
VariableAnnotator variableAnnotator, SlotManager slotManager) {
public ConstantToVariableAnnotator(AnnotationMirror realTop, AnnotationMirror varAnnot) {
this.realTop = realTop;
this.varAnnot = varAnnot;
this.variableAnnotator = variableAnnotator;
this.slotManager = slotManager;
}

@Override
public Void visitExecutable(AnnotatedExecutableType type, Void aVoid) {
scan(type.getReturnType(), null);
if (type.getReceiverType() != null) {
scanAndReduce(type.getReceiverType(), null, null);
}
scanAndReduce(type.getParameterTypes(), null, null);
scanAndReduce(type.getThrownTypes(), null, null);
scanAndReduce(type.getTypeVariables(), null, null);
return null;
}

@Override
Expand All @@ -62,13 +43,14 @@ protected Void scan(AnnotatedTypeMirror type, Void aVoid) {
* @param type A type annotated in the "real qualifier hierarch"
*/
protected void addVariablePrimaryAnnotation(final AnnotatedTypeMirror type) {
if (type.getAnnotationInHierarchy(varAnnot) != null) {
if (type.isAnnotatedInHierarchy(varAnnot)) {
return;
}

AnnotationMirror realQualifier = type.getAnnotationInHierarchy(realTop);
ConstantSlot varSlot = variableAnnotator.createConstant(realQualifier);
type.replaceAnnotation(slotManager.getAnnotation(varSlot));
AnnotationMirror equivalentVarAnno = slotManager.createEquivalentVarAnno(realQualifier);
type.addAnnotation(equivalentVarAnno);
type.removeAnnotation(realQualifier);
//
// for (Entry<Class<? extends Annotation>, VariableSlot> qualToVarAnnot : constantToVarAnnot.entrySet()) {
//
Expand All @@ -80,9 +62,4 @@ protected void addVariablePrimaryAnnotation(final AnnotatedTypeMirror type) {
//
// ErrorReporter.errorAbort("Could not find VarAnnot for real qualifier: " + realQualifier + " type =" + type);
}

public ConstantSlot createConstantSlot(final AnnotationMirror realQualifier) {
ConstantSlot varSlot = variableAnnotator.createConstant(realQualifier);
return varSlot;
}
}
Loading

0 comments on commit d307fc6

Please sign in to comment.