-
Notifications
You must be signed in to change notification settings - Fork 13
Add suppressWarnings on fields #95
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
Changes from 64 commits
44afe23
b39d72c
d820b07
6a5b075
919d2ee
38a79a6
b836928
8af3ce6
3f1009b
39958a4
af9fd46
74b7b3b
690763d
aa4ebc6
440608d
d218d29
c4e9d89
55cd6ae
7ee9a7b
28c52a1
898be2f
605171e
a0db707
cb259a3
b0b584a
aecff9f
adeaf9a
035053f
6a2898e
eba2200
97dcdbb
6aa8bcb
e7d14c7
58d38d0
3b3a821
8fdf83d
72ada16
aa68932
c818b9f
21c8112
08d9e2c
b51475a
10828a2
ba70c68
69e537b
851f8eb
2ae2b00
204ec6b
c9c1ca1
b21407e
caff1d3
bc2ad4e
94d4efe
2db1d9a
e86efcd
606de6e
a89a281
287b50f
308e7c8
1e4f627
33fe68f
2c121cc
41749d1
4a4ada6
789b608
3301cda
c3b2464
e5868d9
8fb982c
9463586
970a2ab
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 |
|---|---|---|
|
|
@@ -29,10 +29,16 @@ | |
|
|
||
| import com.google.common.base.Preconditions; | ||
| import edu.ucr.cs.riple.core.tools.TReport; | ||
| import edu.ucr.cs.riple.injector.changes.AddAnnotation; | ||
| import edu.ucr.cs.riple.injector.changes.AddMarkerAnnotation; | ||
| import edu.ucr.cs.riple.injector.changes.AddSingleElementAnnotation; | ||
| import edu.ucr.cs.riple.injector.location.OnField; | ||
| import edu.ucr.cs.riple.injector.location.OnMethod; | ||
| import edu.ucr.cs.riple.injector.location.OnParameter; | ||
| import java.nio.file.Path; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
| import org.junit.Assert; | ||
| import org.junit.Test; | ||
| import org.junit.runner.RunWith; | ||
| import org.junit.runners.JUnit4; | ||
|
|
@@ -297,6 +303,65 @@ public void deactivateInferenceTest() { | |
| .equals("org.jspecify.nullness.NullUnmarked")); | ||
| } | ||
|
|
||
| @Test | ||
| public void errorInFieldDeclarationForceResolveTest() { | ||
| coreTestHelper | ||
| .addInputDirectory("test", "fielderrorregion") | ||
| .addExpectedReports( | ||
| new TReport(new OnField("Foo.java", "test.Foo", Set.of("f1")), 2), | ||
| new TReport(new OnField("Foo.java", "test.Foo", Set.of("f2", "f3")), 2), | ||
| new TReport(new OnField("Foo.java", "test.Foo", Set.of("f0")), -1), | ||
| new TReport(new OnParameter("Bar.java", "test.Bar", "process(java.lang.Object)", 0), 1), | ||
| new TReport(new OnField("Foo.java", "test.Foo", Set.of("f4")), 1)) | ||
| .toDepth(1) | ||
| .enableForceResolve() | ||
| .start(); | ||
| Path srcRoot = | ||
| coreTestHelper | ||
| .getConfig() | ||
| .globalDir | ||
| .resolve("unittest") | ||
| .resolve("src") | ||
| .resolve("main") | ||
| .resolve("java") | ||
| .resolve("test"); | ||
| Set<AddAnnotation> expectedAnnotations = | ||
| Set.of( | ||
| new AddMarkerAnnotation( | ||
| new OnField(srcRoot.resolve("Foo.java").toString(), "test.Foo", Set.of("f0")), | ||
| "javax.annotation.Nullable"), | ||
| new AddMarkerAnnotation( | ||
| new OnMethod( | ||
| srcRoot.resolve("Bar.java").toString(), | ||
| "test.Bar", | ||
| "process(java.lang.Object)"), | ||
| "org.jspecify.nullness.NullUnmarked"), | ||
| new AddSingleElementAnnotation( | ||
| new OnField(srcRoot.resolve("Foo.java").toString(), "test.Foo", Set.of("f4")), | ||
| "SuppressWarnings", | ||
| "NullAway", | ||
| false), | ||
| new AddSingleElementAnnotation( | ||
| new OnField(srcRoot.resolve("Foo.java").toString(), "test.Foo", Set.of("f0")), | ||
|
||
| "SuppressWarnings", | ||
| "NullAway", | ||
| false), | ||
| new AddSingleElementAnnotation( | ||
| new OnField(srcRoot.resolve("Foo.java").toString(), "test.Foo", Set.of("f2", "f3")), | ||
| "SuppressWarnings", | ||
| "NullAway.Init", | ||
| false), | ||
| new AddSingleElementAnnotation( | ||
| new OnField(srcRoot.resolve("Foo.java").toString(), "test.Foo", Set.of("f1")), | ||
| "SuppressWarnings", | ||
| "NullAway.Init", | ||
| false)); | ||
| // todo: change test infrastructure to do the expected added annotations comparison internally | ||
| // in the upcoming refactoring cycle. | ||
| Assert.assertEquals( | ||
| expectedAnnotations, Set.copyOf(coreTestHelper.getConfig().log.getInjectedAnnotations())); | ||
| } | ||
|
|
||
| @Test | ||
| public void staticBlockLocalVariableInitializationTest() { | ||
| coreTestHelper | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package test; | ||
|
|
||
| import javax.annotation.Nullable; | ||
|
|
||
| public class Bar { | ||
|
|
||
| Object foo = new Object(); | ||
|
|
||
| public void deref() {} | ||
|
|
||
| @Nullable | ||
| public Bar process(Object foo) { | ||
| this.foo = foo; | ||
| receiveNonnull(foo); | ||
| return null; | ||
| } | ||
|
|
||
| public Object receiveNonnull(Object o) { | ||
| // just to keep Bar#process:foo @Nonnull | ||
| return o; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package test; | ||
|
|
||
| import javax.annotation.Nullable; | ||
|
|
||
| public class Foo { | ||
| Bar f0 = new Bar().process(null); | ||
| Bar f1; | ||
| Bar f2, f3; | ||
| @Nullable Bar nullableBar; | ||
| Bar f4 = nullableBar.process(new Object()); | ||
|
Collaborator
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. New test case looks great to me! Could we still add
Member
Author
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. Sure, please find it 970a2ab |
||
|
|
||
| Foo() { | ||
| this.f2 = new Bar(); | ||
| } | ||
|
|
||
| public void run1() { | ||
|
Member
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 we need both
Collaborator
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 believe that's so that more new errors are added than the one that is resolved by marking each field See these reports on the test case: I found the one for
Member
Author
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 exactly that was needed to produce more errors to make sure Regarding
Collaborator
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, then, but, by that logic: shouldn't it be the same number for
Member
Author
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. Actually the difference is that making fields
Collaborator
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. What is the initialization error in question here? Is it one error for I thought we were serializing individual initialization errors. If we aren't, then wouldn't any class with 2 or more constructors and at least one field which is a) not initialized, b) treated as non-null in more than one place, then result in all non-initialized fields being marked To test this, could we have an example analogous to Or am I missing a different reason why adding
Member
Author
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. @lazaroclapp Actually we only serialize one error for initialization errors per constructor which can consist of multiple fields not being initialized. The main purpose of Annotator is to minimize the number of errors the user sees from NullAway output, therefore, we do not split an error coming from NullAway into multiple errors for each uninitialized field. However, the scenario which is mentioned does not happen as we serialize a fix object for each uninitialized field and nullability of each one is investigated individually. I added a unit test for that, please see 8fb982c In this unit test,
|
||
| // to prevent annotator making f1, f3 and f4 @Nullable. | ||
| f1.deref(); | ||
| f3.deref(); | ||
| f4.deref(); | ||
| } | ||
|
|
||
| public void run2() { | ||
| // to prevent annotator making f1, f3 and f4 @Nullable. | ||
| f1.deref(); | ||
| f3.deref(); | ||
| f4.deref(); | ||
| } | ||
| } | ||
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.
Why is this parameter "called method"? Not sure I understand what this change is doing...
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.
Thank you for noticing this 3301cda. It is marking a method
@NullUnmarkedthat received a@Nullbalefor parameter which annotater rejected its parameter to be@Nullable. Renamed it.