Skip to content
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

JSpecify and annotated packages option #574

Open
msridhar opened this issue Feb 16, 2022 · 10 comments
Open

JSpecify and annotated packages option #574

msridhar opened this issue Feb 16, 2022 · 10 comments
Labels
jspecify Related to support for jspecify standard (see jspecify.dev)

Comments

@msridhar
Copy link
Collaborator

Once we land support for @NullMarked, it seems the AnnotatedPackages option would no longer be absolutely necessary. If we end up adding a flag for "JSpecify mode", we could say that at least one of the JSpecify or AnnotatedPackages options should be given (and giving both would of course be supported). We could instead just make AnnotatedPackages optional, but I'm concerned that could lead to confusion for users who are also not using @NullMarked.

@msridhar msridhar added the jspecify Related to support for jspecify standard (see jspecify.dev) label Feb 16, 2022
@bannmann
Copy link

I started adopting JSpecify annotations in a 20K LOC code base. In line with the recommendations in the JSpecify user guide, I planned to annotate one package after another, adding @NullMarked to each package once I finished it.

Having learned that NullAway does not yet support @NullMarked, once I finish annotating a package, I will now add it to the AnnotatedPackages option in addition to flagging the package itself as @NullMarked. The eventual goal would of course be to put @NullMarked on the module level.

Regarding configuration, I share @msridhar's concerns about just making AnnotatedPackages optional.

I suggest adding a second option to control this behavior. It could be called e.g. NullMarkedMode and its values would look something like this:

  • UsePackageAllowList makes NullAway require the AnnotatedPackages option, just like today (the default value)
  • OnlyAnnotatedCode limits NullAway to those packages / modules that have JSpecify @NullMarked annotations. The AnnotatedPackages option would not be required.
    • Whether that mode can be further restricted by AnnotatedPackages is up for debate. Personally, I don't see a point in that and would want to avoid the confusion by having AnnotatedPackages throw an error if it's used together with this mode.

@msridhar
Copy link
Collaborator Author

msridhar commented Apr 21, 2024

@bannmann NullAway should support @NullMarked and @NullUmarked now! Can you open a separate bug if you're seeing that it's not supported? The only place where support likely won't work yet is on modules, but I would expect packages to work.

@msridhar
Copy link
Collaborator Author

Regarding your suggested configurations options @bannmann I like them! We are going to have a messy and probably somewhat lengthy transition over to JSpecify checking, with an unfortunate amount of configuration, in order to not break existing users. I think your options fit well with such a transition plan. If, in your experimentation, it would be beneficial to have a flag that forbids AnnotatedPackages so NullAway relies entirely on @NullMarked, let us know and we can try to add it.

@msridhar
Copy link
Collaborator Author

@pemistahl @beatbrot continuing from #1042, see the discussion above. We now have a JSpecify mode flag, and we also support @NullMarked and @NullUnmarked.

@pemistahl if you are seeing a case where @NullMarked is not working, please open a separate issue on that. It should work on packages, classes, and methods in NullAway.

Note that we still require the AnnotatedPackages flag right now and crash without it. I am open to adding a flag like OnlyAnnotatedCode (I might call it OnlyNullMarkedCode) and then requiring either AnnotatedPackages or OnlyAnnotatedCode (this could be independent of JSpecify mode actually). I think AnnotatedPackages is still quite useful since it treats packages as hierarchical, whereas JSpecify does not. So if you have packages com.foo.p1 and com.foo.p2, you can specify AnnotatedPackages to be com.foo and both will be treated as annotated. With @NullMarked you would need to add two package-info.java files, one in each package. Some companies have dozens or hundreds of packages so this could make a big difference. (If you're using Java modules you could make the whole module @NullMarked but NullAway doesn't support that yet and adoption seems to be low.)

Any thoughts?

@beatbrot
Copy link

beatbrot commented Sep 17, 2024

