-
Notifications
You must be signed in to change notification settings - Fork 288
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
External Library Models: Adding support for Nullable upper bounds of Generic Type parameters #949
External Library Models: Adding support for Nullable upper bounds of Generic Type parameters #949
Conversation
…ernal library models
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #949 +/- ##
============================================
- Coverage 86.17% 85.97% -0.20%
- Complexity 2037 2046 +9
============================================
Files 81 82 +1
Lines 6691 6760 +69
Branches 1290 1301 +11
============================================
+ Hits 5766 5812 +46
- Misses 515 536 +21
- Partials 410 412 +2 ☔ View full report in Codecov by Sentry. |
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.
I have a few initial comments. I got lost reviewing the changes under nullaway/src/main/java/com/uber/nullaway/handlers
. Can you describe the purpose of the new StubxCacheUtil
class and how the refactored code works, for both old JarInfer stubs and newly generated ones?
...or/src/main/resources/sample_annotated/src/com/uber/nullaway/libmodel/AnnotationExample.java
Outdated
Show resolved
Hide resolved
...r-integration-test/src/test/java/com/uber/nullaway/libmodel/LibraryModelIntegrationTest.java
Show resolved
Hide resolved
.../library-model-generator/src/main/java/com/uber/nullaway/libmodel/LibraryModelGenerator.java
Outdated
Show resolved
Hide resolved
.../library-model-generator/src/main/java/com/uber/nullaway/libmodel/LibraryModelGenerator.java
Outdated
Show resolved
Hide resolved
.../library-model-generator/src/main/java/com/uber/nullaway/libmodel/LibraryModelGenerator.java
Outdated
Show resolved
Hide resolved
…nd' into library_model_nullable_upper_bound
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.
Looking mostly good! A few more comments
public static class UpperBoundExample<T> { | ||
|
||
public T getNull() { | ||
return null; | ||
} | ||
} |
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.
This is a bit weird since the method always returns null
, so the return type should really be @Nullable T
. Maybe, for readability, rewrite this class to have a public @Nullable
field and return that field from getNull()
? And maybe rename to getNullable()
? Same changes in the annotated version
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.
Should the return type of the method be @Nullable T
in the unannotated version as well or only in the annotated version?
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.
I'm not suggesting to change the return type to @Nullable T
. I'm suggesting to have a field of type T
and to return the value of that field, rather than just returning null
. Then the return type T
would be appropriate.
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.
Oh that makes sense, thanks!
for (int i = 0; i < typeParamList.size(); i++) { | ||
TypeParameter param = typeParamList.get(i); | ||
for (ClassOrInterfaceType type : param.getTypeBound()) { | ||
if (type.isAnnotationPresent(NULLABLE)) { |
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.
Don't we need logic here like we have in the isAnnotationNullable
method, to handle fully-qualified annotations?
|
||
public InferredJARModelsHandler(Config config) { | ||
super(); | ||
this.config = config; | ||
argAnnotCache = new LinkedHashMap<>(); | ||
loadStubxFiles(); | ||
this.cacheUtil = new StubxCacheUtil("JI"); |
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.
Can we put "JI"
in a suitably-named variable, for readability?
private static final Map<String, Integer> upperBoundsCache; | ||
|
||
static { | ||
StubxCacheUtil cacheUtil = new StubxCacheUtil("LM"); |
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.
Can we put "LM"
in a suitably-named variable, for readability?
…nd' into library_model_nullable_upper_bound
…cify.annotations.Nullable
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.
few more comments, mostly minor
Arrays.asList( | ||
"-d", | ||
temporaryFolder.getRoot().getAbsolutePath(), | ||
"-XepOpt:NullAway:AnnotatedPackages=com.uber")) |
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.
You need to also pass "-XepOpt:NullAway:JSpecifyMode=true"
as an argument to get the error
"import org.jspecify.annotations.Nullable;", | ||
"import com.uber.nullaway.libmodel.AnnotationExample;", | ||
"class Test {", | ||
" //TODO: We should get an error here since jar infer is not enabled", |
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.
We should already get an error here if you pass the flag above
private static final Map<String, Map<String, Map<Integer, Set<String>>>> argAnnotCache; | ||
private static final Map<String, Integer> upperBoundsCache; |
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.
These fields should not be static! That makes them mutable global state. I think they can just be instance fields and everything will work.
Really, StubxCacheUtil.getArgAnnotCache()
and StubxCacheUtil.getUpperBoundCache()
should each return ImmutableMap
s. But given the size of this PR, we can look into that change as a follow up.
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! One comment but it doesn't block this PR
@@ -69,20 +63,22 @@ private static void LOG(boolean cond, String tag, String msg) { | |||
private final Map<String, Map<String, Map<Integer, Set<String>>>> argAnnotCache; | |||
|
|||
private final Config config; | |||
private final StubxCacheUtil cacheUtil; |
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.
As a high level comment, I'm a bit unsure why we still need this handler even after we added the new library models handler. Is it because of some Android-specific logic? We should clean this up, but maybe not for this PR.
With these changes we are able to read and create library models for Nullable upper bounds of generic type parameters from externally annotated source code as shown in the below example.
Externally annotated source code example: