Skip to content

Commit

Permalink
Pull all the changes made to CF in order for PICO to work
Browse files Browse the repository at this point in the history
  • Loading branch information
topnessman committed Oct 5, 2018
1 parent 949b38f commit 3f804db
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,9 @@ public Set<Class<? extends Annotation>> getInvalidConstructorReturnTypeAnnotatio
/**
* Returns whether or not {@code field} has the invariant annotation.
*
* <p>This method is a convenience method for {@link
* #hasFieldInvariantAnnotation(AnnotatedTypeMirror)}.
* <p>This method is a convenience method for {@link *
* #hasFieldInvariantAnnotation(AnnotatedTypeMirror, VariableElement)}.
* #hasFieldInvariantAnnotation(AnnotatedTypeMirror, VariableElement)}.
*
* <p>If the {@code field} is a type variable, this method returns true if any possible
* instantiation of the type parameter could have the invariant annotation. See {@link
Expand All @@ -179,7 +180,8 @@ public Set<Class<? extends Annotation>> getInvalidConstructorReturnTypeAnnotatio
*/
protected final boolean hasFieldInvariantAnnotation(VariableTree field) {
AnnotatedTypeMirror type = getAnnotatedType(field);
return hasFieldInvariantAnnotation(type);
VariableElement fieldElement = TreeUtils.elementFromDeclaration(field);
return hasFieldInvariantAnnotation(type, fieldElement);
}

/**
Expand All @@ -192,7 +194,8 @@ protected final boolean hasFieldInvariantAnnotation(VariableTree field) {
* @param type of field that might have invariant annotation
* @return whether or not the type has the invariant annotation
*/
protected abstract boolean hasFieldInvariantAnnotation(AnnotatedTypeMirror type);
protected abstract boolean hasFieldInvariantAnnotation(
AnnotatedTypeMirror type, VariableElement fieldElement);