Yeah, I agree with your take @msridhar :) At my company, we have several hundreds of packages and annotating each with @NullMarked would be a huge pain for us. But since AnnotatedPackages is hierachical , it is enough for us to just specify com.<companyname> and everything counts as NullMarked.

Some parts of our codebase however is exported as API. And for this small part, we want to use @NullMarked, so that our API consumers don't have to configure their tools at all. So the ideal solution for us would be if NullAway would understand both :)

Edit: Also, I don't see us ever adopting Modules, so while the idea is nice to NullMark a module, it won't help us :)

@pemistahl
Copy link

So the ideal solution for us would be if NullAway would understand both.

Exactly, that's what I have in mind, too. I want to be able to decide whether to check on package level or on class level. We have an application with a very large code base without any static null checks. We would like to gradually add static null checks to this application but we don't want to be enforced to do this for an entire package at a time. Class by class would be much more feasible for us. @msridhar Can you please make this possible?

@msridhar
Copy link
Collaborator Author

msridhar commented Sep 18, 2024

Exactly, that's what I have in mind, too. I want to be able to decide whether to check on package level or on class level. We have an application with a very large code base without any static null checks. We would like to gradually add static null checks to this application but we don't want to be enforced to do this for an entire package at a time. Class by class would be much more feasible for us. @msridhar Can you please make this possible?

This should already be possible. @NullMarked on classes is supported, modulo any remaining bugs. So, for now, you could do the following:

  1. Set AnnotatedPackages to be some dummy value, not corresponding to any real package in your code or libraries
  2. Write @NullMarked on packages or classes as desired, and they should be checked by NullAway.

This issue is about getting rid of 1 and instead providing an option explicitly indicating you don't want to use AnnotatedPackages.

@pemistahl if the above does not work, could you please file a separate issue, ideally with a standalone reproducer? We will take a look.

EDIT: also note that you should not need to pass the JSpecify mode flag for the above to work; @NullMarked should be recognized out of the box.

@pemistahl
Copy link

You are right @msridhar, it works to set AnnotatedPackages to the empty string. Then I can work with @NullMarked alone to enable the checks on class level. Thanks for your help.

@sdeleuze
Copy link

sdeleuze commented Dec 23, 2024

@msridhar The Spring team is interested by this issue as currently we annotate only packages where null-safety is defined with @NullMarked but we have to duplicate that information with NullAway package configuration. As we plan to extend JSpecify and NullAway to other Spring projects, having a unique source of truth would be great.

Configuring NullAway:AnnotatedPackages to an empty string works as expected, and I will use that in Spring Framework for now, but that looks a bit hackish to be promoted as a general guideline, so a proper flag to enable this (allowing the user to choose between specifying packages or analysis of @NullMarked / @NullUnmaked would be a useful enhancement IMO.

We would also be ok with enabling @NullMarked detection if no package has been configured. I think you consider this is maybe too surprising for users and given the fact that support for this is not complete (Spring @NonNullApi is not supported due to #633 for example), maybe that's indeed better to have an explicit configuration for now. But middle/long term when hopefully JSpecify will be more ubiquitious and/or #633 fixed, would make sense from my POV as a default behavior.

sdeleuze added a commit to sdeleuze/spring-framework that referenced this issue Dec 23, 2024
This commit replaces NullAway package configuration by package-level
`@NullMarked` detection by configuring `NullAway:AnnotatedPackages` to
an empty string.

NullAway configuration should be refined to use a proper flag instead
once uber/NullAway#574 is fixed.

See spring-projectsgh-28797
@msridhar
Copy link
Collaborator Author

@sdeleuze thanks for the feedback. I can prioritize adding a flag like OnlyNullMarkedCode that, if provided, makes AnnotatedPackages optional. And, once JSpecify is more ubiquitous, maybe we can even make OnlyNullMarkedCode optional.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
jspecify Related to support for jspecify standard (see jspecify.dev)
Projects
None yet
Development

No branches or pull requests

5 participants