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

baseline-java-versions allows opting in to --enable-preview #2322

Merged
merged 20 commits into from
Jul 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ version: 2.1
jobs:

check:
docker: [{ image: 'cimg/openjdk:11.0.10-node' }]
docker: [{ image: 'cimg/openjdk:17.0.1-node' }]
resource_class: large
environment:
CIRCLE_TEST_REPORTS: /home/circleci/junit
Expand Down Expand Up @@ -58,7 +58,7 @@ jobs:
- store_artifacts: { path: ~/artifacts }

trial-publish:
docker: [{ image: 'cimg/openjdk:11.0.10-node' }]
docker: [{ image: 'cimg/openjdk:17.0.1-node' }]
resource_class: medium
environment:
CIRCLE_TEST_REPORTS: /home/circleci/junit
Expand Down Expand Up @@ -104,7 +104,7 @@ jobs:
- store_artifacts: { path: ~/artifacts }

publish:
docker: [{ image: 'cimg/openjdk:11.0.10-node' }]
docker: [{ image: 'cimg/openjdk:17.0.1-node' }]
resource_class: medium
environment:
CIRCLE_TEST_REPORTS: /home/circleci/junit
Expand Down
2 changes: 1 addition & 1 deletion .circleci/template.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
export CIRCLECI_TEMPLATE=java-library-oss
export JDK=11
export JDK=17
67 changes: 33 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,40 +416,6 @@ This plugin adds the `-Aimmutables.gradle.incremental` compiler arg to the compi

