Skip to content

Commit

Permalink
Fix autodetection of Java version for project creation using CLI
Browse files Browse the repository at this point in the history
Also, make sure project created with Java 18 will use Java 17 and not
Java 11.
Finally, use autodetection for QuarkusJBangCodestartProjectInputBuilder
too.

Fixes quarkusio#24613
  • Loading branch information
gsmet committed Mar 30, 2022
1 parent 0de2c19 commit be33427
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package io.quarkus.cli.create;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import io.quarkus.cli.common.OutputOptionMixin;
import io.quarkus.devtools.project.BuildTool;
Expand All @@ -17,13 +17,13 @@ public class TargetLanguageGroup {

static class VersionCandidates extends ArrayList<String> {
VersionCandidates() {
super(List.copyOf(CreateProjectHelper.JAVA_VERSIONS_LTS));
super(CreateProjectHelper.JAVA_VERSIONS_LTS.stream().map(String::valueOf).collect(Collectors.toList()));
}
}

@CommandLine.Option(names = {
"--java" }, description = "Target Java version.\n Valid values: ${COMPLETION-CANDIDATES}", completionCandidates = VersionCandidates.class, defaultValue = CreateProjectHelper.DEFAULT_JAVA_VERSION)
String javaVersion = CreateProjectHelper.DEFAULT_JAVA_VERSION;
"--java" }, description = "Target Java version.\n Valid values: ${COMPLETION-CANDIDATES}", completionCandidates = VersionCandidates.class, defaultValue = CreateProjectHelper.DETECT_JAVA_RUNTIME_VERSION)
String javaVersion = CreateProjectHelper.DETECT_JAVA_RUNTIME_VERSION;

