diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22ff646a..478e2b5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,18 +7,18 @@ on: jobs: test: runs-on: ${{ matrix.os }} - name: Tests + name: Tests (JDK ${{ matrix.java }}) strategy: fail-fast: false matrix: # NOTE(olafurpg) Windows is not enabled because it times out due to reasons I don't understand. # os: [windows-latest, ubuntu-latest] os: [ubuntu-latest] - java: [8, 11, 17, 21] + java: [8, 11, 17, 21, 25] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: "temurin" cache: "sbt" @@ -26,13 +26,8 @@ jobs: - uses: sbt/setup-sbt@v1 - - name: Setup Gradle 8.10 - uses: gradle/actions/setup-gradle@v4 - with: - gradle-version: '8.10' - - name: Main project tests - run: sbt test + run: sbt test docker_test: runs-on: ${{ matrix.os }} @@ -42,9 +37,9 @@ jobs: matrix: os: [ubuntu-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v5 with: distribution: "temurin" cache: "sbt" @@ -76,7 +71,7 @@ jobs: bazel: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - run: yarn global add @bazel/bazelisk - run: bazel build //... --//semanticdb-javac:enabled=true - run: bazel run scip-semanticdb:bazel -- --sourceroot "$PWD" @@ -91,10 +86,10 @@ jobs: bazel_aspect: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - run: yarn global add @bazel/bazelisk - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v5 with: distribution: "temurin" cache: "sbt" @@ -133,18 +128,17 @@ jobs: - name: Run sample benchmarks run: sbt --client 'bench/Jmh/run -i 1 -f1 -t1 -foe true' - maven: runs-on: ubuntu-latest name: Maven tests strategy: fail-fast: false matrix: - java: [8, 11, 17, 21] + java: [8, 11, 17, 21, 25] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5 with: distribution: "temurin" cache: "sbt" @@ -172,4 +166,3 @@ jobs: - run: du -h index.scip working-directory: examples/maven-example - diff --git a/bin/docker-setup.sh b/bin/docker-setup.sh index 843f6103..1c2b84cb 100755 --- a/bin/docker-setup.sh +++ b/bin/docker-setup.sh @@ -1,21 +1,20 @@ #!/usr/bin/env bash set -eux -curl -fLo /usr/local/bin/coursier https://github.com/coursier/coursier/releases/download/v2.1.5/coursier +curl -fLo /usr/local/bin/coursier https://github.com/coursier/coursier/releases/download/v2.1.24/coursier chmod +x /usr/local/bin/coursier coursier setup --yes --apps coursier,sbt -curl -fLo maven.zip https://archive.apache.org/dist/maven/maven-3/3.9.1/binaries/apache-maven-3.9.1-bin.zip +curl -fLo maven.zip https://archive.apache.org/dist/maven/maven-3/3.9.12/binaries/apache-maven-3.9.12-bin.zip unzip -d /opt/maven maven.zip rm maven.zip mv /opt/maven/*/* /opt/maven -curl -fLo gradle.zip https://services.gradle.org/distributions/gradle-7.6.1-bin.zip -unzip -d /opt/gradle gradle.zip +curl -fLo gradle.zip https://services.gradle.org/distributions/gradle-9.2.1-bin.zip +unzip -d /opt/gradle gradle.zip rm gradle.zip mv /opt/gradle/*/* /opt/gradle # pre-install JDK for all major versions -for JVM_VERSION in 21 17 11 8 -do +for JVM_VERSION in 25 21 17 11 8; do coursier java --jvm $JVM_VERSION --jvm-index https://github.com/coursier/jvm-index/blob/master/index.json -- -version done diff --git a/scip-semanticdb/src/main/java/com/sourcegraph/scip_semanticdb/JavaVersion.java b/scip-semanticdb/src/main/java/com/sourcegraph/scip_semanticdb/JavaVersion.java index 9bedd24b..c18e903f 100644 --- a/scip-semanticdb/src/main/java/com/sourcegraph/scip_semanticdb/JavaVersion.java +++ b/scip-semanticdb/src/main/java/com/sourcegraph/scip_semanticdb/JavaVersion.java @@ -1,6 +1,5 @@ package com.sourcegraph.scip_semanticdb; -import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.FileSystems; @@ -11,18 +10,19 @@ import java.util.Optional; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.io.DataInputStream; public class JavaVersion { public final boolean isJava8; public final JdkPackage pkg; - private static final PathMatcher CLASS_PATTERN = - FileSystems.getDefault().getPathMatcher("glob:**.class"); - private static final PathMatcher JAR_PATTERN = - FileSystems.getDefault().getPathMatcher("glob:**.jar"); + private static final PathMatcher CLASS_PATTERN = FileSystems.getDefault().getPathMatcher("glob:**.class"); + private static final PathMatcher JAR_PATTERN = FileSystems.getDefault().getPathMatcher("glob:**.jar"); public static final int JAVA8_VERSION = 8; public static final int JAVA11_VERSION = 11; public static final int JAVA17_VERSION = 17; + public static final int JAVA21_VERSION = 21; + public static final int JAVA25_VERSION = 25; public static final int DEFAULT_JAVA_VERSION = JAVA8_VERSION; @SuppressWarnings("FieldCanBeLocal") @@ -38,28 +38,41 @@ public JavaVersion(String version) { } private String javaVersion(String version) { - if (version.startsWith("1.8")) return "8"; + if (version.startsWith("1.8")) + return "8"; String[] parts = version.split("\\."); - if (parts.length > 0) return parts[0]; - else return version; + if (parts.length > 0) + return parts[0]; + else + return version; } @SuppressWarnings("ManualMinMaxCalculation") public static int roundToNearestStableRelease(int version) { - if (version <= JAVA8_VERSION) return JAVA8_VERSION; - if (version <= JAVA11_VERSION) return JAVA11_VERSION; - if (version <= JAVA17_VERSION) return JAVA17_VERSION; + if (version <= JAVA8_VERSION) + return JAVA8_VERSION; + if (version <= JAVA11_VERSION) + return JAVA11_VERSION; + if (version <= JAVA17_VERSION) + return JAVA17_VERSION; + if (version <= JAVA21_VERSION) + return JAVA21_VERSION; + if (version <= JAVA25_VERSION) + return JAVA25_VERSION; return version; } /** * Return the JVM version of the given jar/class file. * - *

