-
Notifications
You must be signed in to change notification settings - Fork 26
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
Figure out and document whether module-level @NullMarked
helps users who don't declare a module
#496
Comments
at least on Java 11+ annotation processors, |
Hmm, thanks. Do you have any code that you can share to show that behavior? I finally gave it a shot, myself, and I see "unnamed module" when the class comes from the classpath. Code:
Setup:
Module path:
Classpath:
|
I'm wagering why @SentryMan and I see the module is because our stuff (we both write APT plugins) are running as an annotation processor and not a compiler plugin. Whatever the case build systems barely support So that might be the issue as well. I don't have time today to make an experimental APT project but @SentryMan might be able to. If not I will later this week. |
@cpovirk Can you try putting the plugin on the classpath and or regular Basically we have a nice 2x2 grid of combinations that need to be tried: I think but need to check but I believe if you use |
Somehow this makes me feel very ChatGPT: Certainly! Here are the results for putting the plugin on the classpath or regular (tl;dr I'm still seeing "unnamed module.")
Module path:
Classpath:
Classpath with the annotation processor also on the classpath. (I think my brain had blocked out the knowledge that that was possible :))
|
FWIW @cpovirk you seem more effective than Chat GPT or at least the free version 😄 Thanks for doing that! I will have to figure out someway to make it up as I do have projects that have modules with annotation processors running on classpath that definitely access module-info so I will have to look how they work! Its actually one of the core configuration mechanisms of JStachio as it does a similar crawl up the enclosing stuff as JSpecify. |
It just occurred to me that I don't actually check if it is a named module. I just check to see if an annotation is on the module and it does seem to find that. I know that works because our Spring Example app has an important annotation: https://github.com/jstachio/jstachio/blob/ab86b11599c62589fe4daa21bad90d41ce57f1f6/opt/jstachio-spring-example/src/main/java/module-info.java#L29 And the annotation processor is on the classpath: https://github.com/jstachio/jstachio/blob/ab86b11599c62589fe4daa21bad90d41ce57f1f6/opt/jstachio-spring-example/pom.xml#L18 In maven if you just have an APT as a dependency pre Java 21 aka before Anyway tonight I promise I will get on this to figure out what is going on at least on my end. |
Ah, that's interesting. Maybe an annotation on one module can affect the entire unnamed module? (Spoiler: maybe still no? But there are other scenarios that also seem worth testing.) To test some more, I hacked up error_prone_annotations: diff --git a/annotations/src/main/java/com/google/errorprone/annotations/Keep.java b/annotations/src/main/java/com/google/errorprone/annotations/Keep.java
index 8288b63d9d..d1e0430faa 100644
--- a/annotations/src/main/java/com/google/errorprone/annotations/Keep.java
+++ b/annotations/src/main/java/com/google/errorprone/annotations/Keep.java
@@ -19,6 +19,7 @@ import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.MODULE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@@ -37,6 +38,6 @@ import java.lang.annotation.Target;
* should also be kept.
*/
@Documented
-@Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, TYPE})
+@Target({ANNOTATION_TYPE, CONSTRUCTOR, FIELD, METHOD, MODULE, TYPE})
@Retention(RUNTIME)
public @interface Keep {}
diff --git a/annotations/src/main/java/module-info.java b/annotations/src/main/java/module-info.java
index 3dccd22910..65a0928225 100644
--- a/annotations/src/main/java/module-info.java
+++ b/annotations/src/main/java/module-info.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+@com.google.errorprone.annotations.Keep
open module com.google.errorprone.annotations {
requires java.compiler;
And it looks like I can see the
Maybe what you're seeing with JStachio is that you can pick up annotations from the module you're compiling even if your dependencies are in the unnamed module? That much I would have hoped for, and I should make sure that any docs that we write can't be read as warnings about that case. |
Yes I believe that is the case but I kind of thought you were testing that but now re-reading the title of this post I think I was confused. You are concerned non-modular jars/setup/tools cannot sniff the Anway I finally got to a computer with some level of a dev environment and did And it appears (and I forgot that Maven does this through some magic) that it will add all the libraries that you So in the Spring JStachio example the APT module is actually on the classpath and not the I'm remiss that I forgot that as I even documented that: https://jstach.io/doc/jstachio/current/apidocs/#maven_classpath My apologies on forgetting that. I must admit it is hard to remember what does and doesn't work with modules. |
I think where @SentryMan and myself got confused is the tool in this case the annotation processor does not need to run on the module-path but the code being analyzed does. Otherwise you need to do what Maven/Gradle does which I assume ASM based (your second bullet point at the top of this post). Per the doc:
|
Yep, that's it. I'll take this as another vote for being very, very clear about exactly what circumstances we're warning people about :)
My solution to that problem has been to never learn in the first place :) But that's not serving me well at the moment.... (TIL Your point about Maven's ASM magic also shows me that my bytecode-rewriting concerns are misplaced: The time when most users care about nullness annotation is compile-time, and there's no bytecode-rewriting magic going on then: If the jar has a On the other hand, I know less about how compile-time plugins (meaning mainly annotation processors) might look for a corresponding |
(Oops, I guess someone had taught us this long ago, but I'd forgotten: #34 (comment).) |
@cpovirk I don't blame you. I was relooking at my old comments regarding this that I completely forgot as well 😆 . Damn modules be complicated. |
@xenoterracide asks: Suppose that I put
@NullMarked
in my library'smodule-info
. Then:@msridhar is optimistic that tools will still recognize it.
I am more pessimistic. I worry on two levels:
@NullMarked
is (in javac terms) to keep callinggetEnclosingElement()
until there are no enclosing elements left. I would assume thatpkg.getEnclosingElement()
will not return the module for a package unless the package actually comes from the module path. (I have not verified this.) If so, then tools would need to go out of their way to look for themodule-info
for the package. (And if not all the tools you use do this (e.g., Kotlin, IntelliJ, a build-time Java checker), then you'll get inconsistent behavior.)module-info
for the package" is technically not a well-defined question unless Java "loaded the module for real." In practice, you could probably look up the jar/directory that contains a given package (or a specific class from that package, since multiple jars/directories might contain classes from the same package!). Then you could look in that jar formodule-info.class
(possibly underMETA-INF/versions/9
or similar) and read the file with ASM. But I wouldn't be shocked if that weren't technically enough. Might the jar come from an in-memory filesystem that you might not have access to? Even if it comes from the filesystem, might it be in some kind of special bundle that you need to understand? And even if it comes from a plain old jar, what if the system is doing some wild bytecode rewriting during class loading, which should have gotten applied to themodule-info
but never did because Java didn't load themodule-info
? Does anything change if we're talking about the annotation-processor module path? I suspect that this is all not a big practical concern, but it's at least going to be a reason that tool authors are not enthusiastic about putting in any special handling for the non-JPMS case: It feels like another case in which people may want to avoid "swimming upstream."Once we know more about this, we should write something for tool authors and something for users (possibly even in the Javadoc). It's very possible that the advice for users will end up being: "You don't actually want to rely on module-level
@NullMarked
for libraries that you publicly release; it's best reserved for closed systems, like if your company has fully bought in to modules."The text was updated successfully, but these errors were encountered: