Skip to content

Commit

Permalink
Merge pull request quarkusio#24645 from gsmet/create-project-java-ver…
Browse files Browse the repository at this point in the history
…sion

Fix autodetection of Java version for project creation using CLI
  • Loading branch information
gsmet authored Mar 31, 2022
2 parents 46fd4d8 + be33427 commit 180fabf
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 180fabf

Please sign in to comment.