-
Notifications
You must be signed in to change notification settings - Fork 348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support unique classes (Fixes #3313) #3336
Changes from 23 commits
fd536c4
126014d
b2b91eb
1b756c0
4edfc68
dde03ef
22462e0
017082b
4b36609
fa03246
97ff12d
629a1a9
25b602a
91d8372
eb424fd
c324094
941cab0
d71f608
53a6c12
ff1b9e4
135b266
db149b9
e64f002
167d9cc
cf45fd6
f3d2479
9b60d82
1335ba2
1da4103
7b191e9
bd1fe05
37976e8
1523897
79f35f1
f6e67cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,11 @@ | ||
package org.checkerframework.common.aliasing; | ||
|
||
import com.sun.source.tree.ExpressionTree; | ||
import com.sun.source.tree.MethodInvocationTree; | ||
import com.sun.source.tree.MethodTree; | ||
import com.sun.source.tree.NewArrayTree; | ||
import com.sun.source.tree.ThrowTree; | ||
import com.sun.source.tree.Tree; | ||
import com.sun.source.tree.*; | ||
import com.sun.source.tree.Tree.Kind; | ||
import com.sun.source.tree.VariableTree; | ||
import com.sun.source.util.TreePath; | ||
import java.util.List; | ||
import javax.lang.model.element.ExecutableElement; | ||
import javax.lang.model.element.VariableElement; | ||
import java.util.Set; | ||
import javax.lang.model.element.*; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not use wildcard imports. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We had this before: #3336 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have changed the import statement in my latest commit. Turns out my IDE automatically * imports whenever it imports more than 3 packages. |
||
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey; | ||
import org.checkerframework.common.aliasing.qual.LeakedToResult; | ||
import org.checkerframework.common.aliasing.qual.NonLeaked; | ||
|
@@ -271,7 +265,37 @@ private boolean canBeLeaked(Tree exp) { | |
AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(exp); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should also update the javadoc with the change in behavior. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have changed the documentation for the canBeLeaked method in my latest commit |
||
boolean isMethodInvocation = exp.getKind() == Kind.METHOD_INVOCATION; | ||
boolean isNewClass = exp.getKind() == Kind.NEW_CLASS; | ||
return type.hasExplicitAnnotation(Unique.class) && !isMethodInvocation && !isNewClass; | ||
boolean isUniqueClassFlag = isUniqueClass(exp); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have removed the flag part from the variable name in my latest commit |
||
if (isUniqueClassFlag) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this just be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe extract the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have separated the (isUniqueClass || type.hasExplicitAnnotation(Unique.class) into a separate local variable and documented the logic. |
||
return type.hasAnnotation(Unique.class) && !isMethodInvocation && !isNewClass; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I see that was a redundant check. I have not used it in my latest commits |
||
} else { | ||
return type.hasExplicitAnnotation(Unique.class) && !isMethodInvocation && !isNewClass; | ||
} | ||
} | ||
|
||
/** | ||
* Returns true if class of tree expression {@code exp} has type {@code @Unique} | ||
* | ||
* @param exp the Tree to check | ||
* @return boolean true if class if unique and false otherwise | ||
*/ | ||
private boolean isUniqueClass(Tree exp) { | ||
AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(exp); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The caller already computed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I replaced exp with type as an argument in the isUniqueClass in my latest commit |
||
Element el = types.asElement(type.getUnderlyingType()); | ||
if (el != null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be easier as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have separated out el and annoMirrors checks instead of the nested if conditions. If either of them is null, the method returns false |
||
Set<AnnotationMirror> annoMirrors = atypeFactory.getDeclAnnotations(el); | ||
if (annoMirrors != null) { | ||
for (AnnotationMirror mirror : annoMirrors) { | ||
if (mirror.getAnnotationType() | ||
.asElement() | ||
.getSimpleName() | ||
.contentEquals("Unique")) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, don't use Strings for things like this. Can you use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have used the AnnotationUtils.containtsSameByClass method in my latest commit |
||
return true; | ||
} | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
private boolean isInUniqueConstructor() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import org.checkerframework.common.aliasing.qual.Unique; | ||
|
||
@Unique class Data { | ||
@SuppressWarnings("unique.leaked") | ||
Data() {} // All objects of Data are now @Unique | ||
} | ||
|
||
class Demo { | ||
void check(Data p) { // p is @Unique Data Object | ||
// :: error: (unique.leaked) | ||
Data y = p; // @Unique p is leaked | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the type of the left-hand side important? Can you add another method that does
which I guess should also give a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ping. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, the type of the left-hand side isn't important. However, the method doesn't give an error, even when Data is explicitly annotated as @unique. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure how you mean this. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In the code given above, Object z = p; does raise an error. Hence, the left hand side isn't important. However, the check2 function (where you are returning a @unique Data as an Object) doesn't raise an error both in the typetools/master and in my modified code, even if the Data p is explicitly annotated as @unique Data p. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, can you expand this test case with the |
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not star import.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of star import, I listed the library data types that were required in my latest commit