@CommandLine.Option(names = { "--kotlin" }, description = "Use Kotlin")
boolean kotlin = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ public boolean noJBangWrapper() {

public QuarkusJBangCodestartProjectInput build() {
if (!this.containsData("java")) {
this.addData(NestedMaps.unflatten(Map.of("java.version", CreateProjectHelper.DEFAULT_JAVA_VERSION)));
this.addData(NestedMaps
.unflatten(Map.of("java.version", String.valueOf(CreateProjectHelper.determineBestJavaLtsVersion()))));
}
return new QuarkusJBangCodestartProjectInput(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,25 @@
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.lang.model.SourceVersion;

public class CreateProjectHelper {

public static final Set<String> JAVA_VERSIONS_LTS = Set.of("11", "17");
public static final String DEFAULT_JAVA_VERSION = "11";
private static final Pattern JAVA_VERSION_PATTERN = Pattern.compile("(?:1\\.)?(\\d+)(?:\\..*)?");
// ordering is important here, so let's keep them ordered
public static final SortedSet<Integer> JAVA_VERSIONS_LTS = new TreeSet<>(List.of(11, 17));
private static final int DEFAULT_JAVA_VERSION = 11;
public static final String DETECT_JAVA_RUNTIME_VERSION = "<<detect java runtime version>>";
private static final Pattern JAVA_VERSION_PATTERN = Pattern.compile("(\\d+)(?:\\..*)?");

public static final String DEFAULT_GROUP_ID = "org.acme";
public static final String DEFAULT_ARTIFACT_ID = "code-with-quarkus";
Expand Down Expand Up @@ -79,16 +84,36 @@ public static SourceType determineSourceType(Set<String> extensions) {
public static void setJavaVersion(Map<String, Object> values, String javaTarget) {
requireNonNull(values, "Must provide values");

Matcher matcher = JAVA_VERSION_PATTERN
.matcher(javaTarget != null ? javaTarget : System.getProperty("java.version", ""));
Integer javaFeatureVersionTarget = null;

if (matcher.matches()) {
String versionExtracted = matcher.group(1);
String version = JAVA_VERSIONS_LTS.contains(versionExtracted) ? versionExtracted : DEFAULT_JAVA_VERSION;
values.put(ProjectGenerator.JAVA_TARGET, version);
} else {
values.put(ProjectGenerator.JAVA_TARGET, DEFAULT_JAVA_VERSION);
if (javaTarget != null && !DETECT_JAVA_RUNTIME_VERSION.equals(javaTarget)) {
// Probably too much as we should push only the feature version but let's be as thorough as we used to be
Matcher matcher = JAVA_VERSION_PATTERN.matcher(javaTarget);
if (matcher.matches()) {
javaFeatureVersionTarget = Integer.valueOf(matcher.group(1));
}
}

if (javaFeatureVersionTarget == null) {
javaFeatureVersionTarget = Runtime.version().feature();
}

values.put(ProjectGenerator.JAVA_TARGET, String.valueOf(determineBestJavaLtsVersion(javaFeatureVersionTarget)));
}

public static int determineBestJavaLtsVersion() {
return determineBestJavaLtsVersion(Runtime.version().feature());
}

public static int determineBestJavaLtsVersion(int runtimeVersion) {
int bestLtsVersion = DEFAULT_JAVA_VERSION;
for (int ltsVersion : JAVA_VERSIONS_LTS) {
if (ltsVersion > runtimeVersion) {
break;
}
bestLtsVersion = ltsVersion;
}
return bestLtsVersion;
}

public static Set<String> sanitizeExtensions(Set<String> extensions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class CreateProjectHelperTest {
@Test
public void givenJavaVersion17ShouldReturn17() {
Map<String, Object> values = new HashMap<>();
values.put("nonull", "nonull");
values.put("nonnull", "nonnull");

CreateProjectHelper.setJavaVersion(values, "17");
assertEquals("17", values.get("java_target"));
Expand All @@ -20,9 +20,46 @@ public void givenJavaVersion17ShouldReturn17() {
@Test
public void givenJavaVersion16ShouldReturn11() {
Map<String, Object> values = new HashMap<>();
values.put("nonull", "nonull");
values.put("nonnull", "nonnull");

CreateProjectHelper.setJavaVersion(values, "16.0.1");
assertEquals("11", values.get("java_target"));
}

@Test
public void givenJavaVersion11ShouldReturn11() {
Map<String, Object> values = new HashMap<>();
values.put("nonnull", "nonnull");

CreateProjectHelper.setJavaVersion(values, "11");
assertEquals("11", values.get("java_target"));
}

@Test
public void givenJavaVersion18ShouldReturn17() {
Map<String, Object> values = new HashMap<>();
values.put("nonnull", "nonnull");

CreateProjectHelper.setJavaVersion(values, "18");
assertEquals("17", values.get("java_target"));
}

@Test
public void givenAutoDetectShouldReturnAppropriateVersion() {
Map<String, Object> values = new HashMap<>();
values.put("nonnull", "nonnull");

CreateProjectHelper.setJavaVersion(values, CreateProjectHelper.DETECT_JAVA_RUNTIME_VERSION);
assertEquals(String.valueOf(CreateProjectHelper.determineBestJavaLtsVersion(Runtime.version().feature())),
values.get("java_target"));
}

@Test
public void testDetermineBestLtsVersion() {
assertEquals(11, CreateProjectHelper.determineBestJavaLtsVersion(8));
assertEquals(11, CreateProjectHelper.determineBestJavaLtsVersion(11));
assertEquals(11, CreateProjectHelper.determineBestJavaLtsVersion(12));
assertEquals(17, CreateProjectHelper.determineBestJavaLtsVersion(17));
assertEquals(17, CreateProjectHelper.determineBestJavaLtsVersion(18));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import static io.quarkus.devtools.testing.SnapshotTesting.assertThatDirectoryTreeMatchSnapshots;
import static io.quarkus.devtools.testing.SnapshotTesting.assertThatMatchSnapshot;

import io.quarkus.devtools.codestarts.utils.NestedMaps;
import io.quarkus.devtools.testing.SnapshotTesting;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
Expand All @@ -29,6 +31,9 @@ void generateDefaultProject(TestInfo testInfo) throws Throwable {
.putData(QUARKUS_BOM_GROUP_ID, "io.quarkus")
.putData(QUARKUS_BOM_ARTIFACT_ID, "quarkus-bom")
.putData(QUARKUS_BOM_VERSION, "999-MOCK")
// define the version here as it is now autodetecting the best LTS version at runtime
// and we want a static version for the snapshots
.addData(NestedMaps.unflatten(Map.of("java.version", "11")))
.build();
final Path projectDir = testDirPath.resolve("default");
getCatalog().createProject(input).generate(projectDir);
Expand All @@ -43,6 +48,9 @@ void generatePicocliProject(TestInfo testInfo) throws Throwable {
.putData(QUARKUS_BOM_GROUP_ID, "io.quarkus")
.putData(QUARKUS_BOM_ARTIFACT_ID, "quarkus-bom")
.putData(QUARKUS_BOM_VERSION, "999-MOCK")
// define the version here as it is now autodetecting the best LTS version at runtime
// and we want a static version for the snapshots
.addData(NestedMaps.unflatten(Map.of("java.version", "11")))
.build();
final Path projectDir = testDirPath.resolve("picocli");
getCatalog().createProject(input).generate(projectDir);
Expand Down

0 comments on commit be33427

Please sign in to comment.