For more details, see the Immutables incremental compilation [tracking issue](https://github.com/immutables/immutables/issues/804).

## com.palantir.baseline-enable-preview-flag (off by default)

As described in [JEP 12](https://openjdk.java.net/jeps/12), Java allows you to use shiny new syntax features if you add
the `--enable-preview` flag. However, gradle requires you to add it in multiple places. This plugin can be applied to
within an allprojects block and it will automatically ugprade any project which is already using the latest
sourceCompatibility by adding the necessary `--enable-preview` flags to all of the following task types.

_Note, this plugin should be used with **caution** because preview features may change or be removed, and it
is undesirable to deeply couple a repo to a particular Java version as it makes upgrading to a new major Java version harder._

```gradle
// root build.gradle
allprojects {
apply plugin: 'com.palantir.baseline-enable-preview-flag'
}
```

```gradle
// shorthand for the below:
tasks.withType(JavaCompile) {
options.compilerArgs += "--enable-preview"
}
tasks.withType(Test) {
jvmArgs += "--enable-preview"
}
tasks.withType(JavaExec) {
jvmArgs += "--enable-preview"
}
```

If you've explicitly specified a lower sourceCompatibility (e.g. for a published API jar), then this plugin is a no-op.
In fact, Java will actually error if you try to switch on the `--enable-preview` flag to get cutting edge syntax
features but set `sourceCompatibility` (or `--release`) to an older Java version.

## com.palantir.baseline-java-versions

This plugin allows consistent configuration of JDK versions via [Gradle Toolchains](https://docs.gradle.org/current/userguide/toolchains.html).
Expand Down Expand Up @@ -482,3 +448,36 @@ javaVersion {
```

The optionally configurable fields of the `javaVersion` extension are `target`, for setting the target version used for compilation and `runtime`, for setting the runtime version used for testing and distributions.

### Opting in to `--enable-preview` flag

As described in [JEP 12](https://openjdk.java.net/jeps/12), Java allows you to use incubating syntax features if you add the `--enable-preview` flag. Gradle requires you to add it in many places (including on JavaCompile, Javadoc tasks, as well as in production and on execution tasks like Test, JavaExec). The baseline-java-versions plugin provides a shorthand way of enabling this:

```gradle
// root build.gradle
apply plugin: 'com.palantir.baseline-java-versions'
javaVersions {
libraryTarget = 11
distributionTarget = '17_PREVIEW'
runtime = '17_PREVIEW'
}

// shorthand for configuring all the tasks individually, e.g.
tasks.withType(JavaCompile) {
options.compilerArgs += "--enable-preview"
}
tasks.withType(Test) {
jvmArgs += "--enable-preview"
}
tasks.withType(JavaExec) {
jvmArgs += "--enable-preview"
}
```

In the example above, the `Baseline-Enable-Preview: 17` attribute will be embedded in the resultant Jar's `META-INF/MANIFEST.MF` file. To see for yourself, run:

```
$ unzip -p /path/to/your-project-1.2.3.jar META-INF/MANIFEST.MF
```

_Note, this plugin should be used with **caution** because preview features may change or be removed, which might make upgrading to a new Java version harder._
7 changes: 7 additions & 0 deletions changelog/@unreleased/pr-2322.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type: feature
feature:
description: Users of the `com.palantir.baseline-java-versions` plugin can now set
`javaVersions { distributionTarget = '17_PREVIEW' }` to opt-in to Java's `--enable-preview`
flag at compile time.
links:
- https://github.com/palantir/gradle-baseline/pull/2322
5 changes: 0 additions & 5 deletions gradle-baseline-java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,6 @@ gradlePlugin {
displayName = 'Palantir Baseline Release Compatibility Plugin'
implementationClass = 'com.palantir.baseline.plugins.BaselineReleaseCompatibility'
}
baselineEnablePreviewFlag {
id = 'com.palantir.baseline-enable-preview-flag'
displayName = 'Palantir Baseline --enable-preview Flag Plugin'
implementationClass = 'com.palantir.baseline.plugins.BaselineEnablePreviewFlag'
}
baselinePreferProjectModules {
id = 'com.palantir.baseline-prefer-project-modules'
displayName = 'Palantir Baseline Prefer Project Modules Plugin'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@
package com.palantir.baseline.extensions;

import com.google.common.collect.ImmutableSet;
import java.util.Optional;
import java.util.Set;
import javax.inject.Inject;
import org.gradle.api.Project;
import org.gradle.api.provider.Provider;
import org.gradle.api.provider.SetProperty;
import org.gradle.jvm.toolchain.JavaLanguageVersion;

/**
* Extension to configure {@code --add-exports [VALUE]=ALL-UNNAMED} for the current module.
Expand All @@ -28,11 +32,13 @@ public class BaselineModuleJvmArgsExtension {

private final SetProperty<String> exports;
private final SetProperty<String> opens;
private final SetProperty<JavaLanguageVersion> enablePreview; // stores a singleton version or the empty set

@Inject
public BaselineModuleJvmArgsExtension(Project project) {
exports = project.getObjects().setProperty(String.class);
opens = project.getObjects().setProperty(String.class);
enablePreview = project.getObjects().setProperty(JavaLanguageVersion.class);
}

/**
Expand Down Expand Up @@ -71,6 +77,14 @@ public final void setOpens(String... input) {
opens.set(immutableDeduplicatedCopy);
}

public final void setEnablePreview(Provider<Optional<JavaLanguageVersion>> provider) {
enablePreview.set(provider.map(maybeValue -> maybeValue.map(Set::of).orElseGet(Set::of)));
}

public final Provider<Set<JavaLanguageVersion>> getEnablePreview() {
return enablePreview;
}

private static void validateModulePackagePair(String moduleAndPackage) {
if (moduleAndPackage.contains("=")) {
throw new IllegalArgumentException(String.format(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,10 @@ import com.google.common.collect.ImmutableMap
import com.palantir.baseline.IntellijSupport
import com.palantir.baseline.plugins.javaversions.BaselineJavaVersionExtension
import com.palantir.baseline.plugins.javaversions.BaselineJavaVersionsExtension
import com.palantir.baseline.plugins.javaversions.ChosenJavaVersion
import com.palantir.baseline.util.GitUtils
import groovy.transform.CompileStatic
import groovy.xml.XmlUtil
import org.gradle.api.JavaVersion
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.plugins.ide.idea.model.IdeaLanguageLevel

import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
Expand All @@ -39,6 +36,7 @@ import org.gradle.api.file.FileTreeElement
import org.gradle.api.plugins.quality.CheckstyleExtension
import org.gradle.api.specs.Spec
import org.gradle.api.tasks.util.PatternFilterable
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.plugins.ide.idea.GenerateIdeaModule
import org.gradle.plugins.ide.idea.GenerateIdeaProject
import org.gradle.plugins.ide.idea.GenerateIdeaWorkspace
Expand Down Expand Up @@ -210,7 +208,7 @@ class BaselineIdea extends AbstractBaselinePlugin {
bytecodeTargetLevel.attributes().put("target", defaultBytecodeVersion.toString())
project.allprojects.forEach({ project ->
BaselineJavaVersionExtension version = project.getExtensions().findByType(BaselineJavaVersionExtension.class)
if (version != null && version.target().get().asInt() != defaultBytecodeVersion.asInt()) {
if (version != null && version.target().get().javaLanguageVersion().asInt() != defaultBytecodeVersion.asInt()) {
bytecodeTargetLevel.appendNode("module", ImmutableMap.of(
"name", project.getName(),
"target", version.target().get().toString()))
Expand All @@ -220,22 +218,21 @@ class BaselineIdea extends AbstractBaselinePlugin {

private void updateProjectRootManager(Node node, BaselineJavaVersionsExtension versions) {
Node projectRootManager = node.component.find { it.'@name' == 'ProjectRootManager' }
int featureRelease = versions.distributionTarget().get().asInt()
JavaVersion javaVersion = JavaVersion.toVersion(featureRelease)
ChosenJavaVersion chosenJavaVersion = versions.distributionTarget().get()
int featureRelease = chosenJavaVersion.javaLanguageVersion().asInt()
projectRootManager.attributes().put("project-jdk-name", featureRelease)
projectRootManager.attributes().put("languageLevel", new IdeaLanguageLevel(javaVersion).getLevel())
projectRootManager.attributes().put("languageLevel", chosenJavaVersion.asIdeaLanguageLevel())
}

private static void updateModuleLanguageVersion(IdeaModel ideaModel, Project currentProject) {
ideaModel.module.iml.withXml { XmlProvider provider ->
// Extension must be checked lazily within the transformer
BaselineJavaVersionExtension version = currentProject.extensions.findByType(BaselineJavaVersionExtension.class)
if (version != null) {
int featureRelease = version.target().get().asInt()
JavaVersion javaVersion = JavaVersion.toVersion(featureRelease)
BaselineJavaVersionExtension versionExtension = currentProject.extensions.findByType(BaselineJavaVersionExtension.class)
if (versionExtension != null) {
ChosenJavaVersion chosenJavaVersion = versionExtension.target().get()
Node node = provider.asNode()
Node newModuleRootManager = node.component.find { it.'@name' == 'NewModuleRootManager' }
newModuleRootManager.attributes().put("LANGUAGE_LEVEL", new IdeaLanguageLevel(javaVersion).getLevel())
newModuleRootManager.attributes().put("LANGUAGE_LEVEL", chosenJavaVersion.asIdeaLanguageLevel())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a crucial change for Intellij usability - previously it would say something like JDK_17, but now it knows how to say JDK_17_PREVIEW.

I found this by committing all my intellij-related generated files (which are normally gitignored),

then writing some new code:

image

then hitting the button
image

then seeing what changed in my git diff:

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you probably want to delete this module and ban running ./gradlew idea just like gradle/gradle does. There's too many things that go wrong when you're not using gradle integration in intellij these days

Copy link
Contributor Author

@iamdanfox iamdanfox Jul 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robert3005 I agree the open *.ipr thing seems to have got more fragile (I haven't personally used it in a while)... but with this PR I was specifically trying to make the IntelliJ gradle integration work out of the box!

When I accepted IntelliJ's prompt to enable preview, it added two lines of seemingly non-functional gradle!!

image

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the JavaVersion class... I don't understand how the JavaVersion.VERSION_17_PREVIEW thing is supposed to work!

}
}
}
Expand Down
Loading