The JVM version is determined by reading the 5-8th bytes of classfiles, according to the + *

+ * The JVM version is determined by reading the 5-8th bytes of classfiles, + * according to the * Java Language spec. See * https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.1 * - * @return the JVM version such as 8 for Java 8 and 11 for Java 11. + * @return the JVM version such as 8 for Java 8 and 11 + * for Java 11. */ public static Optional classfileJvmVersion(Path file) { try { @@ -92,7 +105,8 @@ private static int classfileMajorVersion(InputStream classfileBytes) throws IOEx DataInputStream in = new DataInputStream(classfileBytes); // See https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.1 int magic = in.readInt(); // u4 magic - if (magic != 0xCAFEBABE) return -1; + if (magic != 0xCAFEBABE) + return -1; in.readUnsignedShort(); // u2 minor_version return in.readUnsignedShort(); // u2 major_version } diff --git a/tests/buildTools/src/test/resources/mill b/tests/buildTools/src/test/resources/mill index 62e5e186..136be4df 100644 --- a/tests/buildTools/src/test/resources/mill +++ b/tests/buildTools/src/test/resources/mill @@ -1,20 +1,46 @@ #!/usr/bin/env sh -# This is a wrapper script, that automatically download mill from GitHub release pages -# You can give the required mill version with --mill-version parameter -# If no version is given, it falls back to the value of DEFAULT_MILL_VERSION +# This is a wrapper script, that automatically selects or downloads Mill from Maven Central or GitHub release pages. # -# Project page: https://github.com/lefou/millw -# Script Version: 0.4.2 +# This script determines the Mill version to use by trying these sources +# - env-variable `MILL_VERSION` +# - local file `.mill-version` +# - local file `.config/mill-version` +# - `mill-version` from YAML frontmatter of current buildfile +# - if accessible, find the latest stable version available on Maven Central (https://repo1.maven.org/maven2) +# - env-variable `DEFAULT_MILL_VERSION` +# +# If a version has the suffix '-native' a native binary will be used. +# If a version has the suffix '-jvm' an executable jar file will be used, requiring an already installed Java runtime. +# If no such suffix is found, the script will pick a default based on version and platform. +# +# Once a version was determined, it tries to use either +# - a system-installed mill, if found and it's version matches +# - an already downloaded version under ~/.cache/mill/download +# +# If no working mill version was found on the system, +# this script downloads a binary file from Maven Central or Github Pages (this is version dependent) +# into a cache location (~/.cache/mill/download). +# +# Mill Project URL: https://github.com/com-lihaoyi/mill +# Script Version: 1.0.6 # # If you want to improve this script, please also contribute your changes back! +# This script was generated from: dist/scripts/src/mill.sh # # Licensed under the Apache License, Version 2.0 +set -e -DEFAULT_MILL_VERSION=0.10.0 +if [ -z "${DEFAULT_MILL_VERSION}" ] ; then + DEFAULT_MILL_VERSION="1.0.6" +fi + + +if [ -z "${GITHUB_RELEASE_CDN}" ] ; then + GITHUB_RELEASE_CDN="" +fi -set -e MILL_REPO_URL="https://github.com/com-lihaoyi/mill" @@ -24,16 +50,17 @@ fi # Explicit commandline argument takes precedence over all other methods if [ "$1" = "--mill-version" ] ; then - shift - if [ "x$1" != "x" ] ; then - MILL_VERSION="$1" - shift - else - echo "You specified --mill-version without a version." 1>&2 - echo "Please provide a version that matches one provided on" 1>&2 - echo "${MILL_REPO_URL}/releases" 1>&2 - false - fi + echo "The --mill-version option is no longer supported." 1>&2 +fi + +MILL_BUILD_SCRIPT="" + +if [ -f "build.mill" ] ; then + MILL_BUILD_SCRIPT="build.mill" +elif [ -f "build.mill.scala" ] ; then + MILL_BUILD_SCRIPT="build.mill.scala" +elif [ -f "build.sc" ] ; then + MILL_BUILD_SCRIPT="build.sc" fi # Please note, that if a MILL_VERSION is already set in the environment, @@ -42,21 +69,37 @@ fi # If not already set, read .mill-version file if [ -z "${MILL_VERSION}" ] ; then if [ -f ".mill-version" ] ; then - MILL_VERSION="$(head -n 1 .mill-version 2> /dev/null)" + MILL_VERSION="$(tr '\r' '\n' < .mill-version | head -n 1 2> /dev/null)" + elif [ -f ".config/mill-version" ] ; then + MILL_VERSION="$(tr '\r' '\n' < .config/mill-version | head -n 1 2> /dev/null)" + elif [ -n "${MILL_BUILD_SCRIPT}" ] ; then + # `s/.*://`: + # This is a greedy match that removes everything from the beginning of the line up to (and including) the last + # colon (:). This effectively isolates the value part of the declaration. + # + # `s/#.*//`: + # This removes any comments at the end of the line. + # + # `s/['\"]//g`: + # This removes all single and double quotes from the string, wherever they appear (g is for "global"). + # + # `s/^[[:space:]]*//; s/[[:space:]]*$//`: + # These two expressions trim any leading or trailing whitespace ([[:space:]] matches spaces and tabs). + MILL_VERSION="$(grep -E "//\|.*mill-version" "${MILL_BUILD_SCRIPT}" | sed -E "s/.*://; s/#.*//; s/['\"]//g; s/^[[:space:]]*//; s/[[:space:]]*$//")" fi fi -if [ -n "${XDG_CACHE_HOME}" ] ; then - MILL_DOWNLOAD_PATH="${XDG_CACHE_HOME}/mill/download" -else - MILL_DOWNLOAD_PATH="${HOME}/.cache/mill/download" +MILL_USER_CACHE_DIR="${XDG_CACHE_HOME:-${HOME}/.cache}/mill" + +if [ -z "${MILL_DOWNLOAD_PATH}" ] ; then + MILL_DOWNLOAD_PATH="${MILL_USER_CACHE_DIR}/download" fi # If not already set, try to fetch newest from Github if [ -z "${MILL_VERSION}" ] ; then # TODO: try to load latest version from release page echo "No mill version specified." 1>&2 - echo "You should provide a version via '.mill-version' file or --mill-version option." 1>&2 + echo "You should provide a version via a '//| mill-version: ' comment or a '.mill-version' file." 1>&2 mkdir -p "${MILL_DOWNLOAD_PATH}" LANG=C touch -d '1 hour ago' "${MILL_DOWNLOAD_PATH}/.expire_latest" 2>/dev/null || ( @@ -92,80 +135,205 @@ if [ -z "${MILL_VERSION}" ] ; then fi fi -MILL="${MILL_DOWNLOAD_PATH}/${MILL_VERSION}" +MILL_NATIVE_SUFFIX="-native" +MILL_JVM_SUFFIX="-jvm" +FULL_MILL_VERSION=$MILL_VERSION +ARTIFACT_SUFFIX="" +set_artifact_suffix(){ + if [ "$(expr substr $(uname -s) 1 5 2>/dev/null)" = "Linux" ]; then + if [ "$(uname -m)" = "aarch64" ]; then + ARTIFACT_SUFFIX="-native-linux-aarch64" + else + ARTIFACT_SUFFIX="-native-linux-amd64" + fi + elif [ "$(uname)" = "Darwin" ]; then + if [ "$(uname -m)" = "arm64" ]; then + ARTIFACT_SUFFIX="-native-mac-aarch64" + else + ARTIFACT_SUFFIX="-native-mac-amd64" + fi + else + echo "This native mill launcher supports only Linux and macOS." 1>&2 + exit 1 + fi +} + +case "$MILL_VERSION" in + *"$MILL_NATIVE_SUFFIX") + MILL_VERSION=${MILL_VERSION%"$MILL_NATIVE_SUFFIX"} + set_artifact_suffix + ;; + + *"$MILL_JVM_SUFFIX") + MILL_VERSION=${MILL_VERSION%"$MILL_JVM_SUFFIX"} + ;; + + *) + case "$MILL_VERSION" in + 0.1.*) ;; + 0.2.*) ;; + 0.3.*) ;; + 0.4.*) ;; + 0.5.*) ;; + 0.6.*) ;; + 0.7.*) ;; + 0.8.*) ;; + 0.9.*) ;; + 0.10.*) ;; + 0.11.*) ;; + 0.12.*) ;; + *) + set_artifact_suffix + esac + ;; +esac + +MILL="${MILL_DOWNLOAD_PATH}/$MILL_VERSION$ARTIFACT_SUFFIX" try_to_use_system_mill() { + if [ "$(uname)" != "Linux" ]; then + return 0 + fi + MILL_IN_PATH="$(command -v mill || true)" if [ -z "${MILL_IN_PATH}" ]; then - return + return 0 fi - UNIVERSAL_SCRIPT_MAGIC="@ 2>/dev/null # 2>nul & echo off & goto BOF" + SYSTEM_MILL_FIRST_TWO_BYTES=$(head --bytes=2 "${MILL_IN_PATH}") + if [ "${SYSTEM_MILL_FIRST_TWO_BYTES}" = "#!" ]; then + # MILL_IN_PATH is (very likely) a shell script and not the mill + # executable, ignore it. + return 0 + fi - if ! head -c 128 "${MILL_IN_PATH}" | grep -qF "${UNIVERSAL_SCRIPT_MAGIC}"; then - if [ -n "${MILLW_VERBOSE}" ]; then - echo "Could not determine mill version of ${MILL_IN_PATH}, as it does not start with the universal script magic2" 1>&2 - fi - return + SYSTEM_MILL_PATH=$(readlink -e "${MILL_IN_PATH}") + SYSTEM_MILL_SIZE=$(stat --format=%s "${SYSTEM_MILL_PATH}") + SYSTEM_MILL_MTIME=$(stat --format=%y "${SYSTEM_MILL_PATH}") + + if [ ! -d "${MILL_USER_CACHE_DIR}" ]; then + mkdir -p "${MILL_USER_CACHE_DIR}" fi - # Roughly the size of the universal script. - MILL_VERSION_SEARCH_RANGE="2403" - MILL_IN_PATH_VERSION=$(head -c "${MILL_VERSION_SEARCH_RANGE}" "${MILL_IN_PATH}" |\ - sed -n 's/^.*-DMILL_VERSION=\([^\s]*\) .*$/\1/p' |\ - head -n 1) + SYSTEM_MILL_INFO_FILE="${MILL_USER_CACHE_DIR}/system-mill-info" + if [ -f "${SYSTEM_MILL_INFO_FILE}" ]; then + parseSystemMillInfo() { + LINE_NUMBER="${1}" + # Select the line number of the SYSTEM_MILL_INFO_FILE, cut the + # variable definition in that line in two halves and return + # the value, and finally remove the quotes. + sed -n "${LINE_NUMBER}p" "${SYSTEM_MILL_INFO_FILE}" |\ + cut -d= -f2 |\ + sed 's/"\(.*\)"/\1/' + } - if [ -z "${MILL_IN_PATH_VERSION}" ]; then - echo "Could not determine mill version, even though ${MILL_IN_PATH} has the universal script magic" 1>&2 - return + CACHED_SYSTEM_MILL_PATH=$(parseSystemMillInfo 1) + CACHED_SYSTEM_MILL_VERSION=$(parseSystemMillInfo 2) + CACHED_SYSTEM_MILL_SIZE=$(parseSystemMillInfo 3) + CACHED_SYSTEM_MILL_MTIME=$(parseSystemMillInfo 4) + + if [ "${SYSTEM_MILL_PATH}" = "${CACHED_SYSTEM_MILL_PATH}" ] \ + && [ "${SYSTEM_MILL_SIZE}" = "${CACHED_SYSTEM_MILL_SIZE}" ] \ + && [ "${SYSTEM_MILL_MTIME}" = "${CACHED_SYSTEM_MILL_MTIME}" ]; then + if [ "${CACHED_SYSTEM_MILL_VERSION}" = "${MILL_VERSION}" ]; then + MILL="${SYSTEM_MILL_PATH}" + return 0 + else + return 0 + fi + fi fi - if [ "${MILL_IN_PATH_VERSION}" = "${MILL_VERSION}" ]; then - MILL="${MILL_IN_PATH}" + SYSTEM_MILL_VERSION=$(${SYSTEM_MILL_PATH} --version | head -n1 | sed -n 's/^Mill.*version \(.*\)/\1/p') + + cat < "${SYSTEM_MILL_INFO_FILE}" +CACHED_SYSTEM_MILL_PATH="${SYSTEM_MILL_PATH}" +CACHED_SYSTEM_MILL_VERSION="${SYSTEM_MILL_VERSION}" +CACHED_SYSTEM_MILL_SIZE="${SYSTEM_MILL_SIZE}" +CACHED_SYSTEM_MILL_MTIME="${SYSTEM_MILL_MTIME}" +EOF + + if [ "${SYSTEM_MILL_VERSION}" = "${MILL_VERSION}" ]; then + MILL="${SYSTEM_MILL_PATH}" fi } try_to_use_system_mill # If not already downloaded, download it -if [ ! -s "${MILL}" ] ; then +if [ ! -s "${MILL}" ] || [ "$MILL_TEST_DRY_RUN_LAUNCHER_SCRIPT" = "1" ] ; then + case $MILL_VERSION in + 0.0.* | 0.1.* | 0.2.* | 0.3.* | 0.4.* ) + DOWNLOAD_SUFFIX="" + DOWNLOAD_FROM_MAVEN=0 + ;; + 0.5.* | 0.6.* | 0.7.* | 0.8.* | 0.9.* | 0.10.* | 0.11.0-M* ) + DOWNLOAD_SUFFIX="-assembly" + DOWNLOAD_FROM_MAVEN=0 + ;; + *) + DOWNLOAD_SUFFIX="-assembly" + DOWNLOAD_FROM_MAVEN=1 + ;; + esac + case $MILL_VERSION in + 0.12.0 | 0.12.1 | 0.12.2 | 0.12.3 | 0.12.4 | 0.12.5 | 0.12.6 | 0.12.7 | 0.12.8 | 0.12.9 | 0.12.10 | 0.12.11 ) + DOWNLOAD_EXT="jar" + ;; + 0.12.* ) + DOWNLOAD_EXT="exe" + ;; + 0.* ) + DOWNLOAD_EXT="jar" + ;; + *) + DOWNLOAD_EXT="exe" + ;; + esac - # support old non-XDG download dir - MILL_OLD_DOWNLOAD_PATH="${HOME}/.mill/download" - OLD_MILL="${MILL_OLD_DOWNLOAD_PATH}/${MILL_VERSION}" - if [ -x "${OLD_MILL}" ] ; then - MILL="${OLD_MILL}" + DOWNLOAD_FILE=$(mktemp mill.XXXXXX) + if [ "$DOWNLOAD_FROM_MAVEN" = "1" ] ; then + DOWNLOAD_URL="https://repo1.maven.org/maven2/com/lihaoyi/mill-dist${ARTIFACT_SUFFIX}/${MILL_VERSION}/mill-dist${ARTIFACT_SUFFIX}-${MILL_VERSION}.${DOWNLOAD_EXT}" else - VERSION_PREFIX="$(echo $MILL_VERSION | cut -b -4)" - case $VERSION_PREFIX in - 0.0. | 0.1. | 0.2. | 0.3. | 0.4. ) - DOWNLOAD_SUFFIX="" - ;; - *) - DOWNLOAD_SUFFIX="-assembly" - ;; - esac - unset VERSION_PREFIX - - DOWNLOAD_FILE=$(mktemp mill.XXXXXX) - # TODO: handle command not found - echo "Downloading mill ${MILL_VERSION} from ${MILL_REPO_URL}/releases ..." 1>&2 - MILL_VERSION_TAG=$(echo $MILL_VERSION | sed -E 's/([^-]+)(-M[0-9]+)?(-.*)?/\1\2/') - ${CURL_CMD} -f -L -o "${DOWNLOAD_FILE}" "${MILL_REPO_URL}/releases/download/${MILL_VERSION_TAG}/${MILL_VERSION}${DOWNLOAD_SUFFIX}" - chmod +x "${DOWNLOAD_FILE}" - mkdir -p "${MILL_DOWNLOAD_PATH}" - mv "${DOWNLOAD_FILE}" "${MILL}" - - unset DOWNLOAD_FILE - unset DOWNLOAD_SUFFIX + MILL_VERSION_TAG=$(echo "$MILL_VERSION" | sed -E 's/([^-]+)(-M[0-9]+)?(-.*)?/\1\2/') + DOWNLOAD_URL="${GITHUB_RELEASE_CDN}${MILL_REPO_URL}/releases/download/${MILL_VERSION_TAG}/${MILL_VERSION}${DOWNLOAD_SUFFIX}" + unset MILL_VERSION_TAG + fi + + if [ "$MILL_TEST_DRY_RUN_LAUNCHER_SCRIPT" = "1" ] ; then + echo $DOWNLOAD_URL + echo $MILL + exit 0 fi + # TODO: handle command not found + echo "Downloading mill ${MILL_VERSION} from ${DOWNLOAD_URL} ..." 1>&2 + ${CURL_CMD} -f -L -o "${DOWNLOAD_FILE}" "${DOWNLOAD_URL}" + chmod +x "${DOWNLOAD_FILE}" + mkdir -p "${MILL_DOWNLOAD_PATH}" + mv "${DOWNLOAD_FILE}" "${MILL}" + + unset DOWNLOAD_FILE + unset DOWNLOAD_SUFFIX +fi + +if [ -z "$MILL_MAIN_CLI" ] ; then + MILL_MAIN_CLI="${0}" +fi + +MILL_FIRST_ARG="" +if [ "$1" = "--bsp" ] || [ "${1#"-i"}" != "$1" ] || [ "$1" = "--interactive" ] || [ "$1" = "--no-server" ] || [ "$1" = "--no-daemon" ] || [ "$1" = "--repl" ] || [ "$1" = "--help" ] ; then + # Need to preserve the first position of those listed options + MILL_FIRST_ARG=$1 + shift fi unset MILL_DOWNLOAD_PATH unset MILL_OLD_DOWNLOAD_PATH unset OLD_MILL unset MILL_VERSION -unset MILL_VERSION_TAG unset MILL_REPO_URL -exec "${MILL}" "$@" +# -D mill.main.cli is for compatibility with Mill 0.10.9 - 0.13.0-M2 +# We don't quote MILL_FIRST_ARG on purpose, so we can expand the empty value without quotes +# shellcheck disable=SC2086 +exec "${MILL}" $MILL_FIRST_ARG -D "mill.main.cli=${MILL_MAIN_CLI}" "$@" diff --git a/tests/buildTools/src/test/scala/tests/BaseBuildToolSuite.scala b/tests/buildTools/src/test/scala/tests/BaseBuildToolSuite.scala index 6d5f4bb5..b49e8ddf 100644 --- a/tests/buildTools/src/test/scala/tests/BaseBuildToolSuite.scala +++ b/tests/buildTools/src/test/scala/tests/BaseBuildToolSuite.scala @@ -19,6 +19,8 @@ import munit.TestOptions import os.Shellable object Java8Only extends munit.Tag("Java8Only") +case class JVMCompatibility(tools: List[Tool]) + extends munit.Tag("JVMCompatibility") abstract class BaseBuildToolSuite extends MopedSuite(ScipJava.app) { self => @@ -44,6 +46,26 @@ abstract class BaseBuildToolSuite extends MopedSuite(ScipJava.app) { t.tag(munit.Ignore) else t + ), + new TestTransform( + "JVMCompatibility", + t => + t.tags + .collectFirst { case JVMCompatibility(tools) => + tools + } + .map { tools => + val minJDK = Tool.minimumSupportedJdk(tools) + val maxJDK = Tool + .maximumSupportedJdk(tools) + .getOrElse(Int.MaxValue) + val javaVersion = BaseBuildToolSuite.externalJavaVersion + if (javaVersion < minJDK || javaVersion > maxJDK) + t.tag(munit.Ignore) + else + t + } + .getOrElse(t) ) ) @@ -79,28 +101,13 @@ abstract class BaseBuildToolSuite extends MopedSuite(ScipJava.app) { targetRoot: Option[String] = None, tools: List[Tool] = Nil ): Unit = { - val minJDK = Tool.minimumSupportedJdk(tools) - val maxJDK = Tool.maximumSupportedJdk(tools).getOrElse(Int.MaxValue) - val externalJDKVersion = BaseBuildToolSuite.externalJavaVersion - - val JDKSupported = - externalJDKVersion >= minJDK && externalJDKVersion <= maxJDK - - val ignoreMsg = - s"Test ${options - .name} was ignored because the external JDK version doesn't match the toolset requirements: " + - s"Tools: $tools, min JDK = $minJDK, max JDK = $maxJDK, detected JDK = $externalJDKVersion" - - test(options.withTags(options.tags ++ tags)) { - // Unfortunately, MUnit doesn't seem to handle the ignore messages the - // way we'd want: https://github.com/scalameta/munit/issues/549#issuecomment-2056751821 - // So instead, to give some indication that the test was actually ignored, - // we print this message - if (!JDKSupported) - System.err.println(ignoreMsg) - - assume(JDKSupported, ignoreMsg) + val testTags = + if (tools.nonEmpty) + options.tags ++ tags + JVMCompatibility(tools) + else + options.tags ++ tags + test(options.withTags(testTags)) { if (initCommand.nonEmpty) { os.proc(Shellable(initCommand)).call(os.Path(workingDirectory)) } diff --git a/tests/buildTools/src/test/scala/tests/GradleBuildToolSuite.scala b/tests/buildTools/src/test/scala/tests/GradleBuildToolSuite.scala index c17c1ee8..0423a817 100644 --- a/tests/buildTools/src/test/scala/tests/GradleBuildToolSuite.scala +++ b/tests/buildTools/src/test/scala/tests/GradleBuildToolSuite.scala @@ -2,12 +2,8 @@ package tests import tests.Tool._ +class Gradle_9_BuildToolSuite extends GradleBuildToolSuite(Gradle9) class Gradle_8_BuildToolSuite extends GradleBuildToolSuite(Gradle8) -class Gradle_7_BuildToolSuite extends GradleBuildToolSuite(Gradle7) -class Gradle_6_BuildToolSuite extends GradleBuildToolSuite(Gradle6) -class Gradle_5_BuildToolSuite extends GradleBuildToolSuite(Gradle5) -class Gradle_3_BuildToolSuite extends GradleBuildToolSuite(Gradle3) -class Gradle_2_BuildToolSuite extends GradleBuildToolSuite(Gradle2) abstract class GradleBuildToolSuite(gradle: Tool.Gradle) extends GradleBuildToolSuiteBase(gradle) { @@ -42,7 +38,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) - /META-INF/semanticdb/src/main/java/WorkflowOptions.java.semanticdb */ expectedSemanticdbFiles = 2, - gradleVersions = List(Gradle8, Gradle7, Gradle6) + gradleVersions = List(Gradle9, Gradle8) ) checkGradleBuild( @@ -74,7 +70,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) // See comment about immutable annotation processor above, // it explains why we expecte 2 semanticdb files expectedSemanticdbFiles = 2, - gradleVersions = List(Gradle8, Gradle7, Gradle6) + gradleVersions = List(Gradle9, Gradle8) ) checkGradleBuild( @@ -102,7 +98,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |public abstract class ExampleClass {} """.stripMargin, expectedSemanticdbFiles = 1, - gradleVersions = List(Gradle8, Gradle7, Gradle6), + gradleVersions = List(Gradle9, Gradle8), expectedPackages = "maven:com.sourcegraph:example-library:1.1" ) @@ -126,7 +122,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |dependencies { | // This dependency is used by the application. | implementation 'com.google.guava:guava:31.1-jre' - | implementation 'org.scala-lang:scala-library:2.13.8' + | implementation 'org.scala-lang:scala-library:2.13.18' | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' |} @@ -160,8 +156,8 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |""".stripMargin, expectedSemanticdbFiles = 3, // Only add this test on Gradle 5 in the gradle 6 suite - gradleVersions = List(Gradle8, Gradle7, Gradle6, Gradle5), - tools = List(Scala2_13_8) + gradleVersions = List(Gradle9, Gradle8), + tools = List(Scala2_13) ) allJava.foreach { java => @@ -181,7 +177,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |public class Example {} |""".stripMargin, expectedSemanticdbFiles = 1, - gradleVersions = List(Gradle8, Gradle7, Gradle6) + gradleVersions = List(Gradle9, Gradle8) ) } @@ -220,7 +216,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |public class Example {} |""".stripMargin, expectedSemanticdbFiles = 2, - gradleVersions = List(Gradle8, Gradle7, Gradle6) + gradleVersions = List(Gradle9, Gradle8) ) checkGradleBuild( @@ -236,7 +232,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |""".stripMargin, expectedSemanticdbFiles = 2, extraArguments = List("--build-tool", "gradle"), - gradleVersions = List(Gradle8, Gradle7, Gradle6) + gradleVersions = List(Gradle9, Gradle8) ) checkGradleBuild( @@ -250,7 +246,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |""".stripMargin, expectedSemanticdbFiles = 1, extraArguments = List("--", "compileJava"), - gradleVersions = List(Gradle8, Gradle7, Gradle6) + gradleVersions = List(Gradle9, Gradle8) ) checkGradleBuild( @@ -302,7 +298,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |""".stripMargin, expectedSemanticdbFiles = 2, // Two files because `conf/routes` generates a Java file. - gradleVersions = List(Gradle6) + gradleVersions = List(Gradle8) ) checkGradleBuild( @@ -328,7 +324,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |public class ExampleSuite {} |""".stripMargin, expectedSemanticdbFiles = 2, - gradleVersions = List(Gradle6) + gradleVersions = List(Gradle8) ) checkGradleBuild( @@ -341,7 +337,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) | mavenCentral() |} |dependencies { - | implementation 'org.scala-lang:scala-library:2.12.12' + | implementation 'org.scala-lang:scala-library:2.13.18' |} |/src/main/java/foo/JExample.java |package foo; @@ -357,8 +353,8 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |class ExampleSuite {} |""".stripMargin, expectedSemanticdbFiles = 4, - gradleVersions = List(Gradle8, Gradle7, Gradle6), - tools = List(Scala2_12_12) + gradleVersions = List(Gradle9, Gradle8), + tools = List(Scala2_13) ) checkGradleBuild( "kotlin2", @@ -429,7 +425,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |maven:org.jetbrains:annotations:13.0 |maven:org.slf4j:slf4j-api:1.7.36 |""".stripMargin, - gradleVersions = List(Gradle8, Gradle7, Gradle6) + gradleVersions = List(Gradle9, Gradle8) ) List("8", "11").foreach { java => @@ -507,7 +503,7 @@ abstract class GradleBuildToolSuite(gradle: Tool.Gradle) |public class ExampleSuite {} |""".stripMargin, expectedSemanticdbFiles = 2, - gradleVersions = List(Gradle3, Gradle2) + gradleVersions = List(Gradle9, Gradle8) // NOTE(olafur): no packages because we use more modern APIs. ) diff --git a/tests/buildTools/src/test/scala/tests/MillBuildToolSuite.scala b/tests/buildTools/src/test/scala/tests/MillBuildToolSuite.scala index 173af694..bef8a7f7 100644 --- a/tests/buildTools/src/test/scala/tests/MillBuildToolSuite.scala +++ b/tests/buildTools/src/test/scala/tests/MillBuildToolSuite.scala @@ -32,13 +32,11 @@ class MillBuildToolSuite extends BaseBuildToolSuite { def scalaLibrary(scalaVersion: String) = if (scalaVersion.startsWith("3")) List( - "maven:org.scala-lang:scala-library:2.13.12", - "maven:org.scala-lang:scala3-library_3:3.3.3" + "maven:org.scala-lang:scala-library:2.13.16", + s"maven:org.scala-lang:scala3-library_3:$scalaVersion" ).mkString("\n") else if (scalaVersion.startsWith("2.13")) - "maven:org.scala-lang:scala-library:2.13.8" - else if (scalaVersion.startsWith("2.12")) - "maven:org.scala-lang:scala-library:2.12.19" + s"maven:org.scala-lang:scala-library:$scalaVersion" else "idn fail, we don't cover this scala version" @@ -47,14 +45,12 @@ class MillBuildToolSuite extends BaseBuildToolSuite { "3" else if (scalaVersion.startsWith("2.13")) "2.13" - else if (scalaVersion.startsWith("2.12")) - "2.12" else "idn fail, we don't cover this scala version" for { - mill <- List(Mill0_10, Mill0_11) - scala <- List(Scala212, Scala2_13_8, Scala3) + mill <- List(Mill) + scala <- List(Scala2_13, Scala_LTS, Scala_Next) } yield { checkBuild( @@ -100,7 +96,7 @@ class MillBuildToolSuite extends BaseBuildToolSuite { checkBuild( "java-module", s"""|/.mill-version - |${Mill0_10.version} + |${Mill.version} |/build.sc |import mill._, scalalib._ |object minimal extends JavaModule @@ -115,15 +111,15 @@ class MillBuildToolSuite extends BaseBuildToolSuite { |} |""".stripMargin, expectedSemanticdbFiles = 1, - initCommand = setupMill(Mill0_10.version), + initCommand = setupMill(Mill.version), targetRoot = Some("out/io/kipp/mill/scip/Scip/generate.dest"), - tools = List(Mill0_10) + tools = List(Mill) ) checkBuild( "output", s"""|/.mill-version - |${Mill0_10.version} + |${Mill.version} |/build.sc |import mill._, scalalib._ |object minimal extends ScalaModule { @@ -134,9 +130,9 @@ class MillBuildToolSuite extends BaseBuildToolSuite { |@main def hello = () |""".stripMargin, expectedSemanticdbFiles = 1, - initCommand = setupMill(Mill0_10.version), + initCommand = setupMill(Mill.version), targetRoot = Some("out/io/kipp/mill/scip/Scip/generate.dest"), extraArguments = List("--output", "dump.scip"), - tools = List(Mill0_10) + tools = List(Mill) ) } diff --git a/tests/buildTools/src/test/scala/tests/SbtBuildToolSuite.scala b/tests/buildTools/src/test/scala/tests/SbtBuildToolSuite.scala index 45004272..7179b400 100644 --- a/tests/buildTools/src/test/scala/tests/SbtBuildToolSuite.scala +++ b/tests/buildTools/src/test/scala/tests/SbtBuildToolSuite.scala @@ -1,13 +1,13 @@ package tests -import tests.Tool.SBT15 +import tests.Tool.SBT112 abstract class SbtBuildToolSuite(sbt: Tool.SBT) extends BaseBuildToolSuite { import Tool._ for { - scala <- List(Scala211, Scala2_12_12, Scala2_13_8, Scala3) + scala <- List(Scala2_11, Scala2_13, Scala_LTS, Scala_Next) } yield { checkBuild( s"basic-${sbt.name}-${scala.name}", @@ -62,5 +62,4 @@ abstract class SbtBuildToolSuite(sbt: Tool.SBT) extends BaseBuildToolSuite { import Tool._ -class Sbt_15_BuildToolSuite extends SbtBuildToolSuite(SBT15) -class Sbt_110_BuildToolSuite extends SbtBuildToolSuite(SBT110) +class Sbt_112_BuildToolSuite extends SbtBuildToolSuite(SBT112) diff --git a/tests/buildTools/src/test/scala/tests/Tool.scala b/tests/buildTools/src/test/scala/tests/Tool.scala index ea5d219e..f2d62322 100644 --- a/tests/buildTools/src/test/scala/tests/Tool.scala +++ b/tests/buildTools/src/test/scala/tests/Tool.scala @@ -34,35 +34,29 @@ object Tool { tools.flatMap(_.support.maxJava).minOption // See https://docs.gradle.org/current/userguide/compatibility.html + // See https://endoflife.date/gradle for versions with active support sealed abstract class Gradle(version: String, support: JVMSupport) extends Tool("gradle", version, support) - case object Gradle8 extends Gradle("8.7", atMostJava(21)) - case object Gradle7 extends Gradle("7.6.3", atMostJava(17)) - case object Gradle6 extends Gradle("6.8.3", atMostJava(11)) - case object Gradle5 extends Gradle("5.6.4", atMostJava(11)) - case object Gradle3 extends Gradle("3.3", atMostJava(8)) - case object Gradle2 extends Gradle("2.14.1", atMostJava(8)) + case object Gradle9 extends Gradle("9.2.1", javaBetween(17, 25)) + case object Gradle8 extends Gradle("8.14.3", javaBetween(8, 24)) sealed abstract class SBT(version: String, support: JVMSupport) extends Tool("sbt", version, support) // See https://docs.scala-lang.org/overviews/jdk-compatibility/overview.html#build-tool-compatibility-table - case object SBT15 extends SBT("1.5.2", atMostJava(17)) - case object SBT110 extends SBT("1.10.0", noRestrictions) + case object SBT112 extends SBT("1.11.7", noRestrictions) sealed abstract class Scala(version: String, support: JVMSupport) extends Tool("scala", version, support) // See https://docs.scala-lang.org/overviews/jdk-compatibility/overview.html - case object Scala213 extends Scala("2.13.13", noRestrictions) - case object Scala212 extends Scala("2.12.19", noRestrictions) - case object Scala2_12_12 extends Scala("2.12.12", atMostJava(11)) - case object Scala2_13_8 extends Scala("2.13.8", atMostJava(17)) - case object Scala211 extends Scala("2.11.9", atMostJava(11)) - case object Scala3 extends Scala("3.3.3", noRestrictions) + case object Scala_Next extends Scala("3.7.4", noRestrictions) + case object Scala_LTS extends Scala("3.3.7", noRestrictions) + case object Scala2_13 extends Scala("2.13.18", noRestrictions) + case object Scala2_11 extends Scala("2.11.12", noRestrictions) + case object Scala2_10 extends Scala("2.10.7", noRestrictions) sealed abstract class Mill(version: String, support: JVMSupport) extends Tool("mill", version, support) // See https://docs.scala-lang.org/overviews/jdk-compatibility/overview.html#build-tool-compatibility-table - case object Mill0_10 extends Mill("0.10.6", atMostJava(17)) - case object Mill0_11 extends Mill("0.11.5", noRestrictions) + case object Mill extends Mill("1.0.6", noRestrictions) }