-
Notifications
You must be signed in to change notification settings - Fork 8
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
Add @NullUnmarked on classes #134
Conversation
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.
couldn't read through the whole PR but here are a couple quick comments
annotator-core/src/main/java/edu/ucr/cs/riple/core/Annotator.java
Outdated
Show resolved
Hide resolved
@@ -263,6 +263,22 @@ private void forceResolveRemainingErrors() { | |||
// Update log. | |||
config.log.updateInjectedAnnotations(nullUnMarkedAnnotations); | |||
|
|||
// Collect @NullUnmarked annotations for classes for errors in static initialization blocks. |
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.
What about instance initialization blocks? E.g., you could have:
class Foo {
{
getNullable().toString();
}
@Nullable static Object getNullable() { return null; }
}
Will our logic handle this case too?
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.
Yes it does 🙂. Updated a unit test to verify this 47998c0
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.
Maybe we should do some quick renaming in comments / code where you refer to static blocks, to call them initializer blocks (or just INIT_BLOCK
to make it shorter)?
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.
Changed to INIT_BLOCK
cafef18
Co-authored-by: Manu Sridharan <msridhar@gmail.com>
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.
Some nits and questions, but overall it makes sense to me.
.addInput( | ||
"Super.java", | ||
"package com.uber;", | ||
"import edu.custom.NullUnmarked;", |
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.
Does the input need to have the import already or is this added automatically? Or is that outside the scope of this test harness?
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.
Actually that was not necessary, removed it 139c19a. Thank you for noticing this.
new AddMarkerAnnotation( | ||
new OnClass("Test.java", "edu.ucr.Test$1"), "edu.custom.NullUnmarked")) | ||
.start(); | ||
} |
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.
How about named inner classes? Does the logic work in that case?
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.
Yes it does, please find the added test at 71b998b
@@ -426,6 +427,9 @@ public void staticBlockLocalVariableInitializationTest() { | |||
" }", | |||
"}", | |||
"class B {", | |||
" {", | |||
" foo().hashCode();", | |||
" }", |
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 we want to test static initializer block support and instance initializer block in the same test? (if so, the test case might need renaming). Or is it perhaps better to have two separate test cases for ease of reading/debugging?
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.
Utility.readErrorsFromOutputDirectory(config, config.target, fieldDeclarationStore); | ||
nullUnMarkedAnnotations = | ||
remainingErrors.stream() | ||
.filter(error -> !error.getRegion().isInAnonymousClass()) |
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.
Not for this PR, but long term, in theory, this should try to find the containing method/initializer and add @NullUnmarked
there, no? (For anonymous inner classes). It can get complicated with nested anonymous classes and the places they can appear in, so definitely not asking for that in this PR, just wondering if that's in the roadmap for 1.3.6
or after 1.3.6
.
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.
Yes exactly. But I think the plan is to implement that in after 1.3.6
.
FieldDeclarationInfo candidate = | ||
findNodeWithHashHint(node -> node.clazz.equals(clazz), FieldDeclarationInfo.hash(clazz)); | ||
if (candidate == null) { | ||
// field is on byte code. |
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.
So, this comment (and the name of the class), reference a field
, but as far as I can tell this is looking for a class declaration and there is no field involved...
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.
Yes, this class has the required information which its main usage is to store information regarding existing classes and their fields. I have a plan for refactoring these data structures that store information regarding the structure of a code and combine them into one data structure. But the plan is to do that after the release of 1.3.6
. Please let me know if you would like me to change it. Thank you.
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.
Ok, that makes sense, but even given that, this comment right above is incorrect here, because this method is not dealing with any fields. Either remove or change the comment?
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.
So, mostly good except for a few nits. But one important thing is that I think there is an unrelated change that was added into this PR? Unless I am misunderstanding it. If it's a bug fix, it probably should be on a separate PR, unless it's related to adding @NullUnmarked
on classes.
FieldDeclarationInfo candidate = | ||
findNodeWithHashHint(node -> node.clazz.equals(clazz), FieldDeclarationInfo.hash(clazz)); | ||
if (candidate == null) { | ||
// field is on byte code. |
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.
Ok, that makes sense, but even given that, this comment right above is incorrect here, because this method is not dealing with any fields. Either remove or change the comment?
@@ -92,8 +92,7 @@ public Node(Fix root) { | |||
*/ | |||
public void setOrigins(ErrorStore errorStore) { | |||
this.origins = | |||
errorStore.getRegionsForElements( | |||
error -> error.isSingleFix() && error.getResolvingFixes().contains(root)); | |||
errorStore.getRegionsForElements(error -> error.getResolvingFixes().contains(root)); |
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.
Question: what is this change about? I don't understand either what the error.isSingleFix()
check was ensuring before, nor why are we removing it now.
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.
Origins are set of regions that triggered root fix. The condition isSingleFix
was ensuring the error has exactly one fix which is not correct, initialization errors requires multiple fixes to get resolved, therefore I removed this condition.
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.
annotator-core/src/main/java/edu/ucr/cs/riple/core/metadata/trackers/Region.java
Outdated
Show resolved
Hide resolved
annotator-core/src/main/java/edu/ucr/cs/riple/core/metadata/trackers/Region.java
Outdated
Show resolved
Hide resolved
// DepA by 3, DepB by 4 and DepC by 2. Hence, the total effect is: 5. | ||
new TReport(new OnMethod("Foo.java", "test.target.Foo", "returnNullableBad(int)"), 5), | ||
// DepA by 3, DepB by 4 and DepC by 3. Hence, the total effect is: 6. | ||
new TReport(new OnMethod("Foo.java", "test.target.Foo", "returnNullableBad(int)"), 6), |
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.
What changed that changed the effects here and why is it part of this PR about @NullUnmarked
classes? I thought effects were always computed before adding any suppressions/null-unmarked regions... is this related to the other change above I asked about? The error.isSingleFix()
check? If so, should that fix be part of this PR?
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.
…ackers/Region.java Co-authored-by: Lázaro Clapp <lazaro@uber.com>
…ackers/Region.java Co-authored-by: Lázaro Clapp <lazaro@uber.com>
@lazaroclapp This is ready for another round of review. Thank you very much. |
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.
LGTM!
This PR enables annotator to add
@NullUnmarked
annotations to suppress errors inside static initialization blocks.It will also one last step to resolve any remaining errors after suppression injections by adding
@NullUnmarked
annotation on the enclosing class.