/**
* Creates a {@link UnderInitialization} annotation with the given type as its type frame
Expand Down Expand Up @@ -658,8 +661,7 @@ private void computeFieldAccessType(
// The receiver is not initialized for this frame and the type being computed is not
// a LHS.
// Replace all annotations with the top annotation for that hierarchy.
type.clearAnnotations();
type.addAnnotations(qualHierarchy.getTopAnnotations());
type.replaceAnnotation(qualHierarchy.getTopAnnotation(COMMITTED));
}

if (!AnnotationUtils.containsSame(declaredFieldAnnotations, NOT_ONLY_COMMITTED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ protected void markInvariantFieldsAsInitialized(
continue;
}
AnnotatedTypeMirror fieldType = atypeFactory.getAnnotatedType(field);
if (atypeFactory.hasFieldInvariantAnnotation(fieldType)) {
if (atypeFactory.hasFieldInvariantAnnotation(fieldType, field)) {
result.add(field);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,8 @@ public AnnotationMirror getFieldInvariantAnnotation() {
* @return whether or not type has the invariant annotation
*/
@Override
protected boolean hasFieldInvariantAnnotation(AnnotatedTypeMirror type) {
protected boolean hasFieldInvariantAnnotation(
AnnotatedTypeMirror type, VariableElement fieldElement) {
AnnotationMirror invariant = getFieldInvariantAnnotation();
Set<AnnotationMirror> lowerBounds =
AnnotatedTypes.findEffectiveLowerBoundAnnotations(qualHierarchy, type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class TestDiagnosticUtils {

// this regex represents how the diagnostics appear in Java source files
public static final String DIAGNOSTIC_IN_JAVA_REGEX =
"\\s*(error|fixable-error|warning|other):\\s*(\\(?.*\\)?)\\s*";
"\\s*(error|fixable-error|warning|fixable-warning|other):\\s*(\\(?.*\\)?)\\s*";
public static final Pattern DIAGNOSTIC_IN_JAVA_PATTERN =
Pattern.compile(DIAGNOSTIC_IN_JAVA_REGEX);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1575,7 +1575,7 @@ protected void checkTypecastSafety(TypeCastTree node, Void p) {
}
}

private boolean isTypeCastSafe(AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType) {
protected boolean isTypeCastSafe(AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType) {
QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();

if (castType.getKind() == TypeKind.DECLARED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ public S initialStore(
return info;
}

private void addFieldValues(
protected void addFieldValues(
S info, AnnotatedTypeFactory factory, ClassTree classTree, MethodTree methodTree) {

// Add knowledge about final fields, or values of non-final fields
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,21 @@ public void annotate(MethodInvocationTree tree, AnnotatedExecutableType type) {
atypeFactory.getReceiverType(tree), type.getReceiverType()));
}

TreePath path = atypeFactory.getPath(tree);
if (path != null) {
AnnotatedTypeMirror assignmentContext = null;
assignmentContext = TypeArgInferenceUtil.assignedTo(atypeFactory, path);

if (assignmentContext != null) {
matchingMapping =
collector.reduce2(
matchingMapping,
collector.visit(
// Actual assignment lhs type
type.getReturnType(), assignmentContext));
}
}

if (matchingMapping != null && !matchingMapping.isEmpty()) {
replacer.visit(type, matchingMapping);
} else {
Expand Down Expand Up @@ -375,6 +390,53 @@ public Map<AnnotationMirror, Set<? extends AnnotationMirror>> reduce(
return res;
}

public Map<AnnotationMirror, Set<? extends AnnotationMirror>> reduce2(
Map<AnnotationMirror, Set<? extends AnnotationMirror>> r1,
Map<AnnotationMirror, Set<? extends AnnotationMirror>> r2) {

if (r1 == null || r1.isEmpty()) {
return r2;
}
if (r2 == null || r2.isEmpty()) {
return r1;
}

Map<AnnotationMirror, Set<? extends AnnotationMirror>> res =
new HashMap<AnnotationMirror, Set<? extends AnnotationMirror>>(r1.size());
// Ensure that all qualifiers from r1 and r2 are visited.
Set<AnnotationMirror> r2remain = AnnotationUtils.createAnnotationSet();
r2remain.addAll(r2.keySet());
for (Map.Entry<AnnotationMirror, Set<? extends AnnotationMirror>> kv1 : r1.entrySet()) {
AnnotationMirror key1 = kv1.getKey();
Set<? extends AnnotationMirror> a1Annos = kv1.getValue();
Set<? extends AnnotationMirror> a2Annos = r2.get(key1);
if (a2Annos != null && !a2Annos.isEmpty()) {
r2remain.remove(key1);
Set<? extends AnnotationMirror> lubs =
// Should not always go upward. For poly return type, should
qualhierarchy.leastUpperBounds(a1Annos, a2Annos);
Iterator<? extends AnnotationMirror> a1i = a1Annos.iterator();
Iterator<? extends AnnotationMirror> a2i = a2Annos.iterator();
while (a1i.hasNext() && a2i.hasNext()) {
AnnotationMirror a1 = a1i.next();
AnnotationMirror a2 = a2i.next();
if (!qualhierarchy.isSubtype(a1, a2)) {
res.remove(
key1); // Upper bound is lower than lower bound -> no solution
} else {
res.put(key1, Collections.singleton(a1));
}
}
} else {
res.put(key1, a1Annos);
}
}
for (AnnotationMirror key2 : r2remain) {
res.put(key2, r2.get(key2));
}
return res;
}

public Map<AnnotationMirror, Set<? extends AnnotationMirror>> visit(
Iterable<? extends AnnotatedTypeMirror> types,
Iterable<? extends AnnotatedTypeMirror> actualTypes) {
Expand Down Expand Up @@ -487,6 +549,9 @@ private Map<AnnotationMirror, Set<? extends AnnotationMirror>> mapQualifierToPol
} else if (actualType.hasAnnotation(poly)) {
AnnotationMirror typeQual = type.getAnnotationInHierarchy(top);
result.put(poly, Collections.singleton(typeQual));
} else if (type.hasAnnotation(poly)) {
AnnotationMirror typeQual = actualType.getAnnotationInHierarchy(top);
result.put(poly, Collections.singleton(typeQual));
}
}
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,23 @@ public static AnnotatedTypeMirror assignedTo(AnnotatedTypeFactory atypeFactory,
res = atypeFactory.getAnnotatedType(variable);
} else if (assignmentContext instanceof MethodInvocationTree) {
MethodInvocationTree methodInvocation = (MethodInvocationTree) assignmentContext;
ExecutableElement methodElt = TreeUtils.elementFromUse(methodInvocation);
// TODO move to getAssignmentContext
if (methodInvocation.getMethodSelect() instanceof MemberSelectTree
&& ((MemberSelectTree) methodInvocation.getMethodSelect()).getExpression()
== path.getLeaf()) {
return null;
// treepath's leaf is assigned to the method declared receiver type
AnnotatedExecutableType declMethodType = atypeFactory.getAnnotatedType(methodElt);
return declMethodType.getReceiverType();
} // Removing above if block causes StackOverflowException via getReceiverType ->
// assignedTo -> getReceiverType loop!
AnnotatedTypeMirror receiver = null;
try {
receiver = atypeFactory.getReceiverType(methodInvocation);
} catch (Throwable e) {
new Object();
}
ExecutableElement methodElt = TreeUtils.elementFromUse(methodInvocation);
AnnotatedTypeMirror receiver = atypeFactory.getReceiverType(methodInvocation);

res =
assignedToExecutable(
atypeFactory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,20 @@ public static Tree getAssignmentContext(final TreePath treePath) {
case RETURN:
case VARIABLE:
return parent;
case MEMBER_SELECT:
// Also check case when treepath's leaf tree is used as methohd invocation's actual
// receiver
// If so, return that method invocation tree too as the assignment context tree
// rather than
// null as we did before
TreePath grandParentPath = parentPath.getParentPath();
if (grandParentPath != null
&& grandParentPath.getLeaf() instanceof MethodInvocationTree) {
return grandParentPath.getLeaf();
} else {
return null;
}

default:
// 11 Tree.Kinds are CompoundAssignmentTrees,
// so use instanceof rather than listing all 11.
Expand Down

0 comments on commit 3f804db

Please sign in to comment.