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

Publish a GWT module #184

Open
cpovirk opened this issue Mar 24, 2021 · 7 comments
Open

Publish a GWT module #184

cpovirk opened this issue Mar 24, 2021 · 7 comments
Labels
dev development tasks, build issues...
Milestone

Comments

@cpovirk
Copy link
Collaborator

cpovirk commented Mar 24, 2021

GWT matters to relatively few Java developers, but I'm getting the impression that we're going to need to publish a GWT module if we want to be able to use it from Guava and our other projects that support GWT.

(Maybe there's an alternative in which the build systems for those projects rewrite the sources to omit our annotations, but that seems ugly, and it hides the nullness information from any tools that might consume it when compiling the client-side GWT code. Granted, I wouldn't expect nullness information to be used by the normal GWT compiler, but it could plausibly happen with the j2cl compiler.)

I have gotten Guava to depend on the Checker Framework annotations without having an official GWT module for them, but it's a bit ugly, and I suspect that users of Guava's GWT module will fail to compile because they won't see the custom GWT module we set up for the Checker Framework inside our build. And I just now discovered that the approach I was employing is wrong because it results in bundling the Checker Framework annotations into the guava-gwt jar :) [edit: now fixed] (Oddly, we were able to use the Checker Framework annotations just fine until that commit. The difference seems to be that we're now introducing an annotation in a location at which it must be a type-use annotation. Previously, we'd used Checker Framework annotations only in locations where they could also be declaration annotations.)

So my guess is that my life will be simpler if I just create a JSpecify GWT module, rather than try to hack around the absence of one and maybe end up with a crisis :)

There are at least 2 questions here:

  • What sort of jar do we publish to Maven Central for GWT? Does it have a separate artifact ID, or is it distinguished by a classifier? Does it declare a dependency on the jar that contains the compiled classes (since it itself will presumably contain only sources, if only to avoid overlap with the jar of compiled classes)?
  • How do we produce that jar from Gradle?

Possibly useful links:

@tbroyer
Copy link

tbroyer commented Mar 24, 2021

If we're only talking about annotations, then there's no need for anything special IIRC (will double-check just in case)

@cpovirk
Copy link
Collaborator Author

cpovirk commented Mar 24, 2021

The man himself! Thank you. I've been figuring we'd want to loop you in for JSpecify in general (if we hadn't at least once already?), but obviously I had you in mind for this particular question.

My experiments with Guava suggest that there's something specifically problematic about type annotations only if they appear in locations where only a type annotation would be valid (like Supplier in the linked Guava commit). But I still would have thought that would have come up by previously for us. Maybe it's only some very specific locations?

@tbroyer
Copy link

tbroyer commented Mar 25, 2021

I did a few quick tests, and the issue you have with @Nullable in Supplier in Guava is indeed related to where the annotation is being used; i.e. apparently only in type parameters or type arguments. Applying it to the return type of the get() method for example works (it doesn't matter whether it's a type variable), and you only need the annotation bytecode in GWT's classpath, annotation source code is not required.

For Guava, I would suggest doing something similar to what Dagger does for javax.inject (note that in the case of Dagger, the issue is with Provider, not with annotations); i.e. include an org/checkerframework/checker/nullness/qual/Qual.gwt.xml in the guava-gwt JAR, add a matching <inherits … /> in com/google/common/base/Base.gwt.xml, and a dependency to both the binary and source JARs of checker-qual. To keep that checkerframework module the most "internal" to Guava as possible (avoid conflicts with other libs that could do the same), you could name it GuavaQual.gwt.xml instead of Qual.gwt.xml (name doesn't really matter as long as the <inherits/> matches), and for forward-compatibility you could add an <includes name="Nullable.java" /> into the <source path=""/> to only include the file that you need (other similar modules could include other files, GWT will merge those lists)

For JSpecify, to play safe (particularly given that it has zero dependency), you'd only need to have an org/jspecify/JSpecify.gwt.xml or org/jspecify/nullness/Nullness.gwt.xml file in the JAR (you could even put it in the source JAR actually; or do like Truth and make a GWT-specific JAR) with <module><source path=""/></module> (see https://github.com/google/dagger/blob/master/gwt/javax/inject/Inject.gwt.xml).

The main (maybe only) difference between Truth and Guava/Dagger approaches is with transitive dependencies. Truth's way uses the same POM for both flavors, so it cannot declare additional GWT-specific dependencies (such as source JARs); whereas Guava and Dagger both provide artifacts at separate coordinates, where the POM can then declare additional dependencies. Using Truth with GWT means adding two dependencies (the binary JAR and the GWT-specific JAR), whereas with Guava or Dagger you add the dependency to the GWT-specific artifact, which will pull the "normal" artifact transitively (for JavaC, and annotations, for which GWT needs the bytecode).

@netdpb netdpb added this to the 1.0 milestone Sep 14, 2021
@cpovirk
Copy link
Collaborator Author

cpovirk commented Oct 20, 2021

I don't think we have an Official Process yet in place for moving issues between milestones, so I'm just going to mark this as post-1.0 unilaterally and then attempt to justify myself :)

As part of Guava 31.0.1, I changed our build process to strip @Nullable annotations from the GWT sources. That means that Guava can switch to JSpecify annotations even if those annotations don't include a GWT module. (If we do that, we'd probably technically also want to strip @NullMarked from the GWT sources. But if we forget, the stakes are pretty low.)

It will still be nice to publish a JSpecify GWT module eventually (and maybe we'll even do it before 1.0, since it doesn't sound too hard), but anything we can do after 1.0 is worth considering doing after 1.0.

@cpovirk cpovirk modified the milestones: 1.0, Post-1.0 Oct 20, 2021
@cpovirk
Copy link
Collaborator Author

cpovirk commented May 16, 2022

(Another possible complication here is ElementType.MODULE, which we might need to have added to the GWT copy of ElemenType. But that sounds straightforward, and it might not even be necessary, given that MODULE is a declaration location and GWT needs annotation sources only for (some) type-use locations.)

@kevinb9n kevinb9n added the dev development tasks, build issues... label Nov 30, 2022
@cpovirk
Copy link
Collaborator Author

cpovirk commented Dec 16, 2022

Internal testing suggests that we're probably going to need to add MODULE to the GWT copy of ElementType. That doesn't sound like it would be hard. I'll try it "sometime."

But it's also possible that, when we generate the jar of GWT sources, we could just remove MODULE from the @Target line, too. Let's call that the fallback plan.

@cpovirk
Copy link
Collaborator Author

cpovirk commented Dec 29, 2022

But it's also possible that, when we generate the jar of GWT sources, we could just remove MODULE from the @Target line, too. Let's call that the fallback plan.

I was going to add "Or we could omit NullMarked.java from the GWT jar entirely, since GWT never needs annotation source for declaration annotations." But that wouldn't go well for Guava's j2cl users, who also use guava-gwt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dev development tasks, build issues...
Projects
None yet
Development

No branches or pull requests

